]>
Commit | Line | Data |
---|---|---|
1 | --[[ | |
2 | script to create a clone-dump with new crc | |
3 | Author: mosci | |
4 | my Fork: https://github.com/icsom/proxmark3.git | |
5 | Upstream: https://github.com/Proxmark/proxmark3.git | |
6 | ||
7 | 1. read tag-dump, xor byte 22..end with byte 0x05 of the inputfile | |
8 | 2. write to outfile | |
9 | 3. set byte 0x05 to newcrc | |
10 | 4. until byte 0x21 plain like in inputfile | |
11 | 5. from 0x22..end xored with newcrc | |
12 | 6. calculate new crc on each segment (needs to know the new MCD & MSN0..2) | |
13 | ||
14 | simplest usage: | |
15 | read a valid legic tag with 'hf legic reader' | |
16 | save the dump with 'hf legic save orig.hex' | |
17 | place your 'empty' tag on the reader and run 'script run Legic_clone -i orig.hex -w' | |
18 | you will see some output like: | |
19 | read 1024 bytes from legic_dumps/j_0000.hex | |
20 | ||
21 | place your empty tag onto the PM3 to read and display the MCD & MSN0..2 | |
22 | the values will be shown below | |
23 | confirm whnen ready [y/n] ?y | |
24 | #db# setting up legic card | |
25 | #db# MIM 256 card found, reading card ... | |
26 | #db# Card read, use 'hf legic decode' or | |
27 | #db# 'data hexsamples 8' to view results | |
28 | 0b ad c0 de <- !! here you'll see the MCD & MSN of your empty tag, which has to be typed in manually as seen below !! | |
29 | type in MCD as 2-digit value - e.g.: 00 (default: 79 ) | |
30 | > 0b | |
31 | type in MSN0 as 2-digit value - e.g.: 01 (default: 28 ) | |
32 | > ad | |
33 | type in MSN1 as 2-digit value - e.g.: 02 (default: d1 ) | |
34 | > c0 | |
35 | type in MSN2 as 2-digit value - e.g.: 03 (default: 43 ) | |
36 | > de | |
37 | MCD:0b, MSN:ad c0 de, MCC:79 <- this crc is calculated from the MCD & MSN and must match the one on yout empty tag | |
38 | ||
39 | wrote 1024 bytes to myLegicClone.hex | |
40 | enter number of bytes to write? (default: 86 ) | |
41 | ||
42 | loaded 1024 samples | |
43 | #db# setting up legic card | |
44 | #db# MIM 256 card found, writing 0x00 - 0x01 ... | |
45 | #db# write successful | |
46 | ... | |
47 | #db# setting up legic card | |
48 | #db# MIM 256 card found, writing 0x56 - 0x01 ... | |
49 | #db# write successful | |
50 | proxmark3> | |
51 | ||
52 | the default value (number of bytes to write) is calculated over all valid segments and should be ok - just hit enter, wait until write has finished | |
53 | and your clone should be ready (except there has to be a additional KGH-CRC to be calculated - which credentials are unknown until yet) | |
54 | ||
55 | the '-w' switch will only work with my fork - it needs the binary legic_crc8 which is not part of the proxmark3-master-branch | |
56 | also the ability to write DCF is not possible with the proxmark3-master-branch | |
57 | but creating dumpfile-clone files will be possible (without valid segment-crc - this has to done manually with) | |
58 | ||
59 | ||
60 | (example) Legic-Prime Layout with 'Kaba Group Header' | |
61 | +----+----+----+----+----+----+----+----+ | |
62 | 0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 9f | | |
63 | +----+----+----+----+----+----+----+----+ | |
64 | 0x08| ff | 00 | 00 | 00 | 11 |Bck0|Bck1|Bck2| | |
65 | +----+----+----+----+----+----+----+----+ | |
66 | 0x10|Bck3|Bck4|Bck5|BCC | 00 | 00 |Seg0|Seg1| | |
67 | +----+----+----+----+----+----+----+----+ | |
68 | 0x18|Seg2|Seg3|SegC|Stp0|Stp1|Stp2|Stp3|UID0| | |
69 | +----+----+----+----+----+----+----+----+ | |
70 | 0x20|UID1|UID2|kghC| | |
71 | +----+----+----+ | |
72 | ||
73 | MCD= ManufacturerID (1 Byte) | |
74 | MSN0..2= ManufactureSerialNumber (3 Byte) | |
75 | MCC= CRC (1 Byte) calculated over MCD,MSN0..2 | |
76 | DCF= DecrementalField (2 Byte) 'credential' (enduser-Tag) seems to have always DCF-low=0x60 DCF-high=0xea | |
77 | Bck0..5= Backup (6 Byte) Bck0 'dirty-flag', Bck1..5 SegmentHeader-Backup | |
78 | BCC= BackupCRC (1 Byte) CRC calculated over Bck1..5 | |
79 | Seg0..3= SegmentHeader (on MIM 4 Byte ) | |
80 | SegC= SegmentCRC (1 Byte) calculated over MCD,MSN0..2,Seg0..3 | |
81 | Stp0..n= Stamp0... (variable length) length = Segment-Len - UserData - 1 | |
82 | UID0..n= UserDater (variable length - with KGH hex 0x00-0x63 / dec 0-99) length = Segment-Len - WRP - WRC - 1 | |
83 | kghC= KabaGroupHeader (1 Byte + addr 0x0c must be 0x11) | |
84 | as seen on ths example: addr 0x05..0x08 & 0x0c must have been set to this values - otherwise kghCRC will not be created by a official reader (not accepted) | |
85 | --]] | |
86 | ||
87 | example = "Script create a clone-dump of a dump from a Legic Prime Tag" | |
88 | author = "Mosci" | |
89 | desc = | |
90 | [[ | |
91 | This is a script which create a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024) | |
92 | (created with 'hf legic save my_dump.hex') | |
93 | requiered arguments: | |
94 | -i <input file> (file to read data from) | |
95 | ||
96 | optional arguments : | |
97 | -h - Help text | |
98 | -o <output file> - requieres option -c to be given | |
99 | -c <new-tag crc> - requieres option -o to be given | |
100 | -d - Display content of found Segments | |
101 | -s - Display summary at the end | |
102 | -w - write directly to Tag - a file myLegicClone.hex wille be generated also | |
103 | ||
104 | e.g.: | |
105 | hint: using the CRC '00' will result in a plain dump ( -c 00 ) | |
106 | ||
107 | Examples : | |
108 | script run legic_clone -i my_dump.hex -o my_clone.hex -c f8 | |
109 | script run legic_clone -i my_dump.hex -d -s | |
110 | ]] | |
111 | ||
112 | local utils = require('utils') | |
113 | local getopt = require('getopt') | |
114 | local bxor = bit32.bxor | |
115 | ||
116 | -- we need always 2 digits | |
117 | function prepend_zero(s) | |
118 | if (string.len(s)==1) then return "0" .. s | |
119 | else | |
120 | if (string.len(s)==0) then return "00" | |
121 | else return s | |
122 | end | |
123 | end | |
124 | end | |
125 | ||
126 | --- | |
127 | -- This is only meant to be used when errors occur | |
128 | function oops(err) | |
129 | print("ERROR: ",err) | |
130 | return nil, err | |
131 | end | |
132 | ||
133 | --- | |
134 | -- Usage help | |
135 | function help() | |
136 | print(desc) | |
137 | print("Example usage") | |
138 | print(example) | |
139 | end | |
140 | ||
141 | -- Check availability of file | |
142 | function file_check(file_name) | |
143 | local file_found=io.open(file_name, "r") | |
144 | if file_found==nil then | |
145 | file_found=false | |
146 | else | |
147 | file_found=true | |
148 | end | |
149 | return file_found | |
150 | end | |
151 | ||
152 | --- xor-wrapper | |
153 | -- xor all from addr 0x22 (start counting from 1 => 23) | |
154 | function xorme(hex, xor, index) | |
155 | if ( index >= 23 ) then | |
156 | return ('%02x'):format(bxor( tonumber(hex,16) , tonumber(xor,16) )) | |
157 | else | |
158 | return hex | |
159 | end | |
160 | end | |
161 | ||
162 | -- read input-file into array | |
163 | function getInputBytes(infile) | |
164 | local line | |
165 | local bytes = {} | |
166 | ||
167 | local fhi,err = io.open(infile) | |
168 | if err then print("OOps ... faild to read from file ".. infile); return false; end | |
169 | ||
170 | while true do | |
171 | line = fhi:read() | |
172 | if line == nil then break end | |
173 | ||
174 | for byte in line:gmatch("%w+") do | |
175 | table.insert(bytes, byte) | |
176 | end | |
177 | end | |
178 | ||
179 | fhi:close() | |
180 | ||
181 | print("\nread ".. #bytes .." bytes from ".. infile) | |
182 | return bytes | |
183 | end | |
184 | ||
185 | -- write to file | |
186 | function writeOutputBytes(bytes, outfile) | |
187 | local line | |
188 | local bcnt=0 | |
189 | local fho,err = io.open(outfile,"w") | |
190 | if err then print("OOps ... faild to open output-file ".. outfile); return false; end | |
191 | ||
192 | for i = 1, #bytes do | |
193 | if (bcnt == 0) then | |
194 | line=bytes[i] | |
195 | elseif (bcnt <= 7) then | |
196 | line=line.." "..bytes[i] | |
197 | end | |
198 | if (bcnt == 7) then | |
199 | -- write line to new file | |
200 | fho:write(line.."\n") | |
201 | -- reset counter & line | |
202 | bcnt=-1 | |
203 | line="" | |
204 | end | |
205 | bcnt=bcnt+1 | |
206 | end | |
207 | fho:close() | |
208 | print("\nwrote ".. #bytes .." bytes to " .. outfile) | |
209 | return true | |
210 | end | |
211 | ||
212 | -- xore certain bytes | |
213 | function xorBytes(inBytes, crc) | |
214 | local bytes = {} | |
215 | for index = 1, #inBytes do | |
216 | bytes[index] = xorme(inBytes[index], crc, index) | |
217 | end | |
218 | if (#inBytes == #bytes) then | |
219 | -- replace crc | |
220 | bytes[5] = string.sub(crc,-2) | |
221 | return bytes | |
222 | else | |
223 | print("error: byte-count missmatch") | |
224 | return false | |
225 | end | |
226 | end | |
227 | ||
228 | -- get raw segment-data | |
229 | function getSegmentData(bytes, start, index) | |
230 | local raw, len, valid, last, wrp, wrc, rd, crc | |
231 | local segment = {} | |
232 | segment[0] = bytes[start].." "..bytes[start+1].." "..bytes[start+2].." "..bytes[start+3] | |
233 | -- flag = high nibble of byte 1 | |
234 | segment[1] = string.sub(bytes[start+1],0,1) | |
235 | ||
236 | -- valid = bit 6 of byte 1 | |
237 | segment[2] = tonumber(bit32.extract("0x"..bytes[start+1],6,1),16) | |
238 | ||
239 | -- last = bit 7 of byte 1 | |
240 | segment[3] = tonumber(bit32.extract("0x"..bytes[start+1],7,1),16) | |
241 | ||
242 | -- len = (byte 0)+(bit0-3 of byte 1) | |
243 | segment[4] = tonumber(("%03x"):format(tonumber(bit32.extract("0x"..bytes[start+1],0,3),16)..tonumber(bytes[start],16)),16) | |
244 | ||
245 | -- wrp (write proteted) = byte 2 | |
246 | segment[5] = tonumber(bytes[start+2]) | |
247 | ||
248 | -- wrc (write control) - bit 4-6 of byte 3 | |
249 | segment[6] = tonumber(bit32.extract("0x"..bytes[start+3],4,3),16) | |
250 | ||
251 | -- rd (read disabled) - bit 7 of byte 3 | |
252 | segment[7] = tonumber(bit32.extract("0x"..bytes[start+3],7,1),16) | |
253 | ||
254 | -- crc byte 4 | |
255 | segment[8] = bytes[start+4] | |
256 | ||
257 | -- segment index | |
258 | segment[9] = index | |
259 | ||
260 | -- # crc-byte | |
261 | segment[10] = start+4 | |
262 | return segment | |
263 | end | |
264 | ||
265 | --- Kaba Group Header | |
266 | -- checks if a segment does have a kghCRC | |
267 | -- returns boolean false if no kgh has being detected or the kghCRC if a kgh was detected | |
268 | function CheckKgh(bytes, segStart, segEnd) | |
269 | if (bytes[8]=='9f' and bytes[9]=='ff' and bytes[13]=='11') then | |
270 | local i | |
271 | local data = {} | |
272 | segStart=tonumber(segStart,10) | |
273 | segEnd=tonumber(segEnd,10) | |
274 | local dataLen = segEnd-segStart-5 | |
275 | --- gather creadentials for verify | |
276 | local WRP = bytes[(segStart+2)] | |
277 | local WRC = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],4,3),16)) | |
278 | local RD = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],7,1),16)) | |
279 | local XX = "00" | |
280 | cmd = bytes[1]..bytes[2]..bytes[3]..bytes[4]..WRP..WRC..RD..XX | |
281 | for i=(segStart+5), (segStart+5+dataLen-2) do | |
282 | cmd = cmd..bytes[i] | |
283 | end | |
284 | local KGH=("%02x"):format(utils.Crc8Legic(cmd)) | |
285 | if (KGH==bytes[segEnd-1]) then | |
286 | return KGH | |
287 | else | |
288 | return false | |
289 | end | |
290 | else | |
291 | return false | |
292 | end | |
293 | end | |
294 | ||
295 | -- get only the addresses of segemnt-crc's and the length of bytes | |
296 | function getSegmentCrcBytes(bytes) | |
297 | local start=23 | |
298 | local index=0 | |
299 | local crcbytes = {} | |
300 | repeat | |
301 | seg = getSegmentData(bytes,start,index) | |
302 | crcbytes[index]= seg[10] | |
303 | start = start + seg[4] | |
304 | index = index + 1 | |
305 | until (seg[3] == 1 or tonumber(seg[9]) == 126 ) | |
306 | crcbytes[index] = start | |
307 | return crcbytes | |
308 | end | |
309 | ||
310 | -- print segment-data (hf legic decode like) | |
311 | function displaySegments(bytes) | |
312 | --display segment header(s) | |
313 | start=23 | |
314 | index="00" | |
315 | ||
316 | --repeat until last-flag ist set to 1 or segment-index has reached 126 | |
317 | repeat | |
318 | wrc="" | |
319 | wrp="" | |
320 | pld="" | |
321 | Seg = getSegmentData(bytes,start,index) | |
322 | KGH = CheckKgh(bytes,start,(start+tonumber(Seg[4],10))) | |
323 | printSegment(Seg) | |
324 | ||
325 | -- wrc | |
326 | if(Seg[6]>0) then | |
327 | print("WRC protected area:") | |
328 | -- length of wrc = wrc | |
329 | for i=1, Seg[6] do | |
330 | -- starts at (segment-start + segment-header + segment-crc)-1 | |
331 | wrc = wrc..bytes[(start+4+1+i)-1].." " | |
332 | end | |
333 | print(wrc) | |
334 | elseif(Seg[5]>0) then | |
335 | print("Remaining write protected area:") | |
336 | -- length of wrp = (wrp-wrc) | |
337 | for i=1, (Seg[5]-Seg[6]) do | |
338 | -- starts at (segment-start + segment-header + segment-crc + wrc)-1 | |
339 | wrp = wrp..bytes[(start+4+1+Seg[6]+i)-1].." " | |
340 | end | |
341 | print(wrp) | |
342 | end | |
343 | ||
344 | -- payload | |
345 | print("Remaining segment payload:") | |
346 | --length of payload = segment-len - segment-header - segment-crc - wrp -wrc | |
347 | for i=1, (Seg[4]-4-1-Seg[5]-Seg[6]) do | |
348 | -- starts at (segment-start + segment-header + segment-crc + segment-wrp + segemnt-wrc)-1 | |
349 | pld = pld..bytes[(start+4+1+Seg[5]+Seg[6]+i)-1].." " | |
350 | end | |
351 | print(pld) | |
352 | if (KGH) then print("'Kaba Group Header' detected"); end | |
353 | start = start+Seg[4] | |
354 | index = prepend_zero(tonumber(Seg[9])+1) | |
355 | ||
356 | until (Seg[3] == 1 or tonumber(Seg[9]) == 126 ) | |
357 | end | |
358 | ||
359 | -- print Segment values | |
360 | function printSegment(SegmentData) | |
361 | res = "\nSegment "..SegmentData[9]..": " | |
362 | res = res.. "raw header="..SegmentData[0]..", " | |
363 | res = res.. "flag="..SegmentData[1].." (valid="..SegmentData[2].." last="..SegmentData[3].."), " | |
364 | res = res.. "len="..("%04d"):format(SegmentData[4])..", " | |
365 | res = res.. "WRP="..prepend_zero(SegmentData[5])..", " | |
366 | res = res.. "WRC="..prepend_zero(SegmentData[6])..", " | |
367 | res = res.. "RD="..SegmentData[7]..", " | |
368 | res = res.. "crc="..SegmentData[8] | |
369 | print(res) | |
370 | end | |
371 | ||
372 | -- write clone-data to tag | |
373 | function writeToTag(plainBytes) | |
374 | local SegCrcs = {} | |
375 | if(utils.confirm("\nplace your empty tag onto the PM3 to read and display the MCD & MSN0..2\nthe values will be shown below\n confirm when ready") == false) then | |
376 | return | |
377 | end | |
378 | ||
379 | -- gather MCD & MSN from new Tag - this must be enterd manually | |
380 | cmd = 'hf legic read 0x00 0x04' | |
381 | core.console(cmd) | |
382 | print("\nthese are the MCD MSN0 MSN1 MSN2 from the Tag that has being read:") | |
383 | cmd = 'data hexsamples 4' | |
384 | core.console(cmd) | |
385 | print("^^ use this values as input for the following answers (one 2-digit-value per question/answer):") | |
386 | -- enter MCD & MSN (in hex) | |
387 | MCD = utils.input("type in MCD as 2-digit value - e.g.: 00", plainBytes[1]) | |
388 | MSN0 = utils.input("type in MSN0 as 2-digit value - e.g.: 01", plainBytes[2]) | |
389 | MSN1 = utils.input("type in MSN1 as 2-digit value - e.g.: 02", plainBytes[3]) | |
390 | MSN2 = utils.input("type in MSN2 as 2-digit value - e.g.: 03", plainBytes[4]) | |
391 | ||
392 | -- calculate crc8 over MCD & MSN | |
393 | cmd = MCD..MSN0..MSN1..MSN2 | |
394 | MCC = ("%02x"):format(utils.Crc8Legic(cmd)) | |
395 | print("MCD:"..MCD..", MSN:"..MSN0.." "..MSN1.." "..MSN2..", MCC:"..MCC) | |
396 | ||
397 | -- calculate new Segment-CRC for each valid segment | |
398 | SegCrcs = getSegmentCrcBytes(plainBytes) | |
399 | for i=0, (#SegCrcs-1) do | |
400 | -- SegCrcs[i]-4 = address of first byte of segmentHeader (low byte segment-length) | |
401 | segLen=tonumber(("%1x"):format(tonumber(bit32.extract("0x"..plainBytes[(SegCrcs[i]-3)],0,3),16))..("%02x"):format(tonumber(plainBytes[SegCrcs[i]-4],16)),16) | |
402 | segStart=(SegCrcs[i]-4) | |
403 | segEnd=(SegCrcs[i]-4+segLen) | |
404 | KGH=CheckKgh(plainBytes,segStart,segEnd) | |
405 | if (KGH) then | |
406 | print("'Kaba Group Header' detected - re-calculate...") | |
407 | end | |
408 | cmd = MCD..MSN0..MSN1..MSN2..plainBytes[SegCrcs[i]-4]..plainBytes[SegCrcs[i]-3]..plainBytes[SegCrcs[i]-2]..plainBytes[SegCrcs[i]-1] | |
409 | plainBytes[SegCrcs[i]] = ("%02x"):format(utils.Crc8Legic(cmd)) | |
410 | end | |
411 | ||
412 | -- apply MCD & MSN to plain data | |
413 | plainBytes[1] = MCD | |
414 | plainBytes[2] = MSN0 | |
415 | plainBytes[3] = MSN1 | |
416 | plainBytes[4] = MSN2 | |
417 | plainBytes[5] = MCC | |
418 | ||
419 | -- prepare plainBytes for writing (xor plain data with new MCC) | |
420 | bytes = xorBytes(plainBytes, MCC) | |
421 | ||
422 | -- write data to file | |
423 | if (writeOutputBytes(bytes, "myLegicClone.hex")) then | |
424 | WriteBytes = utils.input("enter number of bytes to write?", SegCrcs[#SegCrcs]) | |
425 | ||
426 | -- load file into pm3-buffer | |
427 | cmd = 'hf legic load myLegicClone.hex' | |
428 | core.console(cmd) | |
429 | ||
430 | -- write pm3-buffer to Tag | |
431 | for i=0, WriteBytes do | |
432 | if ( i<5 or i>6) then | |
433 | cmd = ('hf legic write 0x%02x 0x01'):format(i) | |
434 | core.console(cmd) | |
435 | elseif (i == 6) then | |
436 | -- write DCF in reverse order (requires 'mosci-patch') | |
437 | cmd = 'hf legic write 0x05 0x02' | |
438 | core.console(cmd) | |
439 | else | |
440 | print("skipping byte 0x05 - will be written next step") | |
441 | end | |
442 | utils.Sleep(0.2) | |
443 | end | |
444 | end | |
445 | end | |
446 | ||
447 | -- main function | |
448 | function main(args) | |
449 | -- some variables | |
450 | local i=0 | |
451 | local oldcrc, newcrc, infile, outfile | |
452 | local bytes = {} | |
453 | local segments = {} | |
454 | ||
455 | -- parse arguments for the script | |
456 | for o, a in getopt.getopt(args, 'hwsdc:i::o:') do | |
457 | -- output file | |
458 | if o == "o" then | |
459 | outfile = a | |
460 | ofs = true | |
461 | if (file_check(a)) then | |
462 | local answer = utils.confirm("\nthe output-file "..a.." alredy exists!\nthis will delete the previous content!\ncontinue?") | |
463 | if (answer==false) then return oops("quiting") end | |
464 | end | |
465 | end | |
466 | -- input file | |
467 | if o == "i" then | |
468 | infile = a | |
469 | if (file_check(infile)==false) then | |
470 | return oops("input file: "..infile.." not found") | |
471 | else | |
472 | bytes = getInputBytes(infile) | |
473 | oldcrc = bytes[5] | |
474 | ifs = true | |
475 | if (bytes == false) then return oops('couldnt get input bytes') end | |
476 | end | |
477 | i = i+1 | |
478 | end | |
479 | -- new crc | |
480 | if o == "c" then | |
481 | newcrc = a | |
482 | ncs = true | |
483 | end | |
484 | -- display segments switch | |
485 | if o == "d" then ds = true; end | |
486 | -- display summary switch | |
487 | if o == "s" then ss = true; end | |
488 | -- write to tag switch | |
489 | if o == "w" then ws = true; end | |
490 | -- help | |
491 | if o == "h" then return help() end | |
492 | end | |
493 | ||
494 | if (not ifs) then return oops("option -i <input file> is required but missing") end | |
495 | ||
496 | -- bytes to plain | |
497 | bytes = xorBytes(bytes, oldcrc) | |
498 | ||
499 | -- show segments (works only on plain bytes) | |
500 | if (ds) then | |
501 | print("+------------------------------------------- Segments -------------------------------------------+") | |
502 | displaySegments(bytes); | |
503 | end | |
504 | ||
505 | if (ofs and ncs) then | |
506 | -- xor bytes with new crc | |
507 | newBytes = xorBytes(bytes, newcrc) | |
508 | -- write output | |
509 | if (writeOutputBytes(newBytes, outfile)) then | |
510 | -- show summary if requested | |
511 | if (ss) then | |
512 | -- information | |
513 | res = "\n+-------------------------------------------- Summary -------------------------------------------+" | |
514 | res = res .."\ncreated clone_dump from\n\t"..infile.." crc: "..oldcrc.."\ndump_file:" | |
515 | res = res .."\n\t"..outfile.." crc: "..string.sub(newcrc,-2) | |
516 | res = res .."\nyou may load the new file with: hf legic load "..outfile | |
517 | res = res .."\n\nif you don't write to tag immediately ('-w' switch) you will need to recalculate each segmentCRC" | |
518 | res = res .."\nafter writing this dump to a tag!" | |
519 | res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3,Segment-Header0..3" | |
520 | res = res .."\ne.g. (based on Segment00 of the data from "..infile.."):" | |
521 | res = res .."\nhf legic crc8 "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26] | |
522 | -- this can not be calculated without knowing the new MCD, MSN0..2 | |
523 | print(res) | |
524 | end | |
525 | end | |
526 | else | |
527 | if (ss) then | |
528 | -- show why the output-file was not written | |
529 | print("\nnew file not written - some arguments are missing ..") | |
530 | print("output file: ".. (ofs and outfile or "not given")) | |
531 | print("new crc: ".. (ncs and newcrc or "not given")) | |
532 | end | |
533 | end | |
534 | -- write to tag | |
535 | if (ws and #bytes == 1024) then | |
536 | writeToTag(bytes) | |
537 | end | |
538 | end | |
539 | ||
540 | -- call main with arguments | |
541 | main(args) |