Add support for rrg v4.15864

Add key result as comment in config files
Specify card size in hf mf dump/restore
Use regular expression to detect lf config text
Skip the useless waiting when hf mf nested detects the static nonce then
perform staticnested attack
master
wh201906 2 years ago
parent d8d9178ce8
commit 2b5c94974d
No known key found for this signature in database

@ -1,6 +1,7 @@
<RCC> <RCC>
<qresource prefix="/config"> <qresource prefix="/config">
<file>config_official.json</file> <file>config_official.json</file>
<file>config_rrgv4.13.json</file> <file>config_rrgv4.13441.json</file>
<file>config_rrgv4.15864.json</file>
</qresource> </qresource>
</RCC> </RCC>

@ -10,6 +10,13 @@
"2k": "2", "2k": "2",
"4k": "4" "4k": "4"
}, },
"//": "|---|----------------|---|----------------|---| ",
"//": "|sec|key A |res|key B |res| ",
"//": "|---|----------------|---|----------------|---| ",
"//": "|000| ffffffffffff | 1 | ffffffffffff | 1 | ",
"//": "......",
"//": "|---|----------------|---|----------------|---| ",
"//": "",
"key pattern": "\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|", "key pattern": "\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|",
"key A index": 2, "key A index": 2,
"key B index": 4 "key B index": 4
@ -22,6 +29,15 @@
"2k": "2", "2k": "2",
"4k": "4" "4k": "4"
}, },
"//": "|---|----------------|----------------| ",
"//": "|sec|key A |key B | ",
"//": "|---|----------------|----------------| ",
"//": "|000| ffffffffffff | ffffffffffff | ",
"//": "......",
"//": "|004| ? | ? | ",
"//": "......",
"//": "|---|----------------|----------------| ",
"//": " ",
"key pattern": "\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|", "key pattern": "\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|",
"key A index": 2, "key A index": 2,
"key B index": 3 "key B index": 3
@ -39,10 +55,22 @@
"cmd": "hf list mf" "cmd": "hf list mf"
}, },
"dump": { "dump": {
"cmd": "hf mf dump" "cmd": "hf mf dump <card type>",
"card type": {
"mini": "0",
"1k": "1",
"2k": "2",
"4k": "4"
}
}, },
"restore": { "restore": {
"cmd": "hf mf restore" "cmd": "hf mf restore <card type>",
"card type": {
"mini": "0",
"1k": "1",
"2k": "2",
"4k": "4"
}
}, },
"emulator wipe": { "emulator wipe": {
"cmd": "hf mf eclr" "cmd": "hf mf eclr"

@ -15,6 +15,13 @@
"A": "a", "A": "a",
"B": "b" "B": "b"
}, },
"//": "[+] |-----|----------------|---|----------------|---|",
"//": "[+] | Sec | key A |res| key B |res|",
"//": "[+] |-----|----------------|---|----------------|---|",
"//": "[+] | 000 | ffffffffffff | 1 | ffffffffffff | 1 |",
"//": "......",
"//": "[+] |-----|----------------|---|----------------|---|",
"//": "[+] ( 0:Failed / 1:Success )",
"key pattern": "\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|", "key pattern": "\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|",
"key A index": 2, "key A index": 2,
"key B index": 4 "key B index": 4
@ -27,6 +34,15 @@
"2k": "2k", "2k": "2k",
"4k": "4k" "4k": "4k"
}, },
"//": "[+] |-----|----------------|---|----------------|---|",
"//": "[+] | Sec | key A |res| key B |res|",
"//": "[+] |-----|----------------|---|----------------|---|",
"//": "[+] | 000 | ffffffffffff | 1 | ffffffffffff | 1 |",
"//": "......",
"//": "[+] | 004 | ------------ | 0 | ------------ | 0 |",
"//": "......",
"//": "[+] |-----|----------------|---|----------------|---|",
"//": "[+] ( 0:Failed / 1:Success )",
"key pattern": "\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|", "key pattern": "\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|",
"key A index": 2, "key A index": 2,
"key B index": 4 "key B index": 4
@ -44,10 +60,22 @@
"cmd": "trace list -t mf" "cmd": "trace list -t mf"
}, },
"dump": { "dump": {
"cmd": "hf mf dump" "cmd": "hf mf dump --<card type>",
"card type": {
"mini": "mini",
"1k": "1k",
"2k": "2k",
"4k": "4k"
}
}, },
"restore": { "restore": {
"cmd": "hf mf restore" "cmd": "hf mf restore --<card type>",
"card type": {
"mini": "mini",
"1k": "1k",
"2k": "2k",
"4k": "4k"
}
}, },
"emulator wipe": { "emulator wipe": {
"cmd": "hf mf eclr" "cmd": "hf mf eclr"

@ -0,0 +1,241 @@
{
"//": "Based on Proxmark3 rrg repo v4.15864, commit 1f75adc",
"//": "You can change this file if the command format of client changes",
"mifare classic": {
"nested": {
"cmd": "hf mf nested --<card type> --blk <block> -<key type> -k <key>",
"static cmd": "hf mf staticnested --<card type> --blk <block> -<key type> -k <key>",
"card type": {
"mini": "mini",
"1k": "1k",
"2k": "2k",
"4k": "4k"
},
"key type": {
"A": "a",
"B": "b"
},
"//": "[+] -----+-----+--------------+---+--------------+----",
"//": "[+] Sec | Blk | key A |res| key B |res",
"//": "[+] -----+-----+--------------+---+--------------+----",
"//": "[+] 000 | 003 | FFFFFFFFFFFF | 1 | FFFFFFFFFFFF | 1",
"//": "......",
"//": "[+] -----+-----+--------------+---+--------------+----",
"//": "[+] ( 0:Failed / 1:Success )",
"key pattern": "\\s*\\d{3}\\s*\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*$",
"key A index": 2,
"key B index": 4
},
"check": {
"cmd": "hf mf chk --<card type>",
"card type": {
"mini": "mini",
"1k": "1k",
"2k": "2k",
"4k": "4k"
},
"//": "[+] -----+-----+--------------+---+--------------+----",
"//": "[+] Sec | Blk | key A |res| key B |res",
"//": "[+] -----+-----+--------------+---+--------------+----",
"//": "[+] 000 | 003 | FFFFFFFFFFFF | 1 | FFFFFFFFFFFF | 1",
"//": "......",
"//": "[+] 004 | 019 | ------------ | 0 | ------------ | 0",
"//": "......",
"//": "[+] -----+-----+--------------+---+--------------+----",
"//": "[+] ( 0:Failed / 1:Success )",
"key pattern": "\\s*\\d{3}\\s*\\|\\s*\\d{3}\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*\\|\\s*.+?\\s*$",
"key A index": 2,
"key B index": 4
},
"info": {
"cmd": "hf 14a info"
},
"sniff": {
"cmd": "hf sniff"
},
"sniff 14a": {
"cmd": "hf 14a sniff"
},
"list": {
"cmd": "trace list -t mf"
},
"dump": {
"cmd": "hf mf dump --<card type>",
"card type": {
"mini": "mini",
"1k": "1k",
"2k": "2k",
"4k": "4k"
}
},
"restore": {
"cmd": "hf mf restore --<card type>",
"card type": {
"mini": "mini",
"1k": "1k",
"2k": "2k",
"4k": "4k"
}
},
"emulator wipe": {
"cmd": "hf mf eclr"
},
"Magic Card wipe": {
"cmd": "hf mf cwipe"
},
"emulator read block": {
"cmd": "hf mf egetblk --blk <block>",
"data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}"
},
"Magic Card read block": {
"cmd": "hf mf cgetblk --blk <block>",
"data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}"
},
"normal read block": {
"cmd": "hf mf rdbl --blk <block> -<key type> -k <key>",
"key type": {
"A": "a",
"B": "b"
},
"data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}"
},
"darkside": {
"cmd": "hf mf darkside"
},
"save sniff": {
"cmd": "trace save -f <filename>"
},
"load sniff": {
"cmd": "trace load -f <filename>",
"show cmd": "trace list --buffer -t mf"
},
"hardnested": {
"cmd": "hf mf hardnested --blk <known key block> -<known key type> -k <known key> --tblk <target key block> --t<target key type>",
"known key type": {
"A": "a",
"B": "b"
},
"target key type": {
"A": "a",
"B": "b"
}
},
"normal read sector": {
"cmd": "hf mf rdsc --sec <sector> -<key type> -k <key>",
"key type": {
"A": "a",
"B": "b"
},
"data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}"
},
"Magic Card read sector": {
"cmd": "hf mf cgetsc --sec <sector>",
"data pattern": "([0-9a-fA-F]{2} ){15}[0-9a-fA-F]{2}"
},
"//": "When writing a block, if the result is not empty and doesn't contain the failed flag, the function will return true",
"normal write block": {
"cmd": "hf mf wrbl --blk <block> -<key type> -k <key> -d <data>",
"key type": {
"A": "a",
"B": "b"
},
"failed flag": [
"fail",
"error"
]
},
"Magic Card write block": {
"cmd": "hf mf csetblk --blk <block> -d <data>",
"failed flag": [
"fail",
"error"
]
},
"emulator write block": {
"cmd": "hf mf esetblk --blk <block> -d <data>"
},
"Magic Card lock": {
"cmd": "hf 14a raw ",
"sequence": [
"-ak -b 7 40",
"-ak 43",
"-ak E0 00 39 F7",
"-ak E1 00 E1 EE",
"-ak 85 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 18 47",
"-a 52"
]
},
"Magic Card set parameter": {
"cmd": "hf mf csetuid --uid <uid> --atqa <atqa> --sak <sak>"
}
},
"lf": {
"read": {
"cmd": "lf read -v",
"show cmd": "data plot"
},
"sniff": {
"cmd": "lf sniff -v",
"show cmd": "data plot"
},
"search": {
"cmd": "lf search -u"
},
"tune": {
"cmd": "lf tune --divisor <divisor>"
},
"get config": {
"cmd": "hw status",
"field start": "LF Sampling config",
"field end": "\\[#\\] \\S",
"divisor": {
"flag": "divisor",
"pattern": "\\d+"
},
"bits per sample": {
"flag": "bits per sample",
"pattern": "\\d+"
},
"decimation": {
"flag": "decimation",
"pattern": "\\d+"
},
"averaging": {
"flag": "averaging",
"pattern": "\\d+",
"replace": {
"yes": "1",
"no": "0",
"Yes": "1",
"No": "0"
}
},
"trigger threshold": {
"flag": "trigger threshold",
"pattern": "\\d+"
},
"samples to skip": {
"flag": "samples to skip",
"pattern": "\\d+"
},
"//": "execute 'cmd' then find parameters between 'field stard' and 'field end'",
"//": "for each line, if the line doesn't have any flag, skip",
"//": "otherwise, delete characters before 'flag' and 'flag' itself, then use 'pattern' to get the parameter",
"//": "If 'replace' dict exists, replace all keys with respective values before getting parameters"
},
"set config": {
"cmd": "lf config --divisor <divisor> --bps <bits per sample> --dec <decimation> --avg <averaging> --trig <trigger threshold> --skip <samples to skip>",
"divisor cmd": "hw setlfdivisor -d <divisor>"
}
},
"t55xx": {
"clone em410x": {
"read": "lf em 410x reader",
"successful read flag": "EM 410x ID",
"pattern": "EM 410x ID\\s*\\K[0-9a-fA-F]{10}",
"clone cmd": "lf em 410x clone --id <id> <type>",
"t5555 flag": "--q5",
"t55x7 flag": ""
}
}
}

@ -81,8 +81,10 @@ void LF::getLFConfig()
QVariantMap config = configMap["get config"].toMap(); QVariantMap config = configMap["get config"].toMap();
QString cmd = config["cmd"].toString(); QString cmd = config["cmd"].toString();
result = util->execCMDWithOutput(cmd, 400); result = util->execCMDWithOutput(cmd, 400);
start = result.indexOf(config["field start"].toString()); reMatch = QRegularExpression(config["field start"].toString(), QRegularExpression::MultilineOption).match(result);
end = result.indexOf(config["field end"].toString()); start = reMatch.hasMatch() ? reMatch.capturedEnd() : 0;
reMatch = QRegularExpression(config["field end"].toString(), QRegularExpression::MultilineOption).match(result, start);
end = reMatch.hasMatch() ? reMatch.capturedStart() : result.length();
result = result.mid(start, end - start); result = result.mid(start, end - start);
#if (QT_VERSION <= QT_VERSION_CHECK(5,14,0)) #if (QT_VERSION <= QT_VERSION_CHECK(5,14,0))
resultList = result.split("\n", QString::SkipEmptyParts); resultList = result.split("\n", QString::SkipEmptyParts);

@ -130,7 +130,7 @@ void Mifare::chk()
QString cmd = config["cmd"].toString(); QString cmd = config["cmd"].toString();
int keyAindex = config["key A index"].toInt(); int keyAindex = config["key A index"].toInt();
int keyBindex = config["key B index"].toInt(); int keyBindex = config["key B index"].toInt();
QRegularExpression keyPattern = QRegularExpression(config["key pattern"].toString()); QRegularExpression keyPattern = QRegularExpression(config["key pattern"].toString(), QRegularExpression::MultilineOption);
cmd.replace("<card type>", config["card type"].toMap()[cardType.typeText].toString()); cmd.replace("<card type>", config["card type"].toMap()[cardType.typeText].toString());
result = util->execCMDWithOutput( result = util->execCMDWithOutput(
@ -169,7 +169,7 @@ void Mifare::nested(bool isStaticNested)
cmd = config["cmd"].toString(); cmd = config["cmd"].toString();
int keyAindex = config["key A index"].toInt(); int keyAindex = config["key A index"].toInt();
int keyBindex = config["key B index"].toInt(); int keyBindex = config["key B index"].toInt();
QRegularExpression keyPattern = QRegularExpression(config["key pattern"].toString()); QRegularExpression keyPattern = QRegularExpression(config["key pattern"].toString(), QRegularExpression::MultilineOption);
QRegularExpressionMatch reMatch; QRegularExpressionMatch reMatch;
QString result; QString result;
int offset = 0; int offset = 0;
@ -212,7 +212,7 @@ void Mifare::nested(bool isStaticNested)
} }
result = util->execCMDWithOutput( result = util->execCMDWithOutput(
cmd, cmd,
Util::ReturnTrigger(15000, {"Can't found", "Can't authenticate", keyPattern_res->pattern()}), Util::ReturnTrigger(15000, {"Quit", "Can't found", "Can't authenticate", keyPattern_res->pattern()}),
true); true);
if(result.contains("static") && !isStaticNested) if(result.contains("static") && !isStaticNested)
@ -747,14 +747,20 @@ void Mifare::writeSelected(TargetType targetType)
void Mifare::dump() void Mifare::dump()
{ {
QVariantMap config = configMap["dump"].toMap(); QVariantMap config = configMap["dump"].toMap();
util->execCMD(config["cmd"].toString()); QString cmd = config["cmd"].toString();
if(cmd.contains("<card type>"))
cmd.replace("<card type>", config["card type"].toMap()[cardType.typeText].toString());
util->execCMD(cmd);
Util::gotoRawTab(); Util::gotoRawTab();
} }
void Mifare::restore() void Mifare::restore()
{ {
QVariantMap config = configMap["restore"].toMap(); QVariantMap config = configMap["restore"].toMap();
util->execCMD(config["cmd"].toString()); QString cmd = config["cmd"].toString();
if(cmd.contains("<card type>"))
cmd.replace("<card type>", config["card type"].toMap()[cardType.typeText].toString());
util->execCMD(cmd);
Util::gotoRawTab(); Util::gotoRawTab();
} }

Loading…
Cancel
Save