mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-09-11 18:29:22 -07:00
Merge pull request #3473 from YoungJules/feature/add_kgh_tools
Feature/add kgh tools
This commit is contained in:
@@ -56,6 +56,13 @@ if (NOT SKIPPYTHON EQUAL 1)
|
||||
pkg_search_module(PYTHON3EMBED QUIET ${PYTHON3_PKGCONFIG}-embed)
|
||||
endif (NOT SKIPPYTHON EQUAL 1)
|
||||
|
||||
if (MINGW)
|
||||
# Prefer static archives for single-exe deployments.
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
set(ZLIB_USE_STATIC_LIBS ON)
|
||||
set(BZIP2_USE_STATIC_LIBS ON)
|
||||
endif()
|
||||
|
||||
# If cross-compiled, we need to init source and build.
|
||||
if (CMAKE_TOOLCHAIN_FILE)
|
||||
if (ANDROID)
|
||||
@@ -692,7 +699,26 @@ add_library(pm3rrg_rdv4 SHARED
|
||||
${ADDITIONAL_SRC}
|
||||
)
|
||||
|
||||
target_compile_definitions(pm3rrg_rdv4 PRIVATE LIBPM3)
|
||||
add_library(pm3rrg_rdv4_static STATIC
|
||||
${PM3_ROOT}/client/src/proxmark3.c
|
||||
${PM3_ROOT}/client/src/guidummy.cpp
|
||||
${TARGET_SOURCES}
|
||||
${ADDITIONAL_SRC}
|
||||
)
|
||||
|
||||
set(PM3_LIBRARY_TARGETS pm3rrg_rdv4 pm3rrg_rdv4_static)
|
||||
foreach (target IN LISTS PM3_LIBRARY_TARGETS)
|
||||
target_compile_definitions(${target} PRIVATE LIBPM3)
|
||||
target_compile_options(${target} PUBLIC -Wall -Werror -O3)
|
||||
target_include_directories(${target} PRIVATE
|
||||
${PM3_ROOT}/common
|
||||
${PM3_ROOT}/common_fpga
|
||||
${PM3_ROOT}/include
|
||||
${PM3_ROOT}/client/src
|
||||
${PM3_ROOT}/client/include
|
||||
${ADDITIONAL_DIRS}
|
||||
)
|
||||
endforeach()
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
# Fail the build if a client source file is missing from TARGET_SOURCES.
|
||||
@@ -700,17 +726,22 @@ if (UNIX AND NOT APPLE)
|
||||
set_property(TARGET pm3rrg_rdv4 APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--no-undefined")
|
||||
endif()
|
||||
|
||||
target_compile_options(pm3rrg_rdv4 PUBLIC -Wall -Werror -O3)
|
||||
if (EMBED_READLINE)
|
||||
if (NOT SKIPREADLINE EQUAL 1)
|
||||
add_dependencies(pm3rrg_rdv4 ncurses readline)
|
||||
foreach (target IN LISTS PM3_LIBRARY_TARGETS)
|
||||
add_dependencies(${target} ncurses readline)
|
||||
endforeach()
|
||||
endif (NOT SKIPREADLINE EQUAL 1)
|
||||
endif (EMBED_READLINE)
|
||||
if (EMBED_BZIP2)
|
||||
add_dependencies(pm3rrg_rdv4 bzip2)
|
||||
foreach (target IN LISTS PM3_LIBRARY_TARGETS)
|
||||
add_dependencies(${target} bzip2)
|
||||
endforeach()
|
||||
endif (EMBED_BZIP2)
|
||||
if (EMBED_LZ4)
|
||||
add_dependencies(pm3rrg_rdv4 lz4)
|
||||
foreach (target IN LISTS PM3_LIBRARY_TARGETS)
|
||||
add_dependencies(${target} lz4)
|
||||
endforeach()
|
||||
endif (EMBED_LZ4)
|
||||
|
||||
if (MINGW)
|
||||
@@ -718,7 +749,9 @@ if (MINGW)
|
||||
# and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1
|
||||
# FTR __USE_MINGW_ANSI_STDIO seems deprecated in Mingw32
|
||||
# but not Mingw64 https://fr.osdn.net/projects/mingw/lists/archive/users/2019-January/000199.html
|
||||
target_compile_definitions(pm3rrg_rdv4 PRIVATE _ISOC99_SOURCE)
|
||||
foreach (target IN LISTS PM3_LIBRARY_TARGETS)
|
||||
target_compile_definitions(${target} PRIVATE _ISOC99_SOURCE)
|
||||
endforeach()
|
||||
|
||||
set(CMAKE_C_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}")
|
||||
@@ -727,15 +760,6 @@ if (MINGW)
|
||||
set(ADDITIONAL_LNK ws2_32 ${ADDITIONAL_LNK})
|
||||
endif (MINGW)
|
||||
|
||||
target_include_directories(pm3rrg_rdv4 PRIVATE
|
||||
${PM3_ROOT}/common
|
||||
${PM3_ROOT}/common_fpga
|
||||
${PM3_ROOT}/include
|
||||
${PM3_ROOT}/client/src
|
||||
${PM3_ROOT}/client/include
|
||||
${ADDITIONAL_DIRS}
|
||||
)
|
||||
|
||||
if (NOT APPLE)
|
||||
# required for Raspberry Pi, but breaks with clang (OSX). Need to be at the end of the linker line.
|
||||
set(ADDITIONAL_LNK ${ADDITIONAL_LNK} -Wl,--as-needed -latomic -Wl,--no-as-needed)
|
||||
@@ -759,22 +783,26 @@ if (NOT WHEREAMI_FOUND)
|
||||
set(ADDITIONAL_LNK pm3rrg_rdv4_whereami ${ADDITIONAL_LNK})
|
||||
endif (NOT WHEREAMI_FOUND)
|
||||
|
||||
target_link_libraries(pm3rrg_rdv4 PRIVATE
|
||||
m
|
||||
pm3rrg_rdv4_mbedtls
|
||||
pm3rrg_rdv4_cliparser
|
||||
pm3rrg_rdv4_lua
|
||||
pm3rrg_rdv4_tinycbor
|
||||
pm3rrg_rdv4_amiibo
|
||||
pm3rrg_rdv4_reveng
|
||||
pm3rrg_rdv4_hardnested
|
||||
pm3rrg_rdv4_id48
|
||||
pm3rrg_rdv4_mqtt
|
||||
pm3rrg_rdv4_vec
|
||||
${ADDITIONAL_LNK})
|
||||
foreach (target IN LISTS PM3_LIBRARY_TARGETS)
|
||||
target_link_libraries(${target} PRIVATE
|
||||
m
|
||||
pm3rrg_rdv4_mbedtls
|
||||
pm3rrg_rdv4_cliparser
|
||||
pm3rrg_rdv4_lua
|
||||
pm3rrg_rdv4_tinycbor
|
||||
pm3rrg_rdv4_amiibo
|
||||
pm3rrg_rdv4_reveng
|
||||
pm3rrg_rdv4_hardnested
|
||||
pm3rrg_rdv4_id48
|
||||
pm3rrg_rdv4_mqtt
|
||||
pm3rrg_rdv4_vec
|
||||
${ADDITIONAL_LNK})
|
||||
endforeach()
|
||||
|
||||
if (NOT SKIPPTHREAD EQUAL 1)
|
||||
target_link_libraries(pm3rrg_rdv4 PRIVATE pthread)
|
||||
foreach (target IN LISTS PM3_LIBRARY_TARGETS)
|
||||
target_link_libraries(${target} PRIVATE pthread)
|
||||
endforeach()
|
||||
endif (NOT SKIPPTHREAD EQUAL 1)
|
||||
|
||||
if (NOT SKIPPYTHON EQUAL 1)
|
||||
@@ -786,4 +814,6 @@ if (NOT SKIPPYTHON EQUAL 1)
|
||||
endif (PYTHON3EMBED_FOUND OR PYTHON3_FOUND)
|
||||
endif (NOT SKIPPYTHON EQUAL 1)
|
||||
|
||||
target_link_directories(pm3rrg_rdv4 PRIVATE ${ADDITIONAL_LNKDIRS})
|
||||
foreach (target IN LISTS PM3_LIBRARY_TARGETS)
|
||||
target_link_directories(${target} PRIVATE ${ADDITIONAL_LNKDIRS})
|
||||
endforeach()
|
||||
|
||||
+54
-7
@@ -58,13 +58,13 @@ static bool legic_xor(uint8_t *data, uint16_t cardsize) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void legic_xor_with_crc(uint8_t *data, uint16_t cardsize, uint8_t crc) {
|
||||
void legic_xor_with_crc(uint8_t *data, uint16_t cardsize, uint8_t crc) {
|
||||
for (uint16_t i = 22; i < cardsize; i++) {
|
||||
data[i] ^= crc;
|
||||
}
|
||||
}
|
||||
|
||||
static bool legic_clone_update_segment_crcs(uint8_t *data, size_t bytes_read, const uint8_t uid[4]) {
|
||||
bool legic_clone_update_segment_crcs(uint8_t *data, size_t bytes_read, const uint8_t uid[4]) {
|
||||
// Segment headers are parsed from offset 22 everywhere else in LEGIC decoding.
|
||||
size_t start = 22;
|
||||
bool found_segment = false;
|
||||
@@ -96,7 +96,7 @@ static bool legic_clone_update_segment_crcs(uint8_t *data, size_t bytes_read, co
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool legic_clone_update_kgh_crcs(uint8_t *data, size_t bytes_read, const uint8_t uid[4]) {
|
||||
bool legic_clone_update_kgh_crcs(uint8_t *data, size_t bytes_read, const uint8_t uid[4]) {
|
||||
// Decoded segmented payload starts at byte 22.
|
||||
size_t start = 22;
|
||||
bool found_kgh = false;
|
||||
@@ -142,7 +142,7 @@ static bool legic_clone_update_kgh_crcs(uint8_t *data, size_t bytes_read, const
|
||||
return true;
|
||||
}
|
||||
|
||||
static int legic_write_bytes_to_tag(uint16_t offset, uint8_t iv, const uint8_t *data, size_t bytes_read, const char *verb) {
|
||||
int legic_write_bytes_to_tag(uint16_t offset, uint8_t iv, const uint8_t *data, size_t bytes_read, const char *verb) {
|
||||
PrintAndLogEx(SUCCESS, "%s", verb);
|
||||
|
||||
// fast push mode
|
||||
@@ -183,21 +183,68 @@ static int legic_write_bytes_to_tag(uint16_t offset, uint8_t iv, const uint8_t *
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
PrintAndLogEx(WARNING, "Failed writing tag");
|
||||
PrintAndLogEx(WARNING, "Failed writing tag at offset %zu len %zu. Status: %d", i, len, resp.status);
|
||||
g_conn.block_after_ACK = false;
|
||||
return PM3_ERFTRANS;
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "Wrote chunk [offset %zu | len %zu | total %zu", i, len, i + len);
|
||||
PrintAndLogEx(SUCCESS, "Wrote chunk [offset %zu | len %zu | end %zu of %zu]", i, len, i + len, bytes_read);
|
||||
}
|
||||
|
||||
g_conn.block_after_ACK = false;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int legic_write_dump_to_tag(uint8_t *dump, size_t bytes_read) {
|
||||
int legic_write_dump_to_tag(uint8_t *dump, size_t bytes_read) {
|
||||
return legic_write_bytes_to_tag(7, 0x55, dump, bytes_read, "Restoring to card");
|
||||
}
|
||||
|
||||
int legic_migrate_dump(uint8_t *dump, size_t bytes_read, bool rewrite_kgh, const uint8_t dcf[2], bool allow_dcf) {
|
||||
if (dump == NULL || bytes_read <= 22) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (dcf != NULL && !allow_dcf) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
legic_card_select_t card;
|
||||
if (legic_get_type(&card) != PM3_SUCCESS) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
if (card.cardsize < bytes_read) {
|
||||
return PM3_EFILE;
|
||||
}
|
||||
|
||||
uint8_t target_uid[4] = {0};
|
||||
memcpy(target_uid, card.uid, sizeof(target_uid));
|
||||
uint8_t target_mcc = (uint8_t)CRC8Legic(target_uid, sizeof(target_uid));
|
||||
|
||||
if (!legic_clone_update_segment_crcs(dump, bytes_read, target_uid)) {
|
||||
return PM3_EFAILED;
|
||||
}
|
||||
if (rewrite_kgh && !legic_clone_update_kgh_crcs(dump, bytes_read, target_uid)) {
|
||||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
memcpy(dump, target_uid, sizeof(target_uid));
|
||||
dump[4] = target_mcc;
|
||||
legic_xor_with_crc(dump, bytes_read, dump[4]);
|
||||
|
||||
int write_res = legic_write_dump_to_tag(dump, bytes_read);
|
||||
if (write_res != PM3_SUCCESS) {
|
||||
return write_res;
|
||||
}
|
||||
|
||||
if (dcf != NULL) {
|
||||
uint8_t dcf_dump[7] = {0};
|
||||
memcpy(dcf_dump + 5, dcf, 2);
|
||||
return legic_write_bytes_to_tag(5, 0x55, dcf_dump, sizeof(dcf_dump), "Applying explicit DCF update");
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdLegicMigrate(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf legic migrate",
|
||||
|
||||
@@ -31,5 +31,11 @@ int legic_get_type(legic_card_select_t *card);
|
||||
void legic_chk_iv(uint32_t *iv);
|
||||
void legic_seteml(uint8_t *src, uint32_t offset, uint32_t numofbytes);
|
||||
int legic_read_mem(uint32_t offset, uint32_t len, uint32_t iv, uint8_t *out, uint16_t *outlen);
|
||||
int legic_migrate_dump(uint8_t *dump, size_t bytes_read, bool rewrite_kgh, const uint8_t dcf[2], bool allow_dcf);
|
||||
void legic_xor_with_crc(uint8_t *data, uint16_t cardsize, uint8_t crc);
|
||||
bool legic_clone_update_segment_crcs(uint8_t *data, size_t bytes_read, const uint8_t uid[4]);
|
||||
bool legic_clone_update_kgh_crcs(uint8_t *data, size_t bytes_read, const uint8_t uid[4]);
|
||||
int legic_write_bytes_to_tag(uint16_t offset, uint8_t iv, const uint8_t *data, size_t bytes_read, const char *verb);
|
||||
int legic_write_dump_to_tag(uint8_t *dump, size_t bytes_read);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#-----------------------------------------------------------------------------
|
||||
# Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# See LICENSE.txt for the text of the license.
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(legic_kgh_tool)
|
||||
|
||||
set(PM3_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
|
||||
|
||||
add_subdirectory(${PM3_ROOT}/client/experimental_lib ${CMAKE_BINARY_DIR}/experimental_lib)
|
||||
|
||||
add_executable(legic_kgh_tool legic_kgh_tool.c)
|
||||
target_link_libraries(legic_kgh_tool PRIVATE pm3rrg_rdv4_static)
|
||||
target_include_directories(legic_kgh_tool PRIVATE
|
||||
${PM3_ROOT}/common
|
||||
${PM3_ROOT}/client/include
|
||||
${PM3_ROOT}/client/src
|
||||
${PM3_ROOT}/include
|
||||
)
|
||||
|
||||
if (MINGW)
|
||||
target_link_options(legic_kgh_tool PRIVATE -static -static-libgcc)
|
||||
endif()
|
||||
@@ -0,0 +1,71 @@
|
||||
# legic_kgh_tool
|
||||
|
||||
## Running
|
||||
|
||||
`legic_kgh_tool` reads KGH LEGIC card information, badge numbers, and stamps,
|
||||
and writes the supported KGH card layout.
|
||||
|
||||
Examples:
|
||||
|
||||
```bash
|
||||
./legic_kgh_tool COM13 read_badge_number
|
||||
./legic_kgh_tool COM13 read_info
|
||||
./legic_kgh_tool COM13 read_stamp
|
||||
./legic_kgh_tool COM13 read_stamp -o stamp.bin
|
||||
./legic_kgh_tool COM13 write_card 600001 --stamp-file stamp.bin
|
||||
```
|
||||
|
||||
Commands:
|
||||
|
||||
- `read_badge_number` prints the badge number only.
|
||||
- `read_info` prints one-line JSON.
|
||||
- `read_stamp` prints the stamp as 8 hex chars, or writes raw 4 bytes with `-o/--output-file`.
|
||||
- `write_card <badge> (--stamp-file <path> | --stamp-hex <8hex>)` writes the supported KGH layout.
|
||||
|
||||
Notes:
|
||||
|
||||
- Windows ProxSpace examples use `COM13`.
|
||||
- The stamp is 4 bytes and specific to your site.
|
||||
It can be specified as a `.bin` file or as `--stamp-hex` (for example, `003EF417`).
|
||||
- You can retrieve the stamp from a supported KGH card with `read_info` or `read_stamp`.
|
||||
- Linux examples usually use `/dev/ttyACM0` or similar.
|
||||
- `--verbose` can be useful for `read_badge_number` and `write_card`, if they fail for mysterious reasons.
|
||||
|
||||
## Building in ProxSpace (for Windows)
|
||||
|
||||
Do this in ProxSpace:
|
||||
|
||||
```bash
|
||||
cd ~/proxmark3/tools/kgh
|
||||
rm -rf build-lite
|
||||
cmake -G "MSYS Makefiles" -S . -B build-lite \
|
||||
-DSKIPPYTHON=1 \
|
||||
-DSKIPREADLINE=1 \
|
||||
-DSKIPJANSSONSYSTEM=1 \
|
||||
-DSKIPWHEREAMISYSTEM=1 \
|
||||
-DSKIPBT=1
|
||||
cmake --build build-lite --target legic_kgh_tool -j
|
||||
objdump -p build-lite/legic_kgh_tool.exe | grep -i "DLL Name"
|
||||
```
|
||||
|
||||
## Building Linux
|
||||
|
||||
```bash
|
||||
cd tools/kgh
|
||||
rm -rf build-linux
|
||||
cmake -S . -B build-linux \
|
||||
-DSKIPPYTHON=1 \
|
||||
-DSKIPREADLINE=1 \
|
||||
-DSKIPJANSSONSYSTEM=1 \
|
||||
-DSKIPWHEREAMISYSTEM=1 \
|
||||
-DSKIPBT=1
|
||||
cmake --build build-linux --target legic_kgh_tool -j
|
||||
ldd build-linux/legic_kgh_tool
|
||||
```
|
||||
|
||||
## Static Link Notes
|
||||
|
||||
- `legic_kgh_tool` is linked against `pm3rrg_rdv4_static`.
|
||||
- On MinGW, CMake adds `-static -static-libgcc` for the target.
|
||||
- Linux builds are not the same as the ProxSpace single-EXE deployment.
|
||||
- If CMakeCache paths change between ProxSpace and a native shell, delete the build dir and reconfigure.
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user