From 5b6a5206df6b163113c8f71690cd1ecb020981e0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 20 Feb 2018 20:16:30 +0100 Subject: [PATCH] add: 'script run lf_bulk' - the original script is call lf_buld_program but thats a too long name, with adaptations in code. chg: some script textual output --- client/scripts/calc_di.lua | 1 + client/scripts/calc_ev1_it.lua | 1 + client/scripts/calc_mizip.lua | 1 + client/scripts/calypso.lua | 4 + client/scripts/dumptoemul-mfu.lua | 3 + client/scripts/lf_bulk.lua | 193 ++++++++++++++++++++++++++++++ 6 files changed, 203 insertions(+) create mode 100644 client/scripts/lf_bulk.lua diff --git a/client/scripts/calc_di.lua b/client/scripts/calc_di.lua index fc14b7040..b46d45b51 100644 --- a/client/scripts/calc_di.lua +++ b/client/scripts/calc_di.lua @@ -53,6 +53,7 @@ end -- Usage help local function help() print(copyright) + print(author) print(version) print(desc) print('Example usage') diff --git a/client/scripts/calc_ev1_it.lua b/client/scripts/calc_ev1_it.lua index 9d2ccbe3f..e170e9106 100644 --- a/client/scripts/calc_ev1_it.lua +++ b/client/scripts/calc_ev1_it.lua @@ -52,6 +52,7 @@ end -- Usage help local function help() print(copyright) + print(author) print(version) print(desc) print("Example usage") diff --git a/client/scripts/calc_mizip.lua b/client/scripts/calc_mizip.lua index 374eec9ea..4500c9c0f 100644 --- a/client/scripts/calc_mizip.lua +++ b/client/scripts/calc_mizip.lua @@ -57,6 +57,7 @@ end -- Usage help local function help() print(copyright) + print(author) print(version) print(desc) print("Example usage") diff --git a/client/scripts/calypso.lua b/client/scripts/calypso.lua index 281ea9444..ad74c8183 100644 --- a/client/scripts/calypso.lua +++ b/client/scripts/calypso.lua @@ -211,6 +211,10 @@ local _calypso_cmds = { -- The main entry point function main(args) + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() + local data, apdu, flags, uid, cid, result, err, card -- Read the parameters for o, a in getopt.getopt(args, 'h') do diff --git a/client/scripts/dumptoemul-mfu.lua b/client/scripts/dumptoemul-mfu.lua index b308c79e5..bb04008e9 100644 --- a/client/scripts/dumptoemul-mfu.lua +++ b/client/scripts/dumptoemul-mfu.lua @@ -2,6 +2,9 @@ -- Have a look there for further details getopt = require('getopt') bin = require('bin') + +copyright = '' +version = '' example = "script run dumptoemul-mfu -i dumpdata-foobar.bin" author = "Martin Holst Swende \n @Marshmellow \n @iceman" usage = "script run dumptoemul-mfu [-i ] [-o ]" diff --git a/client/scripts/lf_bulk.lua b/client/scripts/lf_bulk.lua new file mode 100644 index 000000000..8e6f2e112 --- /dev/null +++ b/client/scripts/lf_bulk.lua @@ -0,0 +1,193 @@ +-- +-- lf_bulk.lua - A tool to clone a large number of tags at once. +-- Updated 2017-04-18 +-- Updated 2018-02-20 iceman +local getopt = require('getopt') + +copyright = '' +author = "Brian Redbeard" +version = 'v1.0.0' +desc = [[ +Perform bulk enrollment of 26 bit H10301 style RFID Tags +For more info, check the comments in the code +]] +example = [[ + -- + script run lf_bulk.lua -f 1 -b 1000 -c 10 +]] +usage = [[ +script run lf_bulk.lua -f facility -b base_id_num -c count + +Arguments: + -h : this help + -f : facility id + -b : starting card id + -c : count, number of cards to make +]] +local DEBUG = true +--local bxor = bit32.bxor +local bor = bit32.bor +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) + return nil,err +end +--- +-- Usage help +local function help() + print(copyright) + print(author) + print(version) + print(desc) + print('Example usage') + print(example) +end +--- +-- Exit message +local function exitMsg(msg) + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() +end +--[[Implement a function to simply visualize the bitstream in a text format +--This is especially helpful for troubleshooting bitwise math issues]]-- +function toBits(num,bits) + -- returns a table of bits, most significant first. + bits = bits or math.max(1, select(2, math.frexp(num))) + local t = {} -- will contain the bits + for b = bits, 1, -1 do + t[b] = math.fmod(num, 2) + num = math.floor((num - t[b]) / 2) + end + return table.concat(t) +end + +--[[ + Likely, I'm an idiot, but I couldn't find any parity functions in Lua + This can also be done with a combination of bitwise operations (in fact, + is the canonically "correct" way to do it, but my brain doesn't just + default to this and so counting some ones is good enough for me +]]-- +local function evenparity(s) + local _, count = string.gsub(s, "1", "") + local p = count % 2 + if (p == 0) then + return false + else + return true + end +end + +local function isempty(s) + return s == nil or s == '' +end + +--[[ + The Proxmark3 "clone" functions expect the data to be in hex format so + take the card id number and facility ID as arguments and construct the + hex. This should be easy enough to extend to non 26bit formats +]]-- +local function cardHex(i, f) + fac = lshift(f, 16) + id = bor(i, fac) + stream = toBits(id, 26) + + --As the function defaults to even parity and returns a boolean, + --perform a 'not' function to get odd parity + high = not evenparity(string.sub(stream, 0, 12)) and 1 or 0 + low = evenparity(string.sub(stream, 13)) and 1 or 0 + bits = bor( lshift(id, 1), low) + bits = bor( bits, lshift(high, 25)) + + --Since the lua library bit32 is (obviously) 32 bits and we need to + --encode 36 bits to properly do a 26 bit tag with the preamble we need + --to create a higher order and lower order component which we will + --then assemble in the return. The math above defines the proper + --encoding as per HID/Weigand/etc. These bit flips are due to the + --format length check on bit 38 (cmdlfhid.c:64) and + --bit 31 (cmdlfhid.c:66). + preamble = bor(0, lshift(1, 5)) + bits = bor(bits, lshift(1, 26)) + + return ("%04x%08x"):format(preamble, bits) +end +--- +-- main +local function main(args) + + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() + + if #args == 0 then return help() end + + --I really wish a better getopt function would be brought in supporting + --long arguments, but it seems this library was chosen for BSD style + --compatibility + for o, a in getopt.getopt(args, 'f:b:c:h') do + if o == 'h' then return help() end + if o == 'f' then + if isempty(a) then + print("You did not supply a facility code, using 0") + facility = 0 + else + facility = a + end + end + if o == 'b' then + if isempty(a) then return oops("You must supply the flag -b (base id)") end + baseid = a + end + if o == 'c' then + if isempty(a) then return oops("You must supply the flag -c (count)") end + count = a + end + end + + --Due to my earlier complaints about how this specific getopt library + --works, specifying ":" does not enforce supplying a value, thus we + --need to do these checks all over again. + if isempty(baseid) then return oops("You must supply the flag -b (base id)") end + if isempty(count) then return oops("You must supply the flag -c (count)") end + + --If the facility ID is non specified, ensure we code it as zero + if isempty(facility) then + print("Using 0 for the facility code as -f was not supplied") + facility = 0 + end + + --The next baseid + count function presents a logic/UX conflict + --where users specifying -c 1 (count = 1) would try to program two + --tags. This makes it so that -c 0 & -c 1 both code one tag, and all + --other values encode the expected amount. + if tonumber(count) > 0 then count = count - 1 end + + endid = baseid + count + + for cardnum = baseid, endid do + local card = cardHex(cardnum, facility) + print("Press enter to program card "..cardnum..":"..facility.." (hex: "..card..")") + --This would be better with "press any key", but we'll take what we can get. + io.read() + core.console( ('lf hid clone %s'):format(card) ) + end +end + +main(args) \ No newline at end of file