1 -- The getopt-functionality is loaded from pm3/getopt.lua
2 -- Have a look there for further details
3 getopt
= require('getopt')
5 local ansicolors
= require('ansicolors')
8 author
= "Martin Holst Swende \n @Marshmellow \n @iceman"
11 This script takes a dumpfile from 'hf mfu dump' and converts it to a format that can be used
15 script run data_mfu_bin2eml -i dumpdata-foobar.bin
18 script run data_mfu_bin2eml [-i <file>] [-o <file>]
22 -i <file> Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used
23 -o <filename> Specifies the output file. If omitted, <uid>.eml is used.
30 -- A debug printout-function
31 local function dbg(args
)
32 if not DEBUG
then return end
33 if type(args
) == 'table' then
44 -- This is only meant to be used when errors occur
45 local function oops(err
)
46 print('[!!] ERROR:', err
)
47 core
.clearCommandBuffer()
57 print(ansicolors
.cyan
..'Usage'..ansicolors
.reset
)
59 print(ansicolors
.cyan
..'Arguments'..ansicolors
.reset
)
61 print(ansicolors
.cyan
..'Example usage'..ansicolors
.reset
)
65 local function convert_to_ascii(hexdata
)
66 if string.len(hexdata
) % 8 ~= 0 then
67 return oops(("Bad data, length should be a multiple of 8 (was %d)"):format(string.len(hexdata
)))
71 for i
= 1, string.len(hexdata
),8 do
72 js
= js
.."'" ..string.sub(hexdata
,i
,i
+7).."',\n"
78 local function readdump(infile
)
79 t
= infile
:read('*all')
81 local len
,hex
= bin
.unpack(('H%d'):format(len
),t
)
85 local function convert_to_emulform(hexdata
)
86 if string.len(hexdata
) % 8 ~= 0 then
87 return oops(('Bad data, length should be a multiple of 8 (was %d)'):format(string.len(hexdata
)))
90 for i
= 1, string.len(hexdata
), 8 do
91 ascii
= ascii
..string.sub(hexdata
, i
, i
+7)..'\n'
93 return string.sub(ascii
, 1, -2)
96 local function main(args
)
98 local input
= 'dumpdata.bin'
101 for o
, a
in getopt
.getopt(args
, 'i:o:h') do
102 if o
== 'h' then return help() end
103 if o
== 'i' then input
= a
end
104 if o
== 'o' then output
= a
end
106 -- Validate the parameters
108 local infile
= io
.open(input
, 'rb')
109 if infile
== nil then
110 return oops('Could not read file ', input
)
112 local dumpdata
= readdump(infile
)
113 -- The hex-data is now in ascii-format,
115 -- But first, check the uid
116 -- lua uses start index and endindex, not count.
117 -- UID is 3three skip bcc0 then 4bytes.
118 -- 1 lua is one-index.
119 -- 1 + 112 (56*2) new dump format has version/signature/counter data here
120 -- 113,114,115,116,117,118 UID first three bytes
122 -- 121--- UID last four bytes
123 local uid
= string.sub(dumpdata
, 113, 113+5)..string.sub(dumpdata
, 113+8, 113+8+7)
124 output
= output
or (uid
.. '.eml')
126 -- Format some linebreaks
127 dumpdata
= convert_to_emulform(dumpdata
)
129 local outfile
= io
.open(output
, 'w')
130 if outfile
== nil then
131 return oops('Could not write to file ', output
)
134 outfile
:write(dumpdata
:lower())
136 print(('[+] Wrote an emulator-dump to the file %s'):format(output
))
140 In the future, we may implement so that scripts are invoked directly
141 into a 'main' function, instead of being executed blindly. For future
142 compatibility, I have done so, but I invoke my main from here.