diff --git a/.gitignore b/.gitignore index bf86be009..24761385f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # .gitignore # don't push these files to the repository +.idea .history *.log *.eml diff --git a/README.md b/README.md index 94499d9b4..764a08703 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,21 @@ The iceman fork =============== -[![Build Status](https://travis-ci.org/iceman1001/proxmark3.svg?branch=master)](https://travis-ci.org/iceman1001/proxmark3) [![Coverity Status](https://scan.coverity.com/projects/5117/badge.svg)](https://scan.coverity.com/projects/proxmark3_iceman_fork) [![Latest release] (https://img.shields.io/github/release/iceman1001/proxmark3.svg)](https://github.com/iceman1001/proxmark3/releases/latest) +[![Build Status](https://travis-ci.org/iceman1001/proxmark3.svg?branch=master)](https://travis-ci.org/iceman1001/proxmark3)[![Coverity Status](https://scan.coverity.com/projects/5117/badge.svg)](https://scan.coverity.com/project/proxmark3_iceman_fork)[![Latest release](https://img.shields.io/github/release/iceman1001/proxmark3.svg)](https://github.com/iceman1001/proxmark3/releases/latest) -##This fork is HIGHLY experimental (or bleeding edge) -##Donate +## This fork is HIGHLY experimental and bleeding edge + +## Donate https://paypal.me/iceman1001/ Feel free to donate. All support is welcome. -##Notice +## Notice There is so much in this fork, with all fixes and additions its basically the most enhanced fork to this day for the Proxmark3 device. Which makes it so awesum to play with. Do please play with it. Get excited and experiment. As a side note with all coverity scan fixes this client is much more stable than PM3 Master even if I tend to break it sometimes. I'll try to make a release when this fork becomes stable between my experiments. -##Official -The official Proxmark repository is found here: https://github.com/Proxmark/proxmark3 - -##Coverity Scan Config & Run +## Coverity Scan Config & Run Download the Coverity Scan Self-buld and install it. You will need to configure ARM-NON-EABI- Compiler for it to use: - +``` - Configure `cov-configure --comptype gcc --compiler /opt/devkitpro/devkitARM/bin/arm-none-eabi-gcc` @@ -28,8 +26,9 @@ You will need to configure ARM-NON-EABI- Compiler for it to use: `tar czvf proxmark3.tgz cov-int` - upload it to coverity.com +``` -##Whats changed? +## Whats changed? Whats so special with this fork? I have scraped the web for different enhancements to the PM3 source code and not all of them ever found their way to the master branch. Among the stuff is @@ -56,24 +55,24 @@ Among the stuff is * Aczid's bitsliced bruteforce solver in 'hf mf hardnested' --- -##Why don't you merged with offical PM3 Master? +## Why don't you merged with offical PM3 Master? I don't actually know how to make small pull-request to github :( and that is the number one reason for me not pushing a lot of things back to the PM3 master. Me fiddling with the code so much, there is a nightmare in merging a PR. Luckily I have @marshmellow42 who takes some stuff and push PR's back. -##Why don't you add nnnn or mmmm functionality? +## Why don't you add this or that functionality? Give me a hint, and I'll see if I can't merge in the stuff you have. -##PM3 GUI +## PM3 GUI I do tend to rename and move stuff around, the official PM3-GUI from Gaucho will not work so well. *sorry* -##Development +## Development This fork now compiles just fine on - Windows/mingw environment with Qt5.6.1 & GCC 4.8 - Ubuntu 1404, 1510, 1604 - Mac OS X / Homebrew - Docker container -##Setup and build for UBUNTU +## Setup and build for UBUNTU GC made updates to allow this to build easily on Ubuntu 14.04.2 LTS, 15.10 or 16.04 See https://github.com/Proxmark/proxmark3/wiki/Ubuntu%20Linux @@ -110,7 +109,7 @@ https://github.com/daveio/attacksurface/blob/master/proxmark3/pm3-setup.sh - Run the client `./proxmark3 /dev/ttyACM0` -##Homebrew (Mac OS X) +## Homebrew (Mac OS X) These instructions comes from @Chrisfu, where I got the proxmark3.rb scriptfile from. Further questions about Mac & Homebrew, contact @Chrisfu (https://github.com/chrisfu/) @@ -120,13 +119,13 @@ Further questions about Mac & Homebrew, contact @Chrisfu (https://github.com/c 3. Install Proxmark3: `brew install proxmark3` for stable release or `brew install --HEAD proxmark3` for latest non-stable from GitHub. -##Docker container +## Docker container I recently added a docker container on Docker HUB. You find it here: https://hub.docker.com/r/iceman1001/proxmark3/ Follow those instructions to get it up and running. No need for the old proxspace-environment anymore. -[1.6.0] How to start: https://www.youtube.com/watch?v=b5Zta89Cf6Q -[1.6.0] How to connect: https://youtu.be/0ZS2t5C-caI -[1.6.1] How to flash: https://www.youtube.com/watch?v=WXouhuGYEiw +-[1.6.0] How to start: https://www.youtube.com/watch?v=b5Zta89Cf6Q +-[1.6.0] How to connect: https://youtu.be/0ZS2t5C-caI +-[1.6.1] How to flash: https://www.youtube.com/watch?v=WXouhuGYEiw Recommendations: Use only latest container. @@ -206,40 +205,21 @@ Assuming you have Proxmark3 Windows drivers installed you can run the Proxmark s - Run the client `proxmark3.exe comX` -##Buying a proxmark3 +## Buying a proxmark3 The Proxmark 3 device is available for purchase (assembled and tested) from the following locations: * http://proxmark3.tictail.com/ (For buyers in EU, most likely in Sweden) * http://www.elechouse.com/ (new and revised hardware package 2015, located in China) +Enjoy! -##Enjoy - -January 2015, Sweden iceman at host iuse.se +January 2015, Sweden - -##Note from Jonathan Westhues -Most of the ultra-low-volume contract assemblers could put -something like this together with a reasonable yield. A run of around -a dozen units is probably cost-effective. The BOM includes (possibly- -outdated) component pricing, and everything is available from Digikey -and the usual distributors. - -If you've never assembled a modern circuit board by hand, then this is -not a good place to start. Some of the components (e.g. the crystals) -must not be assembled with a soldering iron, and require hot air. - -The schematics are included; the component values given are not -necessarily correct for all situations, but it should be possible to do -nearly anything you would want with appropriate population options. - -The printed circuit board artwork is also available, as Gerbers and an -Excellon drill file. - +## Note from Jonathan Westhues LICENSING: diff --git a/appveyor.yml b/appveyor.yml index cac45bd42..d76c4e957 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,17 +1,27 @@ -os: Windows Server 2012 -platform: mingw -qt: mingw492_32 +version: 1.0.{build} +environment: + global: + CYG_ROOT: C:\cygwin + CYG_MIRROR: http://cygwin.mirror.constant.com + CYG_CACHE: C:\cygwin\var\cache\setup + CYG_BASH: C:\cygwin\bin\bash -branches: - only: - - master - -install: - - set QTDIR=C:\Qt\5.5\mingw492_32 - - set PATH=%PATH%;%QTDIR%\bin;C:\MinGW\bin - -before_build: - - make clean - -build: - - make all +init: +- cmd: + - set QTDIR=C:\Qt\5.5\mingw492_32 + - set PATH=%PATH%;%QTDIR%\bin;C:\MinGW\bin;C:\MinGW\msys\1.0\bin + - c:\cygwin\setup-x86.exe --quiet-mode --no-shortcuts --only-site --root "%CYG_ROOT%" --site "%CYG_MIRROR%" --local-package-dir "%CYG_CACHE%" --packages autoconf,automake,bison,gcc-core,gcc-g++,mingw-runtime,mingw-binutils,mingw-gcc-core,mingw-gcc-g++,mingw-pthreads,mingw-w32api,libtool,make,gettext-devel,gettext,intltool,libiconv,pkg-config,git,curl,libxslt,libreadline-devel,libreadline7 > NUL 2>&1' + - '%CYG_BASH% -lc "cygcheck -dc cygwin"' + - if not exist "make.zip" curl -L -o make.zip http://gnuwin32.sourceforge.net/downlinks/make-bin-zip.php + - if not exist "make-dep.zip" curl -L -o make-dep.zip http://gnuwin32.sourceforge.net/downlinks/make-dep-zip.php + - if not exist "gcc-arm-none-eabi.zip" curl -L -o gcc-arm-none-eabi.zip https://launchpad.net/gcc-arm-embedded/4.8/4.8-2014-q1-update/+download/gcc-arm-none-eabi-4_8-2014q1-20140314-win32.zip + - if not exist "C:\strawberry" cinst strawberryperl #once I workout how to install Digest::SHA for perl, this won't be required + - set PATH=C:\strawberry\perl\bin;C:\strawberry\perl\site\bin;C:\strawberry\c\bin;%PATH% + - unzip -o -q gcc-arm-none-eabi.zip -d c:\gcc\ + - unzip make.zip -d c:\gnuwin32\ + - unzip make-dep.zip -d c:\gnuwin32\ + - set PATH=C:\Program Files\git\bin;%PATH:C:\Program Files\git\bin;=% #move git to begining of PATH so find works correctly + - set PATH=%PATH%;c:\gnuwin32\bin;c:\gcc\bin + - set PATH=%PATH%;c:\gcc\bin +build_script: +- cmd: make all diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index a96cb5d9e..e8c3028f3 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -153,20 +153,20 @@ void FpgaSetupSsc(void) { //----------------------------------------------------------------------------- bool FpgaSetupSscDma(uint8_t *buf, int len) { if (buf == NULL) return false; - + AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; // Disable DMA Transfer AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) buf; // transfer to this memory address AT91C_BASE_PDC_SSC->PDC_RCR = len; // transfer this many bytes AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) buf; // next transfer to same memory address AT91C_BASE_PDC_SSC->PDC_RNCR = len; // ... with same number of bytes - AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // go! + AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // go! return true; } //---------------------------------------------------------------------------- // Uncompress (inflate) the FPGA data. Returns one decompressed byte with -// each call. +// each call. //---------------------------------------------------------------------------- static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8_t *output_buffer) { @@ -184,7 +184,7 @@ static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8 } ++uncompressed_bytes_cnt; - + return *fpga_image_ptr++; } @@ -200,7 +200,7 @@ static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); } - return get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); + return get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); } @@ -218,14 +218,14 @@ static void fpga_inflate_free(voidpf opaque, voidpf address) //---------------------------------------------------------------------------- -// Initialize decompression of the respective (HF or LF) FPGA stream +// Initialize decompression of the respective (HF or LF) FPGA stream //---------------------------------------------------------------------------- static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE]; - + uncompressed_bytes_cnt = 0; - + // initialize z_stream structure for inflate: compressed_fpga_stream->next_in = &_binary_obj_fpga_all_bit_z_start; compressed_fpga_stream->avail_in = &_binary_obj_fpga_all_bit_z_start - &_binary_obj_fpga_all_bit_z_end; @@ -240,7 +240,7 @@ static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_s for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++) header[i] = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); - + // Check for a valid .bit file (starts with _bitparse_fixed_header) if(memcmp(_bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0) return true; @@ -324,7 +324,7 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp comp } DownloadFPGA_byte(b); } - + // continue to clock FPGA until ready signal goes high i=100000; while ( (i--) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE ) ) ) { @@ -396,21 +396,21 @@ static int bitparse_find_section(int bitstream_version, char section_name, unsig //---------------------------------------------------------------------------- -// Check which FPGA image is currently loaded (if any). If necessary +// Check which FPGA image is currently loaded (if any). If necessary // decompress and load the correct (HF or LF) image to the FPGA //---------------------------------------------------------------------------- void FpgaDownloadAndGo(int bitstream_version) { z_stream compressed_fpga_stream; uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00}; - + // check whether or not the bitstream is already loaded if (downloaded_bitstream == bitstream_version) return; // make sure that we have enough memory to decompress BigBuf_free(); BigBuf_Clear_ext(false); - + if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) { return; } @@ -422,14 +422,14 @@ void FpgaDownloadAndGo(int bitstream_version) } inflateEnd(&compressed_fpga_stream); - + // free eventually allocated BigBuf memory BigBuf_free(); BigBuf_Clear_ext(false); -} +} //----------------------------------------------------------------------------- -// Gather version information from FPGA image. Needs to decompress the begin +// Gather version information from FPGA image. Needs to decompress the begin // of the respective (HF or LF) image. // Note: decompression makes use of (i.e. overwrites) BigBuf[]. It is therefore // advisable to call this only once and store the results for later use. @@ -440,7 +440,7 @@ void FpgaGatherVersion(int bitstream_version, char *dst, int len) char tempstr[40] = {0x00}; z_stream compressed_fpga_stream; uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00}; - + dst[0] = '\0'; // ensure that we can allocate enough memory for decompression: @@ -492,7 +492,7 @@ void FpgaGatherVersion(int bitstream_version, char *dst, int len) } strncat(dst, tempstr, len-1); } - + strncat(dst, "\n", len-1); inflateEnd(&compressed_fpga_stream); diff --git a/client/Makefile b/client/Makefile index 3c7a33fdd..5f5df1486 100644 --- a/client/Makefile +++ b/client/Makefile @@ -7,7 +7,7 @@ include ../common/Makefile.common CC = gcc CXX = g++ -COMMON_FLAGS += -std=c99 -O3 -mpopcnt -march=native -g +COMMON_FLAGS += -std=c99 -O3 -g #VPATH = ../common ../zlib OBJDIR = obj @@ -20,7 +20,7 @@ LUAPLATFORM = generic ifneq (,$(findstring MINGW,$(platform))) LDLIBS += -L/mingw/lib -lgdi32 - CFLAGS += -I/mingw/include -D__USE_MINGW_ANSI_STDIO=1 + CFLAGS += -I/mingw/include -D__USE_MINGW_ANSI_STDIO=1 -march=x86-64 CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui MOC = $(QTDIR)/bin/moc LUAPLATFORM = mingw @@ -46,7 +46,8 @@ else ifeq ($(platform),Darwin) # OS X, QT5 detection needs this. export PKG_CONFIG_PATH=/usr/local/Cellar/qt5/5.6.1-1/lib/pkgconfig/ - CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall -O3 + CFLAGS += -march=native + CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall -O3 QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) MOC = $(shell pkg-config --variable=moc_location QtCore) @@ -64,6 +65,7 @@ else ifeq ($(platform),Darwin) LUAPLATFORM = macosx else + CFLAGS += -march=native CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall -O3 QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null) LUALIB += -ldl diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 3891d431c..5351adffa 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -834,9 +834,9 @@ int CmdHFiClassReader_Dump(const char *Cmd) { ul_switch_off_field(); memset(MAC,0,4); // AA2 authenticate credit key and git c_div_key - later store in dump block 4 - if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){ + if (!select_and_auth(CreditKEY, MAC, c_div_key, true, elite, rawkey, false)){ //try twice - for some reason it sometimes fails the first time... - if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){ + if (!select_and_auth(CreditKEY, MAC, c_div_key, true, elite, rawkey, false)){ ul_switch_off_field(); return 0; } diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 4414efa1d..f66effbed 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -24,8 +24,8 @@ int usage_legic_calccrc(void){ PrintAndLog(" c <8|16> : Crc type"); PrintAndLog(""); PrintAndLog("Samples:"); - PrintAndLog(" hf legic crc b deadbeef1122"); - PrintAndLog(" hf legic crc b deadbeef1122 u 9A c 16"); + PrintAndLog(" hf legic crc d deadbeef1122"); + PrintAndLog(" hf legic crc d deadbeef1122 u 9A c 16"); return 0; } int usage_legic_rdmem(void){ @@ -678,8 +678,8 @@ int CmdLegicCalcCrc(const char *Cmd){ while(param_getchar(Cmd, cmdp) != 0x00) { switch(param_getchar(Cmd, cmdp)) { - case 'b': - case 'B': + case 'd': + case 'D': // peek at length of the input string so we can // figure out how many elements to malloc in "data" bg=en=0; @@ -1274,4 +1274,4 @@ int CmdHFLegic(const char *Cmd) { int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); return 0; -} \ No newline at end of file +} diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 13cbee685..820fb93bc 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1081,7 +1081,7 @@ int CmdHF14AMfChk(const char *Cmd) { char filename[FILE_PATH_SIZE]={0}; char buf[13]; uint8_t *keyBlock = NULL, *p; - uint8_t stKeyBlock = 20; + uint16_t stKeyBlock = 20; sector_t *e_sector = NULL; diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 2e5046754..38d35895f 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -1431,7 +1431,7 @@ static const uint64_t crack_states_bitsliced(statelist_t *p){ #endif if ( !lstate_p ) { - __sync_fetch_and_add(&total_states_tested, bucket_states_tested); + __atomic_fetch_add(&total_states_tested, bucket_states_tested, __ATOMIC_SEQ_CST); return key; } @@ -1618,7 +1618,7 @@ out: #endif } - __sync_fetch_and_add(&total_states_tested, bucket_states_tested); + __atomic_fetch_add(&total_states_tested, bucket_states_tested, __ATOMIC_SEQ_CST); return key; } @@ -1636,8 +1636,8 @@ static void* crack_states_thread(void* x){ if (keys_found) break; else if(key != -1) { if (TestIfKeyExists(key)) { - __sync_fetch_and_add(&keys_found, 1); - __sync_fetch_and_add(&foundkey, key); + __atomic_fetch_add(&keys_found, 1, __ATOMIC_SEQ_CST); + __atomic_fetch_add(&foundkey, key, __ATOMIC_SEQ_CST); printf("*"); fflush(stdout); break; diff --git a/client/default_keys.dic b/client/default_keys.dic index 04a7c6698..3ed597a4c 100644 --- a/client/default_keys.dic +++ b/client/default_keys.dic @@ -235,8 +235,8 @@ c2b7ec7d4eb1, 003003003003, # # Data from: http://phreakerclub.com/forum/showthread.php?p=41266 -26973ea74321, -71f3a315ad26, +26973ea74321, +71f3a315ad26, 51044efb5aab, ac70ca327a04, eb0a8ff88ade, @@ -279,7 +279,7 @@ a7abbc77cc9e, f792c4c76a5c, bfb6796a11db, # -# Data from +# Data from 8829da9daf76, # # Data from Salto A/B @@ -290,7 +290,7 @@ bfb6796a11db, 2338b4913111, # # Data from stoye -cb779c50e1bd, +cb779c50e1bd, a27d3804c259, 003cc420001a, f9861526130f, @@ -316,4 +316,38 @@ d9a37831dce5, c5cfe06d9ea3, c0dece673829, # -a56c2df9a26d, \ No newline at end of file +a56c2df9a26d, +# +# Data from: https://pastebin.com/vbwast74 +# +2031d1e57a3b, +68d3f7307c89, +9189449ea24e, +568c9083f71c, +53c11f90822a, +# Vigik Keys +# Various sources : +# * https://github.com/DumpDos/Vigik +# * http://newffr.com/viewtopic.php?&forum=235&topic=11559 +# * Own dumps +021209197591, +22729a9bd40f, +2ef720f2af76, +38fcf33072e0, +424c41524f4e, +484558414354, +49fae4e3849f, +4a6352684677, +509359f131b1, +62d0c424ed8e, +66d2b7dc39ef, +6bc1e1ae547d, +6c78928e1317, +89347350bd36, +8ad5517b4b18, +8fa1d601d0a2, +a22ae129c013, +a6cac2886412, +aa0720018738, +e64a986a5d94, +bf1f4424af76, diff --git a/client/default_pwd.dic b/client/default_pwd.dic index 2c63e53ca..b0659a091 100644 --- a/client/default_pwd.dic +++ b/client/default_pwd.dic @@ -4,6 +4,8 @@ 000D8787, # ref. http://kazus.ru/forums/showpost.php?p=1045937&postcount=77 05D73B9F, +# ref. http://www.proxmark.org/forum/viewtopic.php?= +89A69E60, # Default pwd, simple: 00000000, 11111111, diff --git a/client/proxmark3.c b/client/proxmark3.c index 670b9720e..b7bdb0b13 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -242,6 +242,7 @@ static void set_my_executable_path(void) my_executable_path[path_length] = '\0'; my_executable_directory = (char *)malloc(dirname_length + 2); strncpy(my_executable_directory, my_executable_path, dirname_length+1); + my_executable_directory[dirname_length+1] = '\0'; } } } diff --git a/client/scripts/legic.lua b/client/scripts/legic.lua index 73ef47917..69605781b 100644 --- a/client/scripts/legic.lua +++ b/client/scripts/legic.lua @@ -1,11 +1,11 @@ ---[[ +--[[ if it don't works with you tag-layout - be so kind and let me know ;-) Tested on Tags with those Layouts: (example) Legic-Prime Layout with 'Kaba Group Header' +----+----+----+----+----+----+----+----+ - 0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 9f | + 0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 9f | +----+----+----+----+----+----+----+----+ 0x08| ff | 00 | 00 | 00 | 11 |Bck0|Bck1|Bck2| +----+----+----+----+----+----+----+----+ @@ -33,7 +33,7 @@ kghC = crc8 over MCD + MSN0..MSN2 + UID (example) Legic-Cash on MIM256/1024 tag' (37 bytes) +----+----+----+----+----+----+----+----+ - 0x00|Seg0|Seg1|Seg2|Seg3|SegC|STP0|STP1|STP2| + 0x00|Seg0|Seg1|Seg2|Seg3|SegC|STP0|STP1|STP2| +----+----+----+----+----+----+----+----+ 0x08|STP3|STP4|STP5|STP6| 01 |CURh|CURl|LIMh| +----+----+----+----+----+----+----+----+ @@ -58,7 +58,7 @@ CHK = crc16 over SHD + LRS + CV (example) Legic-Prime Layout 'gantner unsegmented user-credential' +----+----+----+----+----+----+----+----+ - 0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 08 | + 0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 08 | +----+----+----+----+----+----+----+----+ 0x08|Stp0|Stp1|Stp2|Stp3|Stp4|Dat0|Dat1|uCRC| <- addr 0x08..0x0f is WRP +----+----+----+----+----+----+----+----+ @@ -75,11 +75,11 @@ uCRC = crc8 over addr 0x00..0x03+0x07..0x0E (example) Legic-Prime Layout 'gantner unsegmented Master-Token (IAM) with a stamp_len of 4' +----+----+----+----+----+----+----+----+ - 0x00|MCD |MSN0|MSN1|MSN2|MCC | 20 | f8 | 08 | + 0x00|MCD |MSN0|MSN1|MSN2|MCC | 20 | f8 | 08 | +----+----+----+----+----+----+----+----+ 0x08|Stp0|Stp1|Stp2|Stp3| 00 | 00 | 00 |CRC1| +----+----+----+----+----+----+----+----+ - 0x10| 00 | 00 | 00 | 00 | 00 |CRC2| + 0x10| 00 | 00 | 00 | 00 | 00 |CRC2| +----+----+----+----+----+----+ MCD = Manufacturer ID MSN = Manufacturer SerialNumber @@ -106,36 +106,36 @@ it's kinda interactive with following commands in three categories: rt => read Tag as => add Segment mt => make Token wt => write Tag es => edit Segment Header et => edit Token data ed => edit Segment Data tk => toggle KGH-Flag - File I/O rs => remove Segment - ----------------- cc => check Segment-CRC - lf => load File ck => check KGH - sf => save File ds => dump Segments - xf => xor to File - - + File I/O rs => remove Segment + ----------------- cc => check Segment-CRC + lf => load File ck => check KGH + sf => save File ds => dump Segments + xf => xor to File + + (partially) known Segments Virtual Tags Script Output --------------------------- ------------------------------- ------------------------ dlc => dump Legic-Cash ct => copy mainTag to backupTag tac => toggle ansicolors - elc => edit Legic-Cash tc => copy backupTag to mainTag - d3p => dump 3rd-Party-Cash tt => switch mainTag & backupTag - e3p => edit 3rd-Party-Cash di => dump mainTag + elc => edit Legic-Cash tc => copy backupTag to mainTag + d3p => dump 3rd-Party-Cash tt => switch mainTag & backupTag + e3p => edit 3rd-Party-Cash di => dump mainTag do => dump backupTag - - + + rt: 'read tag' - reads a tag placed near to the PM3 wt: 'write tag' - writes the content of the 'virtual inTag' to a tag placed near to th PM3 without the need of changing anything - MCD,MSN,MCC will be read from the tag before and applied to the output. - + lf: 'load file' - load a (xored) file from the local Filesystem into the 'virtual inTag' sf: 'save file' - saves the 'virtual inTag' to the local Filesystem (xored with Tag-MCC) xf: 'xor file' - saves the 'virtual inTag' to the local Filesystem (xored with choosen MCC - use '00' for plain values) - + ct: 'copy tag' - copy the 'virtual Tag' to a second 'virtual TAG' - not usefull yet, but inernally needed tc: 'copy tag' - copy the 'second virtual Tag' to 'virtual TAG' - not usefull yet, but inernally needed tt: 'toggle tag' - copy mainTag to BackupTag and backupTag to mainTag - + di: 'dump mainTag' - shows the current content of the 'virtual Tag' do: 'dump backupTag' - shows the current content of the 'virtual outTag' ds: 'dump Segments' - will show the content of a selected Segment @@ -151,25 +151,25 @@ it's kinda interactive with following commands in three categories: 'Kaba Group Header CRC calculation' tk: 'toggle KGH' - toglle the (script-internal) flag for kgh-calculation for a segment xc: 'etra c' - show string that was used to calculate the kgh-crc of a segment - + dlc: 'dump Legic-Cash' - show balance and checksums of a Legic-Cash Segment elc: 'edit Legic-Cash' - edit values of a Legic-Cash Segment d3p: 'dump 3rd Party' - show balance, history and checksums of a (yet) unknown 3rd-Party Cash Segment e3p: 'edit 3rd Party' - edit Data in 3rd-Party Cash Segment - + tac: 'toggle ansicolors'- switch on and off the colored text-output of this script default can be changed by setting the variable 'colored_output' to false ]] currentTag="inTAG" ---- +--- -- requirements local utils = require('utils') local getopt = require('getopt') local ansicolors = require('ansicolors') ---- +--- -- global variables / defines local bxor = bit32.bxor local bbit = bit32.extract @@ -201,7 +201,7 @@ function load_colors(onoff) acmagenta= ansicolors.magenta acoff = ansicolors.reset else - -- 'no color' + -- 'no color' acgreen = "" accyan = "" acred = "" @@ -215,20 +215,20 @@ end --- -- curency-codes for Legic-Cash-Segments (ISO 4217) local currency = { - ["03d2"]="EUR", - ["0348"]="USD", + ["03d2"]="EUR", + ["0348"]="USD", ["033A"]="GBP", ["02F4"]="CHF" } ---- +--- -- This is only meant to be used when errors occur function oops(err) print(acred.."ERROR: "..acoff ,err) return nil, err end ---- +--- -- Usage help function help() print(desc) @@ -236,10 +236,10 @@ function help() print("Example usage: "..example) end ---- +--- -- table check helper -function istable(t) - return type(t) == 'table' +function istable(t) + return type(t) == 'table' end --- @@ -262,7 +262,7 @@ function deepCopy(object) return _copy(object) end ---- +--- -- xor single byte function xorme(hex, xor, index) if ( index >= 23 ) then @@ -272,7 +272,7 @@ function xorme(hex, xor, index) end end ---- +--- -- (de)obfuscate bytes function xorBytes(inBytes, crc) local bytes = {} @@ -289,13 +289,14 @@ function xorBytes(inBytes, crc) end end ---- +--- -- check availability of file function file_check(file_name) - local file_found=io.open(file_name, "r") + local file_found=io.open(file_name, "r") if file_found==nil then return false else + file_found:close() return true end end @@ -334,20 +335,19 @@ function bytesToTable(bytes, bstart, bend) return t end ---- +--- -- read file into table function getInputBytes(infile) local line local bytes = {} - local fhi,err = io.open(infile) + local fhi,err = io.open(infile,"rb") if err then oops("faild to read from file ".. infile); return false; end - while true do - line = fhi:read() - if line == nil then break end - for byte in line:gmatch("%w+") do - table.insert(bytes, byte) - end - end + + file_data = fhi:read("*a"); + for i = 1, #file_data + do + bytes[i] = string.format("%x",file_data:byte(i)) + end fhi:close() if (bytes[7]=='00') then return false end print(#bytes .. " bytes from "..infile.." loaded") @@ -357,7 +357,7 @@ end --- -- create tag-table helper function createTagTable() - local t={ + local t={ ['MCD'] = '00', ['MSN0']= '11', ['MSN1']= '22', @@ -381,7 +381,7 @@ function createTagTable() return t end ---- +--- -- put bytes into tag-table function bytesToTag(bytes, tag) if(istable(tag)) then @@ -407,14 +407,14 @@ function bytesToTag(bytes, tag) tag.data=bytesToTable(bytes, 10, 13) tag.Bck=bytesToTable(bytes, 14, 20) tag.MTC=bytesToTable(bytes, 21, 22) - + print(acgreen.."Tag-Type: ".. tag.Type..acoff) if (tag.Type=="SAM" and #bytes>23) then tag=segmentsToTag(bytes, tag) print(acgreen..(#tag.SEG+1).." Segment(s) found"..acoff) -- unsegmented Master-Token - -- only tag-data - else + -- only tag-data + else for i=0, #tag.Bck do table.insert(tag.data, tag.Bck[i]) end @@ -429,8 +429,8 @@ function bytesToTag(bytes, tag) return oops("tag is no table in: bytesToTag ("..type(tag)..")") end ---- --- put segments from byte-table to tag-table +--- +-- put segments from byte-table to tag-table function segmentsToTag(bytes, tag) if(#bytes>23) then local start=23 @@ -447,7 +447,7 @@ function segmentsToTag(bytes, tag) return tag else return oops("tag is no table in: segmentsToTag ("..type(tag)..")") end else print("no Segments: must be a MIM22") end -end +end --- -- read Tag-Table in bytes-table @@ -501,14 +501,14 @@ function tagToBytes(tag) end --- PM3 I/O --- ---- +--- -- read from pm3 into virtual-tag function readFromPM3() - local tag, bytes, infile + local tag, bytes, infile infile="legic.temp" core.console("hf legic reader") - core.console("hf legic save "..infile) - tag=readFile(infile) + core.console("hf legic esave "..infile) + tag=readFile(infile..".bin") return tag end @@ -522,7 +522,7 @@ function writeToTag(tag) return end -- get used bytes / tag-len - if(istable(tag.SEG)) then + if(istable(tag.SEG)) then if (istable(tag.Bck)) then for i=0, #tag.SEG do taglen=taglen+tag.SEG[i].len+5 @@ -539,7 +539,7 @@ function writeToTag(tag) tag.MSN2 = outbytes[4] tag.MCC = outbytes[5] -- recheck all segments-crc/kghcrc (only on a credential) - if(istable(tag.Bck)) then + if(istable(tag.Bck)) then checkAllSegCrc(tag) checkAllKghCrc(tag) local uid_new=tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 @@ -555,10 +555,10 @@ function writeToTag(tag) bytes=tagToBytes(tag) -- master-token-crc if (tag.Type~="SAM") then bytes[22]=calcMtCrc(bytes) end - if (bytes) then + if (bytes) then print("write temp-file '"..filename.."'") print(accyan) - writeFile(bytes, filename) + writeFile(bytes, filename) --writeToTag(bytes, taglen, 'MylegicClone.hex') print(acoff) end @@ -577,14 +577,14 @@ function writeToTag(tag) core.console(cmd) --print(cmd) elseif (i == 6) then - -- write DCF in reverse order (requires 'mosci-patch') + -- write DCF in reverse order (requires 'mosci-patch') cmd = 'hf legic write 0x05 0x02' print(acgreen..cmd..acoff) core.console(cmd) --print(cmd) else print(acgreen.."skip byte 0x05 - will be written next step"..acoff) - end + end utils.Sleep(0.2) end end @@ -601,7 +601,7 @@ function readFile(filename) return oops("input file: "..filename.." not found") else bytes = getInputBytes(filename) - if (bytes == false) then return oops('couldnt get input bytes') + if (bytes == false) then return oops('couldnt get input bytes') else -- make plain bytes bytes = xorBytes(bytes,bytes[5]) @@ -616,7 +616,7 @@ function readFile(filename) return tag end ---- +--- -- write bytes to file function writeFile(bytes, filename) if (filename~='MylegicClone.hex') then @@ -631,9 +631,9 @@ function writeFile(bytes, filename) if err then oops("OOps ... faild to open output-file ".. filename) end bytes=xorBytes(bytes, bytes[5]) for i = 1, #bytes do - if (bcnt == 0) then + if (bcnt == 0) then line=bytes[i] - elseif (bcnt <= 7) then + elseif (bcnt <= 7) then line=line.." "..bytes[i] end if (bcnt == 7) then @@ -651,12 +651,12 @@ function writeFile(bytes, filename) end --- Map related --- ---- +--- -- make tagMap function makeTagMap() local tagMap={} - if (#tagMap==0) then - tagMap['name']=input(accyan.."enter Name for this Map: "..acoff , "newTagMap") + if (#tagMap==0) then + tagMap['name']=input(accyan.."enter Name for this Map: "..acoff , "newTagMap") tagMap['mappings']={} tagMap['crc8']={} -- insert fixed Tag-CRC @@ -664,8 +664,8 @@ function makeTagMap() tagMap['crc16']={} end print(accyan.."new tagMap created"..acoff) - return tagMap -end + return tagMap +end --- -- save mapping to file @@ -676,11 +676,11 @@ function saveTagMap(map, filename) if (answer==false) then return print("user abort") end end end - + local line local fho,err = io.open(filename, "w") if err then oops("OOps ... faild to open output-file ".. filename) end - + -- write line to new file for k, v in pairs(map) do if (istable(v)) then @@ -757,17 +757,17 @@ function loadTagMap(filename) local fhi,err = io.open(filename) while true do line = fhi:read() - if line == nil then - break + if line == nil then + break else fields=split(line) end - if (#fields==2) then + if (#fields==2) then if (fields[1]=='offset') then offset=tonumber(fields[2],10) end -- map-name - map[fields[1]]=fields[2] + map[fields[1]]=fields[2] elseif (fields[1]=='mappings') then m=m+1 temp={} @@ -775,9 +775,9 @@ function loadTagMap(filename) temp['name']=fields[3] temp['start']=tonumber(fields[4], 10) temp['end']=tonumber(fields[5], 10) - if(temp['start']>22) then - temp['start']=temp['start']+offset - temp['end']=temp['end']+offset + if(temp['start']>22) then + temp['start']=temp['start']+offset + temp['end']=temp['end']+offset end if (tonumber(fields[6], 10)==1) then temp['highlight']= true else temp['highlight']= false end @@ -792,8 +792,8 @@ function loadTagMap(filename) temp['seq']=seqstr2tbl(s) for k, v in pairs(temp['seq']) do if(tonumber(v, 10)>22) then v=tonumber(v, 10)+offset end - temp['seq'][k]=tonumber(v, 10) - end + temp['seq'][k]=tonumber(v, 10) + end table.insert(map.crc8, temp) end end @@ -854,18 +854,18 @@ function checkMapCrc8(tagMap, bytes, n) local res=false if (#tagMap.crc8>0) then if(istable(tagMap.crc8[n])) then - temp="" + temp="" for k2, v2 in pairs(tagMap.crc8[n]) do if (istable(v2)) then temp=temp..tbl2seqstr(v2) end - end + end local tempres="" local tempres=getSequences(bytes, temp) tempres=("%02x"):format(utils.Crc8Legic(tempres)) if (bytes[tagMap.crc8[n]['pos']]==tempres) then res=true - end + end end end return res @@ -875,19 +875,19 @@ end -- edit existing Map function editTagMap(tag, tagMap) local t = [[ - Data: dm = show dr = dump raw + Data: dm = show dr = dump raw Mappings: im = insert am = add rm = remove - CRC8: ac8 = add sc8 = show rc8 = remove + CRC8: ac8 = add sc8 = show rc8 = remove : q = exit h = Help ]] --if(#tagMap.mappings==0) then oops("no mappings in tagMap"); return tagMap end print("tagMap edit-mode submenu") - repeat + repeat x=input('tagMap submenu:', 'h') if (x=='h') then print(t) elseif (x=='dm') then tagMmap=dumpTagMap(tag, tagMap) elseif (x=='dr') then tagMmap=dumpMap(tag, tagMap) - elseif (x=='rc8') then + elseif (x=='rc8') then if (istable(tagMap.crc8)) then local x1 = selectTableEntry(tagMap.crc8, "select number of CRC8 to remove:") if (istable(tagMap.crc8[x1])) then @@ -913,14 +913,14 @@ Mappings: im = insert am = add rm = remove table.insert(tagMap.crc8, temp) end end - elseif (string.sub(x, 1, 3)=='sc8') then + elseif (string.sub(x, 1, 3)=='sc8') then local bytes=tagToBytes(tag) local res, pos -- trigger manually by sc8 <'4digit' checkadd> <'seqeuence-string'> -- e.g.: sc8 0027 1-4,23-36 - if (string.len(x)>=9) then + if (string.len(x)>=9) then pos=tonumber(string.sub(x, 5, 8), 10) - x=string.sub(x, 9, string.len(x)) + x=string.sub(x, 9, string.len(x)) print("x: "..x.." - pos:"..pos) else x=selectTableEntry(tagMap.crc8, "select CRC:") @@ -960,23 +960,23 @@ function dumpMap(tag, tagMap) print(accyan.."Tag uses "..dend.." bytes:"..acoff) for i=dstart, dend do if (check4MappedByte(i, tagMap) and not check4MapCrc8(i, tagMap) and not check4Highlight(i, tagMap)) then io.write(""..acyellow) - elseif (check4MapCrc8(i, tagMap)) then + elseif (check4MapCrc8(i, tagMap)) then if ( checkMapCrc8(tagMap, bytes, isPosCrc8(tagMap, i) ) ) then io.write(""..acgreen) - else + else io.write(""..acred) end - else - io.write(""..acoff) + else + io.write(""..acoff) end -- highlighted mapping if (check4Highlight(i, tagMap)) then io.write(""..acmagenta) end - + io.write(bytes[i]) - if (i%8==0) then io.write("\n") + if (i%8==0) then io.write("\n") else io.write(" ") end end - + io.write("\n"..acoff) end @@ -1053,14 +1053,14 @@ end --- -- add interactive mapping function addMapping(tag, tagMap, x) - if (type(x)~="number") then x=#tagMap.mappings+1 end + if (type(x)~="number") then x=#tagMap.mappings+1 end local bytes=tagToBytes(tag) local myMapping={} myMapping['name'] =input(accyan.."enter Maping-Name:"..acoff, string.format("mapping %d", #tagMap.mappings+1)) myMapping['start']=tonumber(input(accyan.."enter start-addr:"..acoff, '1'), 10) myMapping['end'] =tonumber(input(accyan.."enter end-addr:"..acoff, #bytes), 10) myMapping['highlight']=confirm("set highlighted") - table.insert(tagMap.mappings, x, myMapping) + table.insert(tagMap.mappings, x, myMapping) return tagMap end @@ -1074,7 +1074,7 @@ function deleteMapping(tag, tagMap) else oops("deleteMapping: got type = "..type(d).." - expected type = 'number'") end end - return tagMap + return tagMap end --- @@ -1107,7 +1107,7 @@ function mapAllSegments(tag, tagMap) --tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." HDR", v['start'], v['start']+3) tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." CRC", v['start']+4, v['start']+4, true) table.insert(tagMap.crc8, {name = 'Segment '..("%02d"):format(v['index']).." CRC", pos=v['start']+4, seq={1,4,v['start'],v['start']+3}} ) - if(WRC>WRP) then + if(WRC>WRP) then WRPC=WRC tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." WRC", v['start']+5, v['start']+5+WRC-1, true) elseif (WRP>WRC and WRC>0) then @@ -1119,7 +1119,7 @@ function mapAllSegments(tag, tagMap) tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." WRP", v['start']+5, v['start']+5+WRP-1, true) end tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." data", v['start']+5+WRPC, v['end'], false) - + end print(#segs.." Segments mapped") else @@ -1128,7 +1128,7 @@ function mapAllSegments(tag, tagMap) return tagMap end ---- +--- -- map all token data function mapTokenData(tagMap, mname, mstart, mend, mhigh) --if ( not mhigh ) then mhigh=false end @@ -1137,7 +1137,7 @@ function mapTokenData(tagMap, mname, mstart, mend, mhigh) myMapping['start']=mstart myMapping['end'] =mend myMapping['highlight']=mhigh - table.insert(tagMap.mappings, myMapping) + table.insert(tagMap.mappings, myMapping) return tagMap end @@ -1189,7 +1189,7 @@ function dumpCDF(tag) res = res..accyan.."MCD: "..acoff..tag.MCD..accyan.." MSN: "..acoff..tag.MSN0.." "..tag.MSN1.." "..tag.MSN2..accyan.." MCC: "..acoff..tag.MCC.."\n" res = res.."DCF: "..tag.DCFl.." "..tag.DCFh..", Token_Type="..tag.Type.." (OLE="..tag.OLE.."), Stamp_len="..tag.Stamp_len.."\n" res = res.."WRP="..tag.WRP..", WRC="..tag.WRC..", RD="..tag.RD..", raw="..tag.raw..((tag.raw=='9f') and (", SSC="..tag.SSC.."\n") or "\n") - + -- credential (end-user tag) if (tag.Type=="SAM" and tag.raw=='9f') then res = res.."Remaining Header Area\n" @@ -1204,8 +1204,8 @@ function dumpCDF(tag) for i=0, (#tag.MTC) do res = res..tag.MTC[i].." " end - - + + -- Master Token specific elseif (tag.Type~="SAM") then res = res .."Master-Token Area\nStamp: " @@ -1221,13 +1221,13 @@ function dumpCDF(tag) local mtcrc=calcMtCrc(bytes) res=res.."\nMaster-Token CRC: " res = res ..tag.MTC[1].." ("..((tag.MTC[1]==mtcrc) and "valid" or "error")..")" - - + + -- 'Gantner User-Credential' specific elseif (tag.Type=="SAM" and (tag.raw=='08' or tag.raw=='09')) then print(acgreen.."Gantner Detected"..acoff) end - + return res else print("no valid Tag in dumpCDF") end end @@ -1241,13 +1241,13 @@ function dumpSegment(tag, index) local res="" --result local raw="" --raw-header -- segment - if ( (istable(tag.SEG[i])) and tag.Type=="SAM" and tag.raw=="9f") then + if ( (istable(tag.SEG[i])) and tag.Type=="SAM" and tag.raw=="9f") then if (istable(tag.SEG[i].raw)) then for k,v in pairs(tag.SEG[i].raw) do raw=raw..v.." " end end - + -- segment header res = res..accyan.."Segment "..("%02d"):format(tag.SEG[i].index)..acoff..": " res = res .."raw header: "..string.sub(raw,0,-2)..", flag="..tag.SEG[i].flag..", (valid="..("%x"):format(tag.SEG[i].valid)..", last="..("%x"):format(tag.SEG[i].last).."), " @@ -1255,7 +1255,7 @@ function dumpSegment(tag, index) res = res .."RD="..("%02x"):format(tag.SEG[i].RD)..", CRC="..tag.SEG[i].crc.." " res = res .."("..(checkSegmentCrc(tag, i) and acgreen.."valid" or acred.."error") ..acoff..")" raw="" - + -- WRC protected if ((tag.SEG[i].WRC>0)) then @@ -1265,7 +1265,7 @@ function dumpSegment(tag, index) dp=dp+1 end end - + -- WRP mprotected if (tag.SEG[i].WRP>tag.SEG[i].WRC) then res = res .."\nRemaining write protected area:\n" @@ -1274,7 +1274,7 @@ function dumpSegment(tag, index) dp=dp+1 end end - + -- payload if (#tag.SEG[i].data-dp>0) then res = res .."\nRemaining segment payload:\n" @@ -1282,14 +1282,14 @@ function dumpSegment(tag, index) res = res..tag.SEG[i].data[dp].." " dp=dp+1 end - if (tag.SEG[i].kgh) then + if (tag.SEG[i].kgh) then res = res..tag.SEG[i].data[dp].." (KGH: "..(checkKghCrc(tag, i) and acgreen.."valid" or acred.."error") ..acoff..")" else res = res..tag.SEG[i].data[dp] end end dp=0 - return res + return res else - return print("Segment not found") + return print("Segment not found") end end @@ -1317,30 +1317,30 @@ function dump3rdPartyCash1(tag , seg) local lastbal0=tonumber(tag.SEG[seg].data[39]..tag.SEG[seg].data[40] ,16) local lastbal1=tonumber(tag.SEG[seg].data[41]..tag.SEG[seg].data[42] ,16) local lastbal2=tonumber(tag.SEG[seg].data[43]..tag.SEG[seg].data[44] ,16) - + test="" -- display decoded/known stuff print("\n------------------------------") print("Tag-ID:\t\t "..uid) - print("Stamp:\t\t "..stamp) + print("Stamp:\t\t "..stamp) print("UID-Mapping: \t\t"..("%06d"):format(tonumber(tag.SEG[seg].data[46]..tag.SEG[seg].data[47]..tag.SEG[seg].data[48], 16))) - print("------------------------------") - print("checksum 1:\t\t "..tag.SEG[seg].data[31].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 19, 30)), tag.SEG[seg].data[31])..")") + print("------------------------------") + print("checksum 1:\t\t "..tag.SEG[seg].data[31].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 19, 30)), tag.SEG[seg].data[31])..")") print("checksum 2:\t\t "..tag.SEG[seg].data[34].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 32, 33)), tag.SEG[seg].data[34])..")") - print("checksum 3:\t\t "..tag.SEG[seg].data[37].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 35, 36)), tag.SEG[seg].data[37])..")") - + print("checksum 3:\t\t "..tag.SEG[seg].data[37].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 35, 36)), tag.SEG[seg].data[37])..")") + print("checksum 4:\t\t "..tag.SEG[seg].data[55].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 46, 54)), tag.SEG[seg].data[55])..")") - print("checksum 5:\t\t "..tag.SEG[seg].data[62].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 56, 61)), tag.SEG[seg].data[62])..")") + print("checksum 5:\t\t "..tag.SEG[seg].data[62].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 56, 61)), tag.SEG[seg].data[62])..")") print("checksum 6:\t\t "..tag.SEG[seg].data[73].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 63, 72)), tag.SEG[seg].data[73])..")") - print("checksum 7:\t\t "..tag.SEG[seg].data[89].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 74, 88)), tag.SEG[seg].data[89])..")") - print("------------------------------") + print("checksum 7:\t\t "..tag.SEG[seg].data[89].." ("..compareCrc(utils.Crc8Legic(uid..dumpTable(tag.SEG[seg].data, "", 74, 88)), tag.SEG[seg].data[89])..")") + print("------------------------------") print(string.format("Balance:\t\t %3.2f", balance/100).." ".."("..compareCrc(balancecrc, tag.SEG[seg].data[34])..")") - print(string.format("Shadow:\t\t\t %3.2f", mirror/100).." ".."("..compareCrc(balancecrc, tag.SEG[seg].data[37])..")") - print("------------------------------") - print(string.format("History 1:\t\t %3.2f", lastbal0/100)) - print(string.format("History 2:\t\t %3.2f", lastbal1/100)) - print(string.format("History 3:\t\t %3.2f", lastbal2/100)) - print("------------------------------\n") + print(string.format("Shadow:\t\t\t %3.2f", mirror/100).." ".."("..compareCrc(balancecrc, tag.SEG[seg].data[37])..")") + print("------------------------------") + print(string.format("History 1:\t\t %3.2f", lastbal0/100)) + print(string.format("History 2:\t\t %3.2f", lastbal1/100)) + print(string.format("History 3:\t\t %3.2f", lastbal2/100)) + print("------------------------------\n") end --- @@ -1387,11 +1387,11 @@ function print3rdPartyCash1(tag, x) print() print("\t\tyet unknown: "..tag.SEG[x].data[38]) print() - print("\t\tHisatory 1: "..dumpTable(tag.SEG[x].data, "", 39, 40)) - print("\t\tHisatory 2: "..dumpTable(tag.SEG[x].data, "", 41, 42)) - print("\t\tHisatory 3: "..dumpTable(tag.SEG[x].data, "", 43, 44)) + print("\t\tHisatory 1: "..dumpTable(tag.SEG[x].data, "", 39, 40)) + print("\t\tHisatory 2: "..dumpTable(tag.SEG[x].data, "", 41, 42)) + print("\t\tHisatory 3: "..dumpTable(tag.SEG[x].data, "", 43, 44)) print() - print("\t\tyet unknown: "..tag.SEG[x].data[45]) + print("\t\tyet unknown: "..tag.SEG[x].data[45]) print() print("\t\tKGH-UID HEX: "..dumpTable(tag.SEG[x].data, "", 46, 48)) print("\t\tBlock 4: "..dumpTable(tag.SEG[x].data, "", 49, 54)) @@ -1428,12 +1428,12 @@ function makeToken() ttype=ttype..k..") "..v.." " end mtq=tonumber(input("select number for Token-Type\n"..ttype, '1'), 10) - if (type(mtq)~="number") then return print("selection invalid!") + if (type(mtq)~="number") then return print("selection invalid!") elseif (mtq>#mt.Type) then return print("selection invalid!") else print("Token-Type '"..mt.Type[mtq].."' selected") end local raw=calcHeaderRaw(mt.WRP[mtq], mt.WRC[mtq], mt.RD[mtq]) local mtCRC="00" - + bytes={"01", "02", "03", "04", "cb", string.sub(mt.DCF[mtq], 0, 2), string.sub(mt.DCF[mtq], 3), raw, "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00"} @@ -1453,7 +1453,7 @@ function makeToken() return bytesToTag(bytes, tempTag) end ---- +--- -- edit token-data function editTag(tag) -- for simulation it makes sense to edit everything @@ -1463,14 +1463,14 @@ function editTag(tag) if (confirm(acyellow.."do you want to edit non-writeable values (e.g. for simulation)?"..acoff)) then edit_tag=edit_sim else edit_tag=edit_real end - + if(istable(tag)) then for k,v in pairs(tag) do if(type(v)~="table" and type(v)~="boolean" and string.find(edit_tag, k)) then tag[k]=input("value for: "..accyan..k..acoff, v) end end - + if (tag.Type=="SAM") then ttype="Header"; else ttype="Stamp"; end if (confirm(acyellow.."do you want to edit "..ttype.." Data?"..acoff)) then -- master-token specific @@ -1481,9 +1481,9 @@ function editTag(tag) -- rest of stamp-bytes are in tag.data 0..n for i=0, (tonumber(0xfc ,10)-("%d"):format('0x'..tag.DCFh))-2 do tag.data[i]=input(ttype.. i+1 ..": ", tag.data[i]) - end + end else - --- on credentials byte7 should always be 9f and byte8 ff + --- on credentials byte7 should always be 9f and byte8 ff -- on Master-Token not (even on SAM63/64 not) -- tag.SSC=input(ttype.."0: ", tag.SSC) for i=0, #tag.data do @@ -1491,18 +1491,18 @@ function editTag(tag) end end end - + bytes=tagToBytes(tag) - + --- check data-consistency (calculate tag.raw) bytes[8]=calcHeaderRaw(tag.WRP, tag.WRC, tag.RD) - + --- Master-Token specific -- should be triggered if a SAM was converted to a non-SAM (user-Token to Master-Token) -- or a Master-Token has being edited (also SAM64 & SAM63 - which are in fact Master-Token) - if(tag.Type~="SAM" or bytes[6]..bytes[7]~="60ea") then + if(tag.Type~="SAM" or bytes[6]..bytes[7]~="60ea") then -- calc new Master-Token crc - bytes[22]=calcMtCrc(bytes) + bytes[22]=calcMtCrc(bytes) else -- ensure tag.SSC set to 'ff' on credential-token (SAM) bytes[9]='ff' @@ -1511,7 +1511,7 @@ function editTag(tag) bytes[21]='00' bytes[22]='00' end - + tag=bytesToTag(bytes, tag) end end @@ -1522,16 +1522,16 @@ function calcHeaderRaw(wrp, wrc, rd) local res wrp=("%02x"):format(tonumber(wrp, 10)) rd=tonumber(rd, 16) - res=("%02x"):format(tonumber(wrp, 16)+tonumber(wrc.."0", 16)+((rd>0) and tonumber("8"..(rd-1), 16) or 0)) + res=("%02x"):format(tonumber(wrp, 16)+tonumber(wrc.."0", 16)+((rd>0) and tonumber("8"..(rd-1), 16) or 0)) return res end ---- +--- -- determine TagType (bits 0..6 of DCFlow) function getTokenType(DCFl) --[[ - 0x00–0x2f IAM - 0x30–0x6f SAM + 0x00–0x2f IAM + 0x30–0x6f SAM 0x70–0x7f GAM ]]-- local tt = tonumber(bbit("0x"..DCFl,0,7),10) @@ -1571,8 +1571,8 @@ function getSegmentData(bytes, start, index) ['data'] = {}, ['kgh'] = false } - if (bytes[start]) then - local i + if (bytes[start]) then + local i -- #index segment.index = index -- flag = high nibble of byte 1 @@ -1598,12 +1598,12 @@ function getSegmentData(bytes, start, index) segment.data[i]=bytes[start+5+i] end return segment - else return false; + else return false; end end --- --- get index, start-aadr, length and content +-- get index, start-aadr, length and content function getSegmentStats(bytes) local sStats = {} local sValid, sLast, sLen, sStart, x @@ -1679,7 +1679,7 @@ function editSegment(tag, index) else print("Segment with Index: "..("%02d"):format(index).." not found in Tag") return false end - regenSegmentHeader(tag.SEG[index]) + regenSegmentHeader(tag.SEG[index]) print("\n"..dumpSegment(tag, index).."\n") return tag end @@ -1692,7 +1692,7 @@ function editSegmentData(data) if (istable(data)) then for i=0, #data-1 do data[i]=input(accyan.."Data"..i..acoff..": ", data[i]) - end + end if (lc) then data=fixLegicCash(data) end return data else @@ -1704,7 +1704,7 @@ end -- list available segmets in virtual tag function segmentList(tag) local i - local res = "" + local res = "" if (istable(tag.SEG[0])) then for i=0, #tag.SEG do res = res .. tag.SEG[i].index .. " " @@ -1719,7 +1719,7 @@ end -- helper to selecting a segment function selectSegment(tag) local sel - if (istable(tag.SEG[0])) then + if (istable(tag.SEG[0])) then print("availabe Segments:\n"..segmentList(tag)) sel=input("select Segment: ", '00') sel=tonumber(sel,10) @@ -1730,7 +1730,7 @@ function selectSegment(tag) return false end end - + --- -- add segment function addSegment(tag) @@ -1768,16 +1768,16 @@ function getSegmentStamp(seg, bytes) local stamp="" local stamp_len=7 --- the 'real' stamp on MIM is not really easy to tell for me since the 'data-block' covers stamp0..stampn+data0..datan - -- there a no stamps longer than 7 bytes & they are write-protected by default , and I have not seen user-credntials + -- there a no stamps longer than 7 bytes & they are write-protected by default , and I have not seen user-credntials -- with stamps smaller 3 bytes (except: Master-Token) - -- WRP -> Read/Write Protection + -- WRP -> Read/Write Protection -- WRC -> Read/Write Condition -- RD depends on WRC - if WRC > 0 and RD=1: only reader with matching #WRC of Stamp-bytes in thier Database have Read-Access to the Tag if (seg.WRP<7) then stamp_len=(seg.WRP) end for i=1, (stamp_len) do stamp=stamp..seg.data[i-1] end - if (bytes) then + if (bytes) then stamp=str2bytes(stamp) return stamp else return stamp end @@ -1807,15 +1807,15 @@ function autoSelectSegment(tag, s) --- search for desired segment-type -- 3rd Party Segment if (s=="3rdparty") then - repeat + repeat io.write(". ") x=x-1 res=check43rdPartyCash1(uid, tag.SEG[x].data) until ( res or x==0 ) - end + end -- Legic-Cash Segment if (s=="legiccash") then - repeat + repeat io.write(". ") x=x-1 res=check4LegicCash(tag.SEG[x].data) @@ -1828,9 +1828,9 @@ function autoSelectSegment(tag, s) return x end --- - -- nothing found - io.write(acyellow.."no Segment found\n"..acoff) - return -1 + -- nothing found + io.write(acyellow.."no Segment found\n"..acoff) + return -1 end --- @@ -1906,8 +1906,8 @@ function edit3rdPartyCash1(tag, x) print(" done") -- fix known checksums tag.SEG[x].data=fix3rdPartyCash1(uid, tag.SEG[x].data) - end - return tag + end + return tag end --- @@ -1924,7 +1924,7 @@ function editLegicCash(data) rid=tonumber(data[18]..data[19]..data[20], 16) -- transaction counter value tcv=tonumber(data[29], 16) - + -- edit currency if (confirm(accyan.."change Currency?"..acoff)) then for k, v in pairs(currency) do io.write(k .. " = " .. v .. "\n") end @@ -1932,7 +1932,7 @@ function editLegicCash(data) data[8]=string.sub(curr, 1, 2) data[9]=string.sub(curr, 3, 4) end - + -- edit limit if (confirm(accyan.."change Limit?"..acoff)) then limit=string.format("%06x", input(accyan.."enter the Decimal for the new Limit:"..acoff, limit)) @@ -1940,7 +1940,7 @@ function editLegicCash(data) data[11]=string.sub(limit, 3, 4) data[12]=string.sub(limit, 5, 6) end - + -- edit balance if (confirm(accyan.."change Balance?"..acoff)) then balance=string.format("%06x", input(accyan.."enter the Decimal for the new Balance:"..acoff, balance)) @@ -1948,14 +1948,14 @@ function editLegicCash(data) data[15]=string.sub(balance, 1, 2) data[16]=string.sub(balance, 3, 4) data[17]=string.sub(balance, 5, 6) - end - + end + -- edit transaction-counter if (confirm(accyan.."change Transaction-Counter?"..acoff)) then tcv=string.format("%02x", input(accyan.."enter the 4-digit Hex for the new Currency:"..acoff, data[29])) data[29]=tcv end - + -- edit reader.id if (confirm(accyan.."change Last-Reader-ID?"..acoff)) then rid=string.format("%06x", input(accyan.."enter the Decimal for the new Balance:"..acoff, rid)) @@ -1964,7 +1964,7 @@ function editLegicCash(data) data[19]=string.sub(rid, 3, 4) data[20]=string.sub(rid, 5, 6) end - + return fixLegicCash(data) end @@ -2007,7 +2007,7 @@ function check43rdPartyCash1(uid, data) --end --end --end - end + end end return false end @@ -2015,7 +2015,7 @@ end --- CRC related --- --- -- build segmentCrc credentials -function segmentCrcCredentials(tag, segid) +function segmentCrcCredentials(tag, segid) if (istable(tag.SEG[0])) then local cred = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 cred = cred ..tag.SEG[segid].raw[1]..tag.SEG[segid].raw[2]..tag.SEG[segid].raw[3]..tag.SEG[segid].raw[4] @@ -2025,7 +2025,7 @@ end --- -- build kghCrc credentials -function kghCrcCredentials(tag, segid) +function kghCrcCredentials(tag, segid) if (istable(tag) and istable(tag.SEG[0])) then local x='00' if (type(segid)=="string") then segid=tonumber(segid,10) end @@ -2107,7 +2107,7 @@ end --- -- calculate Master-Token crc -function calcMtCrc(bytes) +function calcMtCrc(bytes) --print(#bytes) local cmd=bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[7]..bytes[6]..bytes[8] local len=(tonumber(0xfc ,10)-("%d"):format('0x'..bytes[7])) @@ -2129,7 +2129,7 @@ function calcSegmentCrc(tag, segid) end --- --- calcuate kghCRC for a given segment +-- calcuate kghCRC for a given segment function calcKghCrc(tag, segid) if (istable(tag.SEG[0])) then -- check if a 'Kaber Group Header' exists @@ -2156,7 +2156,7 @@ function checkAllKghCrc(tag) if (istable(tag.SEG[0])) then for i=0, #tag.SEG do crc=calcKghCrc(tag, i) - if (tag.SEG[i].kgh) then + if (tag.SEG[i].kgh) then tag.SEG[i].data[#tag.SEG[i].data-1]=crc end end @@ -2167,7 +2167,7 @@ end -- validate segmentCRC for a given segment function checkSegmentCrc(tag, segid) local data=segmentCrcCredentials(tag, segid) - if (("%02x"):format(utils.Crc8Legic(data))==tag.SEG[segid].crc) then + if (("%02x"):format(utils.Crc8Legic(data))==tag.SEG[segid].crc) then return true end return false @@ -2179,7 +2179,7 @@ function checkKghCrc(tag, segid) if (type(tag.SEG[segid])=='table') then if (tag.data[3]=="11" and tag.raw=="9f" and tag.SSC=="ff") then local data=kghCrcCredentials(tag, segid) - if (("%02x"):format(utils.Crc8Legic(data))==tag.SEG[segid].data[tag.SEG[segid].len-5-1]) then return true; end + if (("%02x"):format(utils.Crc8Legic(data))==tag.SEG[segid].data[tag.SEG[segid].len-5-1]) then return true; end else return false; end else oops(acred.."'Kaba Group header' detected but no Segment-Data found"..ansocolors.reset) end end @@ -2188,70 +2188,70 @@ end -- helptext for modify-mode function modifyHelp() local t=[[ - + Data I/O Segment Manipulation Token-Data ----------------- -------------------- --------------------- rt => read Tag as => add Segment mt => make Token wt => write Tag es => edit Segment Header et => edit Token data ed => edit Segment Data tk => toggle KGH-Flag - File I/O rs => remove Segment - ----------------- cc => check Segment-CRC - lf => load File ck => check KGH - sf => save File ds => dump Segments - xf => xor to File - - - Virtual Tags tagMap (partial) known Segments + File I/O rs => remove Segment + ----------------- cc => check Segment-CRC + lf => load File ck => check KGH + sf => save File ds => dump Segments + xf => xor to File + + + Virtual Tags tagMap (partial) known Segments -------------------------------- --------------------- --------------------------- - ct => copy mainTag to backupTag mm => make (new) Map dlc => dump Legic-Cash - tc => copy backupTag to mainTag em => edit Map submenu elc => edit Legic-Cash + ct => copy mainTag to backupTag mm => make (new) Map dlc => dump Legic-Cash + tc => copy backupTag to mainTag em => edit Map submenu elc => edit Legic-Cash tt => switch mainTag & backupTag lm => load map from file d3p => dump 3rd-Party-Cash di => dump mainTag sm => save map to file e3p => edit 3rd-Party-Cash - do => dump backupTag - + do => dump backupTag + h => this help q => quit - ]] + ]] return t end ---- +--- -- modify Tag (interactive) function modifyMode() local i, backupTAG, outTAG, inTAG, outfile, infile, sel, segment, bytes, outbytes, tagMap - + actions = { --- -- helptext - ["h"] = function(x) - print(" Version: "..version); + ["h"] = function(x) + print(" Version: "..version); print(modifyHelp().."\n".."tags im Memory: "..(istable(inTAG) and ((currentTag=='inTAG') and acgreen.."*mainTAG"..acoff or "mainTAG") or "").." "..(istable(backupTAG) and ((currentTag=='backupTAG') and acgreen.."*backupTAG"..acoff or "backupTAG") or "")) end, --- -- read real Tag with PM3 into virtual 'mainTAG' - ["rt"] = function(x) - inTAG=readFromPM3(); - --actions.di() + ["rt"] = function(x) + inTAG=readFromPM3(); + --actions.di() end, --- -- write content of virtual 'mainTAG' to real Tag with PM3 - ["wt"] = function(x) + ["wt"] = function(x) writeToTag(inTAG) end, --- - -- copy mainTAG to backupTAG - ["ct"] = function(x) - print(accyan.."copy mainTAG to backupTAG"..acoff) + -- copy mainTAG to backupTAG + ["ct"] = function(x) + print(accyan.."copy mainTAG to backupTAG"..acoff) backupTAG=deepCopy(inTAG) end, --- -- copy backupTAG to mainTAG - ["tc"] = function(x) + ["tc"] = function(x) print(accyan.."copy backupTAG to mainTAG"..acoff) inTAG=deepCopy(backupTAG) end, --- -- toggle between mainTAG and backupTAG - ["tt"] = function(x) + ["tt"] = function(x) -- copy main to temp outTAG=deepCopy(inTAG) -- copy backup to main @@ -2264,8 +2264,8 @@ function modifyMode() end, --- -- load file into mainTAG - ["lf"] = function(x) - + ["lf"] = function(x) + if (type(x)=='string' and file_check(x)) then filename=x else filename=input("enter filename: ", "legic.temp") end inTAG=readFile(filename) @@ -2274,130 +2274,130 @@ function modifyMode() if(confirm(accyan.."Mapping-File for "..acoff..filename..accyan.." found - load it also?"..acoff)) then tagMap=loadTagMap(filename..".map") end - end + end end, --- -- save values of mainTAG to a file (xored with MCC of mainTAG) - ["sf"] = function(x) + ["sf"] = function(x) if(istable(inTAG)) then outfile=input("enter filename:", "legic.temp") bytes=tagToBytes(inTAG) --bytes=xorBytes(bytes, inTAG.MCC) - if (bytes) then + if (bytes) then writeFile(bytes, outfile) end end end, --- - -- save values of mainTAG to a file (xored with 'specific' MCC) - ["xf"] = function(x) + -- save values of mainTAG to a file (xored with 'specific' MCC) + ["xf"] = function(x) if(istable(inTAG)) then outfile=input("enter filename:", "legic.temp") crc=input("enter new crc: ('00' for a plain dump)", inTAG.MCC) print("obfuscate witth: "..crc) bytes=tagToBytes(inTAG) bytes[5]=crc - if (bytes) then + if (bytes) then writeFile(bytes, outfile) end end end, --- -- dump mainTAG (and all Segments) - ["di"] = function(x) - if (istable(inTAG)) then + ["di"] = function(x) + if (istable(inTAG)) then local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2 if(istable(inTAG.SEG[0])) then for i=0, #inTAG.SEG do if(check43rdPartyCash1(uid, inTAG.SEG[i].data)) then - io.write(accyan.."in Segment index: "..inTAG.SEG[i].index ..acoff.. "\n") + io.write(accyan.."in Segment index: "..inTAG.SEG[i].index ..acoff.. "\n") elseif(check4LegicCash(inTAG.SEG[i].data)) then io.write(accyan.."in Segment index: "..inTAG.SEG[i].index..acoff.."\n") - lc=true; + lc=true; lci=inTAG.SEG[i].index; end end end - print("\n"..dumpTag(inTAG).."\n") + print("\n"..dumpTag(inTAG).."\n") if (lc) then actions["dlc"](lci) end lc=false - end + end end, --- -- dump backupTAG (and all Segments) ["do"] = function(x) if (istable(backupTAG)) then print("\n"..dumpTag(backupTAG).."\n") end end, --- -- create a empty tagMap - ["mm"] = function(x) + ["mm"] = function(x) -- clear existing tagMap and init - if (istable(inTAG)) then + if (istable(inTAG)) then tagMap=makeTagMap() end end, --- -- edit a tagMap - ["em"] = function(x) - if (istable(inTAG)==false) then - if (confirm("no mainTAG in memory!\nread from PM3?")) then - actions['rt']() - elseif (confirm("load from File?")) then - actions['lf']() + ["em"] = function(x) + if (istable(inTAG)==false) then + if (confirm("no mainTAG in memory!\nread from PM3?")) then + actions['rt']() + elseif (confirm("load from File?")) then + actions['lf']() else return - end + end end - if (istable(tagMap)==false) then actions['mm']() end + if (istable(tagMap)==false) then actions['mm']() end -- edit tagMap=editTagMap(inTAG, tagMap) end, --- -- save a tagMap - ["sm"] = function(x) + ["sm"] = function(x) if (istable(tagMap)) then if (istable(tagMap) and #tagMap.mappings>0) then print(accyan.."Map contains "..acoff..#tagMap..accyan.." mappings"..acoff) saveTagMap(tagMap, input(accyan.."enter filename:"..acoff, "Legic.map")) - else + else print(acyellow.."no mappings in tagMap!"..acoff) end - end + end end, --- -- load a tagMap - ["lm"] = function(x) + ["lm"] = function(x) tagMap=loadTagMap(input(accyan.."enter filename:"..acoff, "Legic.map")) end, --- -- dump single segment - ["ds"] = function(x) + ["ds"] = function(x) if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10) else sel=selectSegment(inTAG) end - if (sel) then print("\n"..(dumpSegment(inTAG, sel) or acred.."no Segments available") ..acoff.."\n") end + if (sel) then print("\n"..(dumpSegment(inTAG, sel) or acred.."no Segments available") ..acoff.."\n") end end, --- -- edit segment header - ["es"] = function(x) + ["es"] = function(x) if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10) else sel=selectSegment(inTAG) end - if (sel) then + if (sel) then if(istable(inTAG.SEG[0])) then inTAG=editSegment(inTAG, sel) inTAG.SEG[sel]=regenSegmentHeader(inTAG.SEG[sel]) - else print(acyellow.."no Segments in Tag"..acoff) end + else print(acyellow.."no Segments in Tag"..acoff) end end end, --- -- add segment - ["as"] = function(x) + ["as"] = function(x) if (istable(inTAG.SEG[0])) then inTAG=addSegment(inTAG) inTAG.SEG[#inTAG.SEG-1]=regenSegmentHeader(inTAG.SEG[#inTAG.SEG-1]) - inTAG.SEG[#inTAG.SEG]=regenSegmentHeader(inTAG.SEG[#inTAG.SEG]) + inTAG.SEG[#inTAG.SEG]=regenSegmentHeader(inTAG.SEG[#inTAG.SEG]) else print(accyan.."Master-Token / unsegmented Tag!"..acoff) end end, --- -- remove segment - ["rs"] = function(x) + ["rs"] = function(x) if (istable(inTAG.SEG[0])) then if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10) else sel=selectSegment(inTAG) end @@ -2409,16 +2409,16 @@ function modifyMode() end, --- -- edit data-portion of single segment - ["ed"] = function(x) + ["ed"] = function(x) if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10) else sel=selectSegment(inTAG) end - if (istable(inTAG.SEG[sel])) then - inTAG.SEG[sel].data=editSegmentData(inTAG.SEG[sel].data) + if (istable(inTAG.SEG[sel])) then + inTAG.SEG[sel].data=editSegmentData(inTAG.SEG[sel].data) end end, --- -- edit Tag (MCD, MSN, MCC etc.) - ["et"] = function(x) + ["et"] = function(x) if (istable(inTAG)) then editTag(inTAG) end @@ -2428,14 +2428,14 @@ function modifyMode() ["mt"] = function(x) inTAG=makeToken(); actions.di() end, --- -- fix segment-crc on single segment - ["ts"] = function(x) + ["ts"] = function(x) if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10) else sel=selectSegment(inTAG) end - regenSegmentHeader(inTAG.SEG[sel]) + regenSegmentHeader(inTAG.SEG[sel]) end, --- - -- toggle kgh-crc-flag on a single segment - ["tk"] = function(x) + -- toggle kgh-crc-flag on a single segment + ["tk"] = function(x) if (istable(inTAG) and istable(inTAG.SEG[0])) then if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10) else sel=selectSegment(inTAG) end @@ -2447,7 +2447,7 @@ function modifyMode() -- calculate LegicCrc8 ["k"] = function(x) if (type(x)=="string" and string.len(x)>0) then - print(("%02x"):format(utils.Crc8Legic(x))) + print(("%02x"):format(utils.Crc8Legic(x))) end end, --- @@ -2455,32 +2455,32 @@ function modifyMode() ["xb"] = function(x) end, --- - -- print string for LegicCrc8-calculation about single segment - ["xc"] = function(x) + -- print string for LegicCrc8-calculation about single segment + ["xc"] = function(x) if (istable(inTAG) and istable(inTAG.SEG[0])) then if (type(x)=="string" and string.len(x)>0) then sel=tonumber(x,10) - else sel=selectSegment(inTAG) end - print("k "..kghCrcCredentials(inTAG, sel)) - end + else sel=selectSegment(inTAG) end + print("k "..kghCrcCredentials(inTAG, sel)) + end end, --- -- fix legic-cash checksums - ["flc"] = function(x) + ["flc"] = function(x) if (type(x)=="string" and string.len(x)>0) then x=tonumber(x,10) - else x=selectSegment(inTAG) end + else x=selectSegment(inTAG) end inTAG.SEG[x].data=fixLegicCash(inTAG.SEG[x].data) end, --- -- edit legic-cash values fixLegicCash(data) - ["elc"] = function(x) + ["elc"] = function(x) x=autoSelectSegment(inTAG, "legiccash") inTAG.SEG[x].data=editLegicCash(inTAG.SEG[x].data) end, --- -- dump legic-cash human-readable - ["dlc"] = function(x) + ["dlc"] = function(x) -- if segment index was user defined - if (type(x)=="string" and string.len(x)>0) then + if (type(x)=="string" and string.len(x)>0) then x=tonumber(x,10) print(string.format("User-Selected Index %02d", x)) -- or try to find match @@ -2493,11 +2493,11 @@ function modifyMode() ["d3p"] = function(x) local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2 -- if segment index was user defined - if (type(x)=="string" and string.len(x)>0) then + if (type(x)=="string" and string.len(x)>0) then x=tonumber(x,10) print(string.format("User-Selected Index %02d", x)) -- or try to find match - else x=autoSelectSegment(inTAG, "3rdparty") end + else x=autoSelectSegment(inTAG, "3rdparty") end if (istable(inTAG) and istable(inTAG.SEG[x]) and inTAG.SEG[x].len == 100) then uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2 if (check43rdPartyCash1(uid, inTAG.SEG[x].data)) then @@ -2510,7 +2510,7 @@ function modifyMode() ["r3p"] = function(x) local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2 -- if segment index was user defined - if (type(x)=="string" and string.len(x)>0) then + if (type(x)=="string" and string.len(x)>0) then x=tonumber(x,10) print(string.format("User-Selected Index %02d", x)) -- or try to find match @@ -2519,14 +2519,14 @@ function modifyMode() end, --- -- edit 3rd-party-cash-segment values (Balance, Mapping-UID, Stamp) - ["e3p"] = function(x) + ["e3p"] = function(x) local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2 -- if segment index was user defined - if (type(x)=="string" and string.len(x)>0) then + if (type(x)=="string" and string.len(x)>0) then x=tonumber(x,10) print(string.format("User-Selected Index %02d", x)) -- or try to find match - else x=autoSelectSegment(inTAG, "3rdparty") end + else x=autoSelectSegment(inTAG, "3rdparty") end if (istable(inTAG) and istable(inTAG.SEG[x]) and inTAG.SEG[x].len == 100) then inTAG=edit3rdPartyCash1(inTAG, x) dump3rdPartyCash1(inTAG, x) @@ -2534,16 +2534,16 @@ function modifyMode() end, --- -- force fixing 3rd-party-checksums - ["f3p"] = function(x) + ["f3p"] = function(x) if(type(x)=="string" and string.len(x)>=2) then x=tonumber(x, 10) else x=selectSegment(inTAG) end - if (istable(inTAG.SEG[x])) then + if (istable(inTAG.SEG[x])) then local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2 inTAG.SEG[x].data=fix3rdPartyCash1(uid, inTAG.SEG[x].data) - end + end end, --- - -- get stamp from single segment + -- get stamp from single segment ["gs"] = function(x) if(type(x)=="string" and string.len(x)>=2) then x=tonumber(x, 10) else x=selectSegment(inTAG) end @@ -2554,7 +2554,7 @@ function modifyMode() end, --- -- calculate crc16 - ["c6"] = function(x) local crc16=string.format("%4.04x", utils.Crc16(x)) + ["c6"] = function(x) local crc16=string.format("%4.04x", utils.Crc16(x)) print(string.sub(crc16, 0,2).." "..string.sub(crc16, 3,4)) end, --- @@ -2562,27 +2562,27 @@ function modifyMode() ["cc"] = function(x) if (istable(inTAG)) then checkAllSegCrc(inTAG) end end, --- -- set backup-area-bytes to '00' - ["cb"] = function(x) + ["cb"] = function(x) if (istable(inTAG)) then print(accyan.."purge BackupArea"..acoff) - inTAG=clearBackupArea(inTAG) - end - end, + inTAG=clearBackupArea(inTAG) + end + end, --- -- check and fix all segments inTAG.SEG[x].kgh toggled 'on' ["ck"] = function(x) if (istable(inTAG)) then checkAllKghCrc(inTAG) end end, --- -- check and fix all segments inTAG.SEG[x].kgh toggled 'on' - ["tac"] = function(x) - if (colored_output) then + ["tac"] = function(x) + if (colored_output) then colored_output=false else colored_output=true - end + end load_colors(colored_output) end, } - repeat + repeat -- defualt message / prompt ic=input("Legic command? ('h' for help - 'q' for quit)", "h") -- command actions decisions (first match, longer commands before shorter) @@ -2607,53 +2607,53 @@ function main(args) -- just a spacer for better readability print() --- parse arguments - for o, a in getopt.getopt(args, 'hrmi:do:c:') do + for o, a in getopt.getopt(args, 'hrmi:do:c:') do -- display help if o == "h" then return help(); end -- read tag from PM3 if o == "r" then inTAG=readFromPM3() end -- input file if o == "i" then inTAG=readFile(a) end - -- dump virtual-Tag + -- dump virtual-Tag if o == "d" then dfs=true end -- interacive modifying if o == "m" then interactive=true; modifyMode() end -- xor (e.g. for clone or plain file) if o == "c" then cfs=true; crc=a end -- output file - if o == "o" then outfile=a; ofs=true end + if o == "o" then outfile=a; ofs=true end end - + -- file conversion (output to file) if (ofs) then -- dump infile / tag-read - if (dfs) then - print("-----------------------------------------") + if (dfs) then + print("-----------------------------------------") print(dumpTag(inTAG)) end bytes=tagToBytes(inTAG) - if (cfs) then + if (cfs) then -- xor willl be done in function writeFile -- with the value of byte[5] - bytes[5]=crc + bytes[5]=crc end -- write to outfile - if (bytes) then + if (bytes) then writeFile(bytes, outfile) - --- read real tag into virtual tag + --- read real tag into virtual tag -- inTAG=readFromPM3() end --- or simply use the bytes that where wriiten inTAG=bytesToTag(bytes, inTAG) -- show new content - if (dfs) then + if (dfs) then print("-----------------------------------------") - print(dumpTag(inTAG)) + print(dumpTag(inTAG)) end end end - + end --- -- script start -main(args) \ No newline at end of file +main(args) diff --git a/client/util.c b/client/util.c index 4adc4e701..5485488c9 100644 --- a/client/util.c +++ b/client/util.c @@ -534,9 +534,11 @@ void xor(unsigned char * dst, unsigned char * src, size_t len) { int32_t le24toh (uint8_t data[3]) { return (data[2] << 16) | (data[1] << 8) | data[0]; } +#ifndef ANDROID uint32_t le32toh (uint8_t *data) { return (uint32_t)( (data[3]<<24) | (data[2]<<16) | (data[1]<<8) | data[0]); } +#endif // Pack a bitarray into a uint32_t. uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bits) { diff --git a/client/util.h b/client/util.h index ede50e8c1..84d1a3163 100644 --- a/client/util.h +++ b/client/util.h @@ -31,6 +31,10 @@ #include #endif +#ifdef ANDROID + #include +#endif + #ifndef BITMASK # define BITMASK(X) (1 << (X)) @@ -146,7 +150,9 @@ extern void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length) extern void xor(unsigned char * dst, unsigned char * src, size_t len); extern int32_t le24toh (uint8_t data[3]); +#ifndef ANDROID extern uint32_t le32toh (uint8_t *data); +#endif extern uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bits); extern void rol(uint8_t *data, const size_t len); extern uint32_t SwapBits(uint32_t value, int nrbits); diff --git a/common/Makefile.common b/common/Makefile.common index aa93433aa..e697ae140 100644 --- a/common/Makefile.common +++ b/common/Makefile.common @@ -65,8 +65,8 @@ endif # uncomment these two; to fix 256 vs 512kb PM3 devices # flashing bootrom -b is needed -APP_CFLAGS += -DHAS_512_FLASH -COMMON_FLAGS += -DHAS_512_FLASH +#APP_CFLAGS += -DHAS_512_FLASH +#COMMON_FLAGS += -DHAS_512_FLASH # Also search prerequisites in the common directory (for usb.c), the fpga directory (for fpga.bit), and the zlib directory VPATH = . ../common ../fpga ../zlib @@ -99,7 +99,7 @@ $(VERSIONOBJ): $(OBJDIR)/%.o: %.c $(INCLUDES) # See ldscript.common. -- Henryk Plötz 2009-08-27 OBJCOPY_TRANSLATIONS = --no-change-warnings \ --change-addresses -0x100000 --change-start 0 \ - --change-section-address .bss+0 --change-section-address .data+0 \ + --change-section-address .bss+0 --change-section-address .data-0x100000 \ --change-section-address .commonarea+0 $(OBJDIR)/%.s19: $(OBJDIR)/%.elf $(OBJCOPY) -Osrec --srec-forceS3 --strip-debug $(OBJCOPY_TRANSLATIONS) $^ $@ diff --git a/liblua/llex.c b/liblua/llex.c index 81b8de9e3..d91f00f7d 100644 --- a/liblua/llex.c +++ b/liblua/llex.c @@ -199,7 +199,7 @@ static void buffreplace (LexState *ls, char from, char to) { #if ANDROID -#define getlocaldecpoint() '.' +#define getlocaledecpoint() '.' #elif !defined(getlocaledecpoint) #define getlocaledecpoint() (localeconv()->decimal_point[0]) #endif