text
[RRG-proxmark3.git] / client / luascripts / lf_electra.lua
blob5b0886aa4a83f7542fdac03d5db86bd6aa298171
1 local getopt = require('getopt')
2 local utils = require('utils')
3 local ac = require('ansicolors')
4 local os = require('os')
5 local count = 0
6 line = '-------------------------------------------------------------------------'
7 mod = " ELECTRA or EM410x fob cloning SCRIPT "
8 version = " v1.1.17 02/09/2023 made by jareckib "
9 desc = [[
11 Cloning new ELECTRA tags or EM410x to T5577 tag. This script changes
12 block 0. Additional data is written to block 3 and 4. The last
13 ELECTRA ID can be accessed through the option ---> "-c". For copy
14 directly from the original ELECTRA tag, ---> option "-e". For copy
15 from input, EM410X ID ---> option "-s". Next option for cloning simple
16 EM4102 ---> option "-m". If press <Enter> it, which writes an ID.
17 If press <n> ---> exit the script.
19 example = [[
20 -------------------------------------------------------------------------------
22 --------------- cloning ELECTRA tag from input ID to T5577 tag ----------------
24 script run lf_electra -s 11AA22BB55
26 ----------------- continue cloning from last cloned ELECTRA -------------------
28 script run lf_electra -c
30 ---------------------- ELECTRA cloning from the original TAG -----------------
32 script run lf_electra -e
34 ----------------------------- simple EM4102 cloning ---------------------------
36 script run lf_electra -m
38 -------------------------------------------------------------------------------
40 usage = [[
41 script run lf_electra.lua [-e] [-h] [-c] [-m] [-s <ID HEX number>]
43 arguments = [[
44 -h : this help
45 -c : continue cloning from last ID used
46 -s : ELECTRA - EM410x ID HEX number
47 -e : Read original ELECTRA from Proxmark3 device
48 -m : EM410x cloning
50 --------------------------------------Path to logs files
51 local DEBUG = false
52 local dir = os.getenv('HOME')..'/.proxmark3/logs/'
53 local LAST_ID = os.getenv('HOME')..'/.proxmark3/logs/last_id.txt'
54 local ID_STATUS = (io.popen('dir /a-d /o-d /tw /b/s "'..dir..'" 2>nul:'):read("*a"):match"%C+")
55 if not ID_STATUS then
56 error"No files in this directory"
57 end
58 -------------------------------------------A debug printout-function
59 local function dbg(args)
60 if not DEBUG then return end
61 if type(args) == 'table' then
62 local i = 1
63 while args[i] do
64 dbg(args[i])
65 i = i+1
66 end
67 else
68 print('###', args)
69 end
70 end
71 ------------------------------------------------- errors
72 local function oops(err)
73 core.console('clear')
74 print( string.rep('--',39) )
75 print( string.rep('--',39) )
76 print(ac.red..' ERROR:'..ac.reset.. err)
77 print( string.rep('--',39) )
78 print( string.rep('--',39) )
79 return nil, err
80 end
81 -----------------------------------------------sleep
82 local function sleep(n)
83 os.execute("sleep " ..tonumber(n))
84 end
85 --------------------wait
86 function wait(msec)
87 local t = os.clock()
88 repeat
89 until os.clock() > t + msec * 1e-3
90 end
91 ----------------------------------------------time wait
92 local function timer(n)
93 while n > 0 do
94 io.write(ac.cyan.." ::::: "..ac.yellow.. tonumber(n) ..ac.yellow.." sec "..ac.cyan..":::::\r"..ac.reset)
95 sleep(1)
96 io.flush()
97 n = n-1
98 end
99 end
100 ----------------------------------------------------- help
101 local function help()
102 core.console('clear')
103 print(line)
104 print(ac.cyan..mod..ac.reset)
105 print(ac.cyan..version..ac.reset)
106 print(ac.yellow..desc..ac.reset)
107 print(line)
108 print(ac.cyan..' Usage'..ac.reset)
109 print(usage)
110 print(ac.cyan..' Arguments'..ac.reset)
111 print(arguments)
112 print(line)
113 timer(30)
114 core.console('clear')
115 print(ac.cyan..' Example usage'..ac.reset)
116 print(example)
118 ------------------------------------ Exit message
119 local function exitMsg(msg)
120 print( string.rep('--',39) )
121 print( string.rep('--',39) )
122 print(msg)
123 print()
125 --------------------------------- idsearch EM ID
126 local function id()
127 local f = assert(io.open(ID_STATUS, "r"))
128 for line in f:lines() do
129 id = line:match"^%[%+%] EM 410x ID (%x+)"
130 if id then break end
132 f:close()
133 local f= io.open(ID_STATUS, "w+")
134 f:write(id)
135 f:close()
136 local f= io.open(ID_STATUS, "r")
137 local t = f:read("*all")
138 f:close()
139 local hex_hi = tonumber(t:sub(1, 2), 16)
140 local hex_low = tonumber(t:sub(3, 10), 16)
141 return hex_hi, hex_low
143 ---------------------------------------read file
144 local function readfile()
145 local f = io.open(ID_STATUS, "r")
146 for line in f:lines() do
147 id = line:match"^(%x+)"
148 if id then break end
150 f:close()
151 if not id then
152 return oops (" ....No ID found in file") end
153 local f= io.open(ID_STATUS, "r")
154 local t = f:read("*all")
155 f:close()
156 local hex_hi = tonumber(t:sub(1, 2), 16)
157 local hex_low = tonumber(t:sub(3, 10), 16)
158 return hex_hi, hex_low
160 ----------------------------------------last ID
161 local function IDsaved()
162 local f = io.open(LAST_ID, "r")
163 for line in f:lines() do
164 id = line:match"^(%x+)"
165 if id then break end
167 f:close()
168 if not id then
169 return oops (" ....No ID found in file") end
170 local f= io.open(LAST_ID, "r")
171 local t = f:read("*all")
172 f:close()
173 local hex_hi = tonumber(t:sub(1, 2), 16)
174 local hex_low = tonumber(t:sub(3, 10), 16)
175 return hex_hi, hex_low
177 ----------------------------------------write file
178 local function writefile(hex_hi, hex_low)
179 local f = io.open(ID_STATUS, "w+")
180 local g = io.open(LAST_ID, 'w+')
181 f:write(("%02X%08X\n"):format(hex_hi, hex_low))
182 f:close()
183 g:write(("%02X%08X\n"):format(hex_hi, hex_low))
184 g:close()
185 print((' Saved EM410x ID '..ac.green..'%02X%08X'..ac.reset..' to TXT file:'):format(hex_hi, hex_low))
186 print((ac.yellow..' %s'..ac.reset):format(LAST_ID))
187 return true, 'Ok'
189 ---------------replace line
190 local last_str = ''
191 function txt_change(str)
192 io.write(('\b \b'):rep(#last_str)) -- old line
193 io.write(str) -- new line
194 io.flush()
195 last_str = str
197 ---------------------------------------- main
198 local function main(args)
199 print( string.rep('--',39) )
200 print( string.rep('--',39) )
201 print()
202 if #args == 0 then return help() end
203 local saved_id = false
204 local id_original = false
205 local emarine = false
206 local input_id = ''
207 for o, a in getopt.getopt(args, 'hems:c') do
208 if o == 'h' then return help() end
209 if o == 'e' then id_original = true end
210 if o == 'm' then emarine = true end
211 if o == 's' then input_id = a end
212 if o == 'c' then saved_id = true end
214 --------------------check -id
215 if not saved_id and not id_original and not emarine then
216 if input_id == nil then return oops(' empty EM410x ID string') end
217 if #input_id == 0 then return oops(' empty EM410x ID string') end
218 if #input_id < 10 then return oops(' EM410x ID too short. Must be 5 hex bytes') end
219 if #input_id > 10 then return oops(' EM410x ID too long. Must be 5 hex bytes') end
221 core.console('clear')
222 print( string.rep('--',39) )
223 print(ac.green..' ....... OFF THE HINTS WILL BE LESS ON THE SCREEN'..ac.reset)
224 print( string.rep('--',39) )
225 core.console('pref set hint --off')
226 print( string.rep('--',39) )
227 timer(4)
228 core.console('clear')
229 local hi = tonumber(input_id:sub(1, 2), 16)
230 local low = tonumber(input_id:sub(3, 10), 16)
231 if saved_id then
232 hi, low = IDsaved()
233 print( string.rep('--',39) )
234 print( string.rep('--',39) )
235 print('')
236 print(ac.green..' ......Continue cloning from last saved ID'..ac.reset)
237 print('')
238 print( string.rep('--',39) )
240 if id_original then
241 print( string.rep('--',39) )
242 print( string.rep('--',39) )
243 print('')
244 print(ac.green..' Put the ELECTRA tag on the coil PM3 to read '..ac.reset)
245 print('')
246 print( string.rep('--',39))
247 print(string.rep('--',39))
249 if emarine then
250 print( string.rep('--',39) )
251 print( string.rep('--',39) )
252 print('')
253 print(ac.green..' Put the EM4102 tag on the coil PM3 to read '..ac.reset)
254 print('')
255 print( string.rep('--',39) )
256 print( string.rep('--',39) )
258 if emarine or id_original then
259 io.write(' Press'..ac.yellow..' Enter'..ac.reset..' to continue ... ');io.read()
260 txt_change(' Readed TAG : ')
261 core.console(' lf em 410x read')
262 print( string.rep('--',39) )
263 hi, low = id()
264 timer(7)
265 core.console('clear')
266 print( string.rep('--',39) )
267 print( string.rep('--',39) )
268 print('')
269 print(ac.green..' Continuation of the cloning process....'..ac.reset)
270 print('')
271 print( string.rep('--',39) )
273 if not emarine and not id_original and not saved_id then
274 print( string.rep('--',39) )
275 print( string.rep('--',39) )
276 print('')
277 print(ac.green..' ........ ELECTRA cloning from Entered EM-ELECTRA ID'..ac.reset)
278 print('')
279 print( string.rep('--',39) )
281 if emarine then
282 d = ('EM4102 ID ')
283 else
284 d =('ELECTRA ID ')
286 local template = ((d)..ac.green..'%02X%08X'..ac.reset)
287 for i = low, low + 100, 1 do
288 local msg = (template):format(hi, low)
289 print( string.rep('--',39) )
290 if count > 0 then
291 print((' TAGs created: '..ac.green..'%s'..ac.reset):format(count))
292 print( string.rep('--',39) )
294 print((' %s >>>>>> cloning to '..ac.cyan..'T5577 -'..ac.yellow..' Enter'..ac.reset..' for yes or '..ac.yellow..'n'..ac.reset..' for exit'):format(msg))
295 print(' Before confirming the cloning operation, put a blank '..ac.cyan..'T5577'..ac.reset..' tag on coil'..ac.cyan..' PM3'..ac.reset..' !')
296 print( string.rep('--',39) )
297 io.write(' Continue with this operation'..ac.yellow..' (Enter/n)'..ac.reset..' ? > ')
298 answer = io.read()
299 if answer == 'n' then
300 core.console('clear')
301 print( string.rep('--',39) )
302 print(ac.red..' USER ABORTED'..ac.reset)
303 print( string.rep('--',39) )
304 break
306 core.console('clear')
307 print( string.rep('--',39) )
308 if emarine then
309 core.console( ('lf em 410x clone --id %02X%08X'):format(hi, low) )
310 else
311 core.console( ('lf em 410x clone --id %02X%08X'):format(hi, low) )
312 core.console('lf t55 write -b 0 -d 00148080')
313 core.console('lf t55 write -b 3 -d 7E1EAAAA')
314 core.console('lf t55 write -b 4 -d AAAAAAAA')
316 count = count+1
318 writefile(hi, low)
319 core.console('pref set hint --on')
320 print( string.rep('--',39) )
321 if count > 0 then
322 print((' TAGs created: '..ac.green..'%s'..ac.reset):format(count))
323 print( string.rep('--',39) )
326 main(args)