mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
commit
94882a4cb9
4 changed files with 354 additions and 9 deletions
|
@ -324,7 +324,7 @@ int CmdLFCommandRead(const char *Cmd) {
|
|||
uint32_t samples = 0;
|
||||
uint16_t datalen = 0;
|
||||
|
||||
uint8_t payload_header_size = 12;
|
||||
const uint8_t payload_header_size = 12;
|
||||
struct p {
|
||||
uint32_t delay;
|
||||
uint16_t ones;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "cmdhf14a.h" // for getTagInfo
|
||||
#include "fileutils.h" // loadDictionary
|
||||
#include "util_posix.h"
|
||||
#include "cmdlf.h" // for lf sniff
|
||||
|
||||
// Some defines for readability
|
||||
#define T55XX_DLMODE_FIXED 0 // Default Mode
|
||||
|
@ -399,7 +400,21 @@ static int usage_t55xx_clonehelp(void) {
|
|||
PrintAndLogEx(NORMAL, _GREEN_("lf visa2000 clone"));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_t55xx_sniff(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: lf t55xx sniff [w <width 0> <width 1>] [l <min level>] [b] [h]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " w <0> <1> - Set samples width for 0 and 1 matching (default auto detect)");
|
||||
PrintAndLogEx(NORMAL, " l <level> - Set minimum signal level (default 20)");
|
||||
PrintAndLogEx(NORMAL, " b - Extract from current sample buffer (default will get new samples)");
|
||||
PrintAndLogEx(NORMAL, " h - This help");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx sniff"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx sniff b"));
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" lf t55xx sniff w 7 14 b"));
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static int CmdT55xxCloneHelp(const char *Cmd) {
|
||||
|
@ -3709,6 +3724,301 @@ static int CmdT55xxProtect(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdT55xxSniff(const char *Cmd) {
|
||||
uint8_t cmdp = 0;
|
||||
bool sampleData = true;
|
||||
uint8_t width0 = 0;
|
||||
uint8_t width1 = 0;
|
||||
uint8_t minLevel = 20;
|
||||
int pulseSamples = 0;
|
||||
bool eop;
|
||||
uint8_t page;
|
||||
uint32_t usedPassword;
|
||||
uint32_t blockData;
|
||||
uint8_t blockAddr;
|
||||
char data[100]; // Max should be 80.
|
||||
uint16_t dataLen = 0;
|
||||
size_t idx = 0;
|
||||
size_t start;
|
||||
int minWidth;
|
||||
int maxWidth;
|
||||
char modeText [100];
|
||||
char pwdText [100];
|
||||
bool haveData = false;
|
||||
|
||||
/*
|
||||
Notes:
|
||||
T55xx packet lengths (1 of 4 needs to be checked)
|
||||
-----------------------------------------------
|
||||
| Default | LL 0 | Leading 0 | 1 of 4 |
|
||||
----------------------------------------------------------------|
|
||||
| Standard Write | 38 | 39 | 39 | 40 |
|
||||
| Protect Write | 70 | 71 | 73 | 74 |
|
||||
| AOR | 34 | 35 | 37 | 38 |
|
||||
| Standard Read | 5 | 6 | 7 | 8 |
|
||||
| Protect Read | 38 | 39 | 41 | 42 |
|
||||
| Regular Read | 2 | 3 | 3 | 4 |
|
||||
| Reset | 2 | 3 | 3 | 4 |
|
||||
----------------------------------------------------------------
|
||||
|
||||
T55xx bit widths (decimation 1) - Expected, but may vary a little
|
||||
Reference 0 for LL0 and Leading 0 can be longer
|
||||
-----------------------------------------------
|
||||
| Default | LL 0 | Leading 0 | 1 of 4 |
|
||||
----------------------------------------------------|
|
||||
| 0 | 16 - 32 | 9 - 33 | 5 - 80 | tbc |
|
||||
| 1 | 48 - 64 | 41 - 72 | 21 - 96 | tbc |
|
||||
----------------------------------------------------
|
||||
00 01 10 11
|
||||
|
||||
|
||||
*/
|
||||
while (param_getchar(Cmd, cmdp) != 0x00) {
|
||||
switch (tolower(param_getchar(Cmd, cmdp))) {
|
||||
case 'h':
|
||||
return usage_t55xx_sniff();
|
||||
case 'b':
|
||||
sampleData = false;
|
||||
cmdp ++;
|
||||
break;
|
||||
case 'w':
|
||||
width0 = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
||||
width1 = param_get8ex(Cmd, cmdp + 2, 0, 10);
|
||||
cmdp += 3;
|
||||
|
||||
if (width0 == 0) PrintAndLogEx (ERR,"need both sample widths! "_RED_("Missing sample width for 0"));
|
||||
if (width1 == 0) PrintAndLogEx (ERR,"need both sample widths! "_RED_("Missing sample width for 1"));
|
||||
if ((width0 == 0) || (width1 == 0)) {
|
||||
PrintAndLogEx (NORMAL,"");
|
||||
return usage_t55xx_sniff();
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
minLevel = param_get8ex(Cmd, cmdp + 1, 0, 10);
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
cmdp++;
|
||||
PrintAndLogEx (ERR,"Invalid options supplied!");
|
||||
return usage_t55xx_sniff();
|
||||
}
|
||||
}
|
||||
|
||||
// setup and sample data from Proxmark (if not directed to existing sample/graphbuffer
|
||||
if (sampleData) {
|
||||
// get samples
|
||||
CmdLFSniff ("");
|
||||
}
|
||||
|
||||
idx = 0;
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO,_CYAN_("T55xx write Detection"));
|
||||
PrintAndLogEx(INFO,"Minimum signal level : "_GREEN_("%d"),minLevel);
|
||||
PrintAndLogEx(SUCCESS, "Downlink mode | password | Data | blk | page | 0 | 1 | raw");
|
||||
PrintAndLogEx(SUCCESS, "-----------------+----------+----------+-----+------+-----+-----+-------------------------------------------------------------------------------");
|
||||
|
||||
while (idx < GraphTraceLen)
|
||||
{
|
||||
start = idx;
|
||||
minWidth = 1000;
|
||||
maxWidth = 0;
|
||||
|
||||
// Auto detect bit widths
|
||||
if ((width0 == 0) && (width1 == 0)) {
|
||||
// Skip till we get to a "non modulated section"
|
||||
while ((idx < GraphTraceLen) && ((GraphBuffer[idx] < -5) || (GraphBuffer[idx] > 5)))
|
||||
idx++;
|
||||
|
||||
while ((idx < GraphTraceLen) && ((GraphBuffer[idx] > (-1 * minLevel)) && (GraphBuffer[idx] < minLevel)))
|
||||
idx++;
|
||||
|
||||
eop = false;
|
||||
pulseSamples = 0;
|
||||
|
||||
// Skip until start of next signal - Should be a positive rise above 0
|
||||
while ((idx < GraphTraceLen) && (GraphBuffer[idx] < 10)) idx++;
|
||||
|
||||
while ((idx < GraphTraceLen) && !eop) {
|
||||
|
||||
if ((GraphBuffer[idx-1] <= 0) && (GraphBuffer[idx] > 0))
|
||||
pulseSamples = 0;
|
||||
|
||||
if ((GraphBuffer[idx-1] > 0) && (GraphBuffer[idx] <= 0)) {
|
||||
if (pulseSamples > 0) {
|
||||
|
||||
if (pulseSamples < minWidth)
|
||||
minWidth = pulseSamples;
|
||||
|
||||
if (pulseSamples > maxWidth)
|
||||
maxWidth = pulseSamples;
|
||||
|
||||
pulseSamples = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((GraphBuffer[idx-1] > 0) && (GraphBuffer[idx] <= 0) ) {
|
||||
// End of Packet will have a High to zero drop and stay around 0, so if it drags on or does not keep going down
|
||||
if (((GraphBuffer[idx+5] + 10) > GraphBuffer[idx]) || (pulseSamples > 50)) { // very high chance of being noise
|
||||
eop = true;
|
||||
}
|
||||
} else {
|
||||
pulseSamples++;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
maxWidth = minWidth * 1.75;// + ((25 * MinWidth) / 100);
|
||||
// minWidth = MinWidth;// - ((15 * MinWidth) / 100);
|
||||
} else {
|
||||
maxWidth = width1;
|
||||
minWidth = width0;
|
||||
}
|
||||
|
||||
// =====================================================
|
||||
// go back and find first packet....
|
||||
idx = start;
|
||||
haveData = false;
|
||||
|
||||
// Skip till we get to a "non modulated section" - ie skip if sample is in mid packet
|
||||
while ((idx < GraphTraceLen) && ((GraphBuffer[idx] < -5) || (GraphBuffer[idx] > 5)))
|
||||
idx++;
|
||||
while ((idx < GraphTraceLen) && ((GraphBuffer[idx] > (-1 * minLevel)) && (GraphBuffer[idx] < minLevel)))
|
||||
idx++;
|
||||
|
||||
dataLen = 0;
|
||||
eop = false;
|
||||
pulseSamples = 0;
|
||||
|
||||
// Skip until start of next signal - Should be a positive rise above 0
|
||||
while ((idx < GraphTraceLen) && (GraphBuffer[idx] < 10)) idx++;
|
||||
|
||||
while ((idx < GraphTraceLen) && !eop) {
|
||||
if ((GraphBuffer[idx-1] <= 0) && (GraphBuffer[idx] > 0)) {
|
||||
pulseSamples = 0;
|
||||
}
|
||||
// a return to 0 makes end of needed data. it should cross to negataive before rising to next bit
|
||||
if ((GraphBuffer[idx-1] > 0) && (GraphBuffer[idx] <= 0) ) {
|
||||
// End of Packet will have a High to zero drop and stay around 0, so if it drags on or does not keep going down
|
||||
//
|
||||
if (((GraphBuffer[idx+5] + 10) > GraphBuffer[idx]) || (pulseSamples > 50)) { // very high chance of being noise
|
||||
eop = true;
|
||||
} else { // if we have way too many samples, wont be a valid bit.
|
||||
if (pulseSamples >= maxWidth) //16) // 30 ??
|
||||
data[dataLen++] = '1';
|
||||
else {
|
||||
if (pulseSamples >= minWidth) // Since we found Min Width this should be hit
|
||||
data[dataLen++] = '0';
|
||||
else {
|
||||
eop = true; // Too short, not a bit - Something went wrong, as we found min width
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
pulseSamples++;
|
||||
if (dataLen > 80) // to long for t55xx packets
|
||||
eop = true;
|
||||
idx++;
|
||||
}
|
||||
data[dataLen] = 0x00;
|
||||
|
||||
// printf ("%d : %s\n",dataLen,data);
|
||||
|
||||
sprintf(modeText, "Default");
|
||||
sprintf(pwdText, " ");
|
||||
|
||||
if (dataLen == 73) { // Potential leading 0 password write.
|
||||
if ((memcmp (data, "01100", 5) == 0) || (memcmp (data, "01000", 5) == 0)) { // Still looking good Page 1 or 0
|
||||
|
||||
page = data[2] - '0';
|
||||
usedPassword = 0;
|
||||
for (uint8_t i = 5; i < 32+5; i++) {
|
||||
usedPassword <<= 1;
|
||||
if (data[i] == '1')
|
||||
usedPassword |= 1;
|
||||
}
|
||||
blockData = 0;
|
||||
for (uint8_t i = 38; i < 38+32; i++) {
|
||||
blockData <<= 1;
|
||||
if (data[i] == '1')
|
||||
blockData |= 1;
|
||||
}
|
||||
blockAddr = 0;
|
||||
for (uint8_t i = 70; i < 70+3; i++) {
|
||||
blockAddr <<= 1;
|
||||
if (data[i] == '1')
|
||||
blockAddr |= 1;
|
||||
}
|
||||
haveData = true;
|
||||
sprintf(modeText, "leading 0");
|
||||
sprintf(pwdText,"%08X", usedPassword);
|
||||
}
|
||||
}
|
||||
|
||||
if (dataLen == 70) { // Potential default password write.
|
||||
|
||||
if ((memcmp (data, "10", 2) == 0) || (memcmp (data, "11", 2) == 0)) { // Still looking good Page 1 or 0
|
||||
|
||||
page = data[1] - '0';
|
||||
usedPassword = 0;
|
||||
for (uint8_t i = 2; i < 34; i++) {
|
||||
usedPassword <<= 1;
|
||||
if (data[i] == '1')
|
||||
usedPassword |= 1;
|
||||
}
|
||||
blockData = 0;
|
||||
for (uint8_t i = 35; i < 67; i++) {
|
||||
blockData <<= 1;
|
||||
if (data[i] == '1')
|
||||
blockData |= 1;
|
||||
}
|
||||
blockAddr = 0;
|
||||
for (uint8_t i = 67; i < 70; i++) {
|
||||
blockAddr <<= 1;
|
||||
if (data[i] == '1')
|
||||
blockAddr |= 1;
|
||||
}
|
||||
haveData = true;
|
||||
sprintf(pwdText, "%08X", usedPassword);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (dataLen == 38) { // Potential defaukt write (no password).
|
||||
|
||||
if ((memcmp (data, "10", 2) == 0) || (memcmp (data, "11", 2) == 0)) { // Still looking good Page 1 or 0
|
||||
|
||||
page = data[1] - '0';
|
||||
blockData = 0;
|
||||
for (uint8_t i = 3; i < 35; i++) {
|
||||
blockData <<= 1;
|
||||
if (data[i] == '1')
|
||||
blockData |= 1;
|
||||
}
|
||||
blockAddr = 0;
|
||||
for (uint8_t i = 35; i < 38; i++) {
|
||||
blockAddr <<= 1;
|
||||
if (data[i] == '1')
|
||||
blockAddr |= 1;
|
||||
}
|
||||
haveData = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((haveData) && (minWidth > 1) && (maxWidth > minWidth)){
|
||||
if (blockAddr == 7)
|
||||
PrintAndLogEx (SUCCESS, "%-15s | "_GREEN_("%s")" | "_YELLOW_("%08X")" | "_YELLOW_("%d")" | "_GREEN_("%d")" | %3d | %3d | %s", modeText, pwdText, blockData, blockAddr, page, minWidth, maxWidth, data);
|
||||
else
|
||||
PrintAndLogEx (SUCCESS, "%-15s | "_GREEN_("%s")" | "_GREEN_("%08X")" | "_GREEN_("%d")" | "_GREEN_("%d")" | %3d | %3d | %s", modeText, pwdText, blockData, blockAddr, page, minWidth, maxWidth, data);
|
||||
}
|
||||
}
|
||||
PrintAndLogEx (SUCCESS, "------------------------------------------------------------------------------------------------------------------------------------------------");
|
||||
PrintAndLogEx (NORMAL, "");
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"},
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
|
@ -3732,6 +4042,7 @@ static command_t CommandTable[] = {
|
|||
{"chk", CmdT55xxChkPwds, IfPm3Lf, "Check passwords from dictionary/flash"},
|
||||
{"protect", CmdT55xxProtect, IfPm3Lf, "Password protect tag"},
|
||||
{"recoverpw", CmdT55xxRecoverPW, IfPm3Lf, "[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!"},
|
||||
{"sniff", CmdT55xxSniff, AlwaysAvailable, "Attempt to recover T55xx commands from sample buffer"},
|
||||
{"special", special, IfPm3Lf, "Show block changes with 64 different offsets"},
|
||||
{"wipe", CmdT55xxWipe, IfPm3Lf, "[q] Wipe a T55xx tag and set defaults (will destroy any data on tag)"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
|
|
|
@ -7,6 +7,7 @@ This document is based mostly on information posted on http://www.proxmark.org/f
|
|||
- [White cloner (after 2016)](#white-cloner-after-2016)
|
||||
- [White cloner (after 2016 D Quality)](#white-cloner-after-2016-d-quality)
|
||||
- [restore page1 data](#restore-page1-data)
|
||||
- [Sniffing the comms](#sniffing-the-comms)
|
||||
|
||||
|
||||
# Blue and black cloners
|
||||
|
@ -61,3 +62,19 @@ Standard password is normally (for T55xx): AA55BBBB
|
|||
lf t55xx write b 1 d E0150A48 1
|
||||
If t55xx write b 2 d 2D782308 1
|
||||
```
|
||||
|
||||
# Sniffing the comms
|
||||
The T55x7 protocol uses a pwm based protocol for writing to tags. In order to make decoding easier try the new command as seen below instead. It will try to extract the data written.
|
||||
|
||||
```
|
||||
lf config s <x bytes>
|
||||
lf t55xx sniff
|
||||
|
||||
-- if you have a save trace from before, try
|
||||
data load xxxxxxx.pm3
|
||||
lf t55xx sniff b
|
||||
```
|
||||
|
||||
It uses the existing `lf sniff` command to collect the data, so setting that first as per normal sniffing is recommended. Once you have a sniff, you can "re-sniff" from the stored sniffed data and try different settings, if you think the data is not clean.
|
||||
|
||||
As normal, the cloner may write data past the end of the 40K sample buffer. So using the `lf config s <x bytes>` then re-run the sniff to see if there is more data.
|
|
@ -22,7 +22,17 @@ Step by step guides are online such as [RyscCorps](https://store.ryscc.com/blogs
|
|||
Download the Gator96100 ProxSpace package from https://github.com/Gator96100/ProxSpace/releases
|
||||
|
||||
Extract 'ProxSpace' to a location path without spaces.
|
||||
For example D:\OneDrive\Documents\GitHub is ok whereas C:\My Documents\My Projects\proxspace is not.
|
||||
|
||||
Good example
|
||||
```
|
||||
D:\OneDrive\Documents\GitHub
|
||||
```
|
||||
|
||||
Bad example
|
||||
```
|
||||
C:\My Documents\My Projects\proxspace
|
||||
^
|
||||
```
|
||||
|
||||
If you're running Windows in a Virtualbox guest, make sure not to install ProxSpace on a vbox shared drive. (It's ok later to move the `/pm3` subfolder to a shared drive and edit the `*.bat`)
|
||||
|
||||
|
@ -56,11 +66,13 @@ Now you're ready to follow the [compilation instructions](/doc/md/Use_of_Proxmar
|
|||
|
||||
# Installing on Windows with WSL 1
|
||||
|
||||
WSL 1 requires to run on Windows 10 version 1709 or above. Previous versions didn't have support for COM ports.
|
||||
WSL 1 requires to run on Windows 10 version 1709 or above. Previous windows versions didn't have support for COM ports.
|
||||
|
||||
### stay away from WSL 2
|
||||
*Microsoft introduced WSL 2 starting on Windows 10 version 2004 with Hyper-V powering its virtualization; As of 2020-08-13, WSL 2 does not support USB and Serial.*
|
||||
|
||||
Install WSL 1 with e.g. the standard Ubuntu. You can follow the guide on [Microsoft Docs](https://docs.microsoft.com/en-us/windows/wsl/install-win10) but be careful to follow WSL 1 specific instructions!
|
||||
###
|
||||
Install WSL 1 with e.g. the standard Ubuntu. You can follow the guide on [Microsoft Docs](https://docs.microsoft.com/en-us/windows/wsl/install-win10) but be careful to follow WSL 1 specific instructions! When they recommend you to restart, you must restart.
|
||||
|
||||
For WSL configuration, see [Manage and configure Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/wsl-config).
|
||||
|
||||
|
@ -70,9 +82,14 @@ Make sure your WSL can launch Windows processes to get the `pm3` scripts working
|
|||
|
||||
If you want to run the graphical components of the Proxmark3 client, you need to install a X Server such as [VcXsrv](https://sourceforge.net/projects/vcxsrv/) or [Xming](https://sourceforge.net/projects/xming/) and launch it, e.g. by executing XLaunch.
|
||||
|
||||
## Window terminal Installation
|
||||
Microsoft has recent released a new terminal for their OS. It is much better experience than old `cmd.exe` so we strongly recommend installing it.
|
||||
It is also open sourced, ref [terminal](https://github.com/microsoft/terminal). You can download and install from here: [windows terminal](https://aka.ms/terminal)
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
Enter WSL prompt (`wsl`) and from there, follow the [Linux Installation Instructions](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) for Ubuntu, summarized here below:
|
||||
Enter WSL prompt (`wsl` or `start windows terminal`) and from there, follow the [Linux Installation Instructions](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) for Ubuntu, summarized here below:
|
||||
|
||||
Make sure your WSL guest OS is up-to-date first
|
||||
```sh
|
||||
|
@ -86,7 +103,7 @@ Install dependencies
|
|||
sudo apt-get install --no-install-recommends git ca-certificates build-essential pkg-config \
|
||||
libreadline-dev gcc-arm-none-eabi libnewlib-dev libbz2-dev qtbase5-dev
|
||||
```
|
||||
|
||||
_note_
|
||||
If you don't need the graphical components of the Proxmark3 client, you can skip the installation of `qtbase5-dev`.
|
||||
|
||||
## Clone the RRG/Iceman repository
|
||||
|
@ -97,13 +114,13 @@ git clone https://github.com/RfidResearchGroup/proxmark3.git
|
|||
|
||||
## Compile and use the project
|
||||
|
||||
To use the compiled client, the only difference is that the Proxmark3 port is translated from your `comX` port where "X" is the com port number assigned to proxmark3 under Windows, to a `/dev/ttySX`, so commands become:
|
||||
To use the compiled client, the only difference is that the Proxmark3 port is translated from your `comX` port where **"X"** is the com port number assigned to proxmark3 under Windows, to a `/dev/ttySX`, so commands become:
|
||||
|
||||
```sh
|
||||
proxmark3 /dev/ttyACM0 => proxmark3 /dev/ttySX
|
||||
```
|
||||
|
||||
Depending on the Windows version, you might need to give permission to the current user to access `/dev/ttySX`: (change X to your port number)
|
||||
Depending on the Windows version, you might need to give permission to the current user to access `/dev/ttySX`: (change **X** to your port number)
|
||||
|
||||
```sh
|
||||
ls -al /dev/ttySX
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue