From eb35636f49b4f4f9d78f57c13bf3b29e0405c3dd Mon Sep 17 00:00:00 2001 From: Lukas Kuzmiak Date: Mon, 8 Jun 2020 17:26:03 -0700 Subject: [PATCH 1/3] remove duplicated key (first occurrence kept) --- client/dictionaries/mfc_default_keys.dic | 4 ---- 1 file changed, 4 deletions(-) diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index 6e2a2f4da..26f1f938e 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -741,7 +741,6 @@ D3A297DC2698 9EA3387A63C1 A3FAA6DAFF67 A7141147D430 -AAFB06045877 ACFFFFFFFFFF AFCEF64C9913 B27ADDFB64B0 @@ -763,7 +762,6 @@ FD8705E721B0 00ada2cd516d # # -D3F7D3F7D3F7 ## 237a4d0d9119 0ed7846c2bc9 @@ -1068,7 +1066,6 @@ a2a3cca2a3cc 385efa542907 3864fcba5937 3f3865fccb69 -5c8ff9990da2 6291b3860fc8 63fca9492f38 863fcb959373 @@ -1114,7 +1111,6 @@ fe04ecfe5577 5a7a52d5e20d # Bosch Solution 6000 # # Found in TagInfo app -8A19D40CF2B5 # Hotel key card key C1E51C63B8F5 # RATB key 1DB710648A65 18F34C92A56E # E-GO card key From a0cbaee1385b127226303159fbae8610ed933591 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Jun 2020 08:51:12 +0200 Subject: [PATCH 2/3] chg: mad makeover --- client/src/cmdhfmf.c | 33 +++++++------- client/src/cmdhfmfp.c | 38 ++++++++-------- client/src/mifare/mad.c | 96 +++++++++++++++++++++++------------------ 3 files changed, 89 insertions(+), 78 deletions(-) diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 983055924..b3ccbbe3b 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -4496,7 +4496,7 @@ static int CmdHF14AMfMAD(const char *Cmd) { void *argtable[] = { arg_param_begin, arg_lit0("vV", "verbose", "show technical data"), - arg_str0("aA", "aid", "print all sectors with aid", NULL), + arg_str0("aA", "aid", "print all sectors with specified aid", NULL), arg_str0("kK", "key", "key for printing sectors", NULL), arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"), arg_param_end @@ -4543,7 +4543,7 @@ static int CmdHF14AMfMAD(const char *Cmd) { if (aidlen == 2) { uint16_t aaid = (aid[0] << 8) + aid[1]; - PrintAndLogEx(NORMAL, "\n-------------- AID 0x%04x ---------------", aaid); + PrintAndLogEx(INFO, "-------------- " _CYAN_("AID 0x%04x") " ---------------", aaid); uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; size_t madlen = 0; @@ -4621,58 +4621,57 @@ static int CmdHFMFNDEF(const char *Cmd) { uint8_t data[4096] = {0}; int datalen = 0; - PrintAndLogEx(NORMAL, ""); - if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) { - PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); + PrintAndLogEx(ERR, "error, read sector 0. card don't have MAD or don't have MAD on default keys"); return PM3_ESOFT; } bool haveMAD2 = false; int res = MADCheck(sector0, NULL, verbose, &haveMAD2); - if (res) { - PrintAndLogEx(ERR, "MAD error %d.", res); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "MAD error %d", res); return res; } if (haveMAD2) { if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) { - PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); + PrintAndLogEx(ERR, "error, read sector 0x10. card don't have MAD or don't have MAD on default keys"); return PM3_ESOFT; } } uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; size_t madlen = 0; - if (MADDecode(sector0, (haveMAD2 ? sector10 : NULL), mad, &madlen)) { - PrintAndLogEx(ERR, "can't decode mad."); - return PM3_ESOFT; + res = MADDecode(sector0, (haveMAD2 ? sector10 : NULL), mad, &madlen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "can't decode MAD"); + return res; } - printf("data reading:"); + PrintAndLogEx(INFO, "data reading:"); for (int i = 0; i < madlen; i++) { if (ndefAID == mad[i]) { uint8_t vsector[16 * 4] = {0}; if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector)) { - PrintAndLogEx(ERR, "read sector %d error.", i + 1); + PrintAndLogEx(ERR, "error, reading sector %d ", i + 1); return PM3_ESOFT; } memcpy(&data[datalen], vsector, 16 * 3); datalen += 16 * 3; - printf("."); + PrintAndLogEx(INPLACE, "."); } } - printf(" OK\n"); + PrintAndLogEx(NORMAL, ""); if (!datalen) { - PrintAndLogEx(ERR, "no NDEF data."); + PrintAndLogEx(WARNING, "no NDEF data"); return PM3_SUCCESS; } if (verbose2) { - PrintAndLogEx(NORMAL, "NDEF data:"); + PrintAndLogEx(SUCCESS, "NDEF data:"); dump_buffer(data, datalen, stdout, 1); } diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index f39ba5c2e..36e847fa1 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -1423,63 +1423,61 @@ static int CmdHFMFPNDEF(const char *Cmd) { uint8_t data[4096] = {0}; int datalen = 0; - PrintAndLogEx(NORMAL, ""); - if (mfpReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector0, verbose)) { - PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); - return 2; + PrintAndLogEx(ERR, "error, read sector 0. card don't have MAD or don't have MAD on default keys"); + return PM3_ESOFT; } bool haveMAD2 = false; int res = MADCheck(sector0, NULL, verbose, &haveMAD2); - if (res) { - PrintAndLogEx(ERR, "MAD error %d.", res); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "MAD error %d", res); return res; } if (haveMAD2) { if (mfpReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector10, verbose)) { - PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); - return 2; + PrintAndLogEx(ERR, "error, read sector 0x10. card don't have MAD or don't have MAD on default keys"); + return PM3_ESOFT; } } uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; size_t madlen = 0; - if (MADDecode(sector0, (haveMAD2 ? sector10 : NULL), mad, &madlen)) { - PrintAndLogEx(ERR, "can't decode mad."); - return 10; + res = MADDecode(sector0, (haveMAD2 ? sector10 : NULL), mad, &madlen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "can't decode MAD"); + return res; } - printf("data reading:"); + PrintAndLogEx(INFO, "data reading:"); for (int i = 0; i < madlen; i++) { if (ndefAID == mad[i]) { uint8_t vsector[16 * 4] = {0}; if (mfpReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector, false)) { - PrintAndLogEx(ERR, "read sector %d error.", i + 1); - return 2; + PrintAndLogEx(ERR, "error, reading sector %d", i + 1); + return PM3_ESOFT; } memcpy(&data[datalen], vsector, 16 * 3); datalen += 16 * 3; - printf("."); + PrintAndLogEx(INPLACE, "."); } } - printf(" OK\n"); + PrintAndLogEx(NORMAL, ""); if (!datalen) { - PrintAndLogEx(ERR, "no NDEF data."); - return 11; + PrintAndLogEx(ERR, "no NDEF data"); + return PM3_SUCCESS; } if (verbose2) { - PrintAndLogEx(NORMAL, "NDEF data:"); + PrintAndLogEx(INFO, "NDEF data:"); dump_buffer(data, datalen, stdout, 1); } NDEFDecodeAndPrint(data, datalen, verbose); - return PM3_SUCCESS; } diff --git a/client/src/mifare/mad.c b/client/src/mifare/mad.c index ffacba3a7..47240b6f2 100644 --- a/client/src/mifare/mad.c +++ b/client/src/mifare/mad.c @@ -11,7 +11,7 @@ #include "mad.h" #include "ui.h" #include "commonutil.h" // ARRAYLEN - +#include "pm3_cmd.h" #include "crc.h" #include "util.h" @@ -110,21 +110,20 @@ static const char *GetAIDDescription(uint16_t AID) { } static int madCRCCheck(uint8_t *sector, bool verbose, int MADver) { - if (MADver == 1) { + if (MADver == 2) { uint8_t crc = CRC8Mad(§or[16 + 1], 15 + 16); if (crc != sector[16]) { - PrintAndLogEx(WARNING, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]); - return 3; + PrintAndLogEx(WARNING, _RED_("Wrong MAD %d CRC") " calculated: 0x%02x != 0x%02x", MADver, crc, sector[16]); + return PM3_ESOFT; }; } else { uint8_t crc = CRC8Mad(§or[1], 15 + 16 + 16); if (crc != sector[0]) { - PrintAndLogEx(WARNING, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]); - return 3; + PrintAndLogEx(WARNING, _RED_("Wrong MAD %d CRC") " calculated: 0x%02x != 0x%02x", MADver, crc, sector[16]); + return PM3_ESOFT; }; } - - return 0; + return PM3_SUCCESS; } static uint16_t madGetAID(uint8_t *sector, int MADver, int sectorNo) { @@ -135,54 +134,53 @@ static uint16_t madGetAID(uint8_t *sector, int MADver, int sectorNo) { } int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2) { - int res = 0; - if (!sector0) - return 1; + if (sector0 == NULL) + return PM3_EINVARG; uint8_t GPB = sector0[3 * 16 + 9]; if (verbose) - PrintAndLogEx(NORMAL, "GPB: 0x%02x", GPB); + PrintAndLogEx(INFO, "GPB: 0x%02x", GPB); // DA (MAD available) if (!(GPB & 0x80)) { PrintAndLogEx(ERR, "DA=0! MAD not available."); - return 1; + return PM3_ESOFT; } // MA (multi-application card) if (verbose) { if (GPB & 0x40) - PrintAndLogEx(NORMAL, "Multi application card."); + PrintAndLogEx(INFO, "Multi application card."); else - PrintAndLogEx(NORMAL, "Single application card."); + PrintAndLogEx(INFO, "Single application card."); } uint8_t MADVer = GPB & 0x03; if (verbose) - PrintAndLogEx(NORMAL, "MAD version: %d", MADVer); + PrintAndLogEx(INFO, "MAD version: %d", MADVer); // MAD version if ((MADVer != 0x01) && (MADVer != 0x02)) { PrintAndLogEx(ERR, "Wrong MAD version: 0x%02x", MADVer); - return 2; + return PM3_ESOFT; }; if (haveMAD2) *haveMAD2 = (MADVer == 2); - res = madCRCCheck(sector0, true, 1); + int res = madCRCCheck(sector0, true, 1); - if (verbose && !res) - PrintAndLogEx(NORMAL, "CRC8-MAD1 OK."); + if (verbose && res == PM3_SUCCESS) + PrintAndLogEx(INFO, "CRC8-MAD1 (%s)", _GREEN_("ok")); if (MADVer == 2 && sector10) { int res2 = madCRCCheck(sector10, true, 2); - if (!res) + if (res == PM3_SUCCESS) res = res2; if (verbose && !res2) - PrintAndLogEx(NORMAL, "CRC8-MAD2 OK."); + PrintAndLogEx(INFO, "CRC8-MAD2 (%)", _GREEN_("ok")); } return res; @@ -191,7 +189,11 @@ int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2) int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen) { *madlen = 0; bool haveMAD2 = false; - MADCheck(sector0, sector10, false, &haveMAD2); + int res = MADCheck(sector0, sector10, false, &haveMAD2); + if (res != PM3_SUCCESS) { + PrintAndLogEx(INFO, "Not a valid MAD"); + return res; + } for (int i = 1; i < 16; i++) { mad[*madlen] = madGetAID(sector0, 1, i); @@ -208,51 +210,63 @@ int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen (*madlen)++; } } - - return 0; + return PM3_SUCCESS; } - int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { // check MAD1 only - MADCheck(sector, NULL, verbose, haveMAD2); + int res = MADCheck(sector, NULL, verbose, haveMAD2); + if (verbose) { + if (res == PM3_SUCCESS) + PrintAndLogEx(INFO, "CRC8-MAD1 (%s)", _GREEN_("ok")); + else + PrintAndLogEx(INFO, "CRC8-MAD1 (%s)", _RED_("fail")); + } // info byte uint8_t InfoByte = sector[16 + 1] & 0x3f; if (InfoByte) { - PrintAndLogEx(NORMAL, "Card publisher sector: 0x%02x", InfoByte); + PrintAndLogEx(INFO, "Card publisher sector: " _GREEN_("0x%02x"), InfoByte); } else { if (verbose) - PrintAndLogEx(NORMAL, "Card publisher sector not present."); + PrintAndLogEx(WARNING, "Card publisher sector not present"); } if (InfoByte == 0x10 || InfoByte >= 0x28) PrintAndLogEx(WARNING, "Info byte error"); - PrintAndLogEx(NORMAL, "00 MAD1"); + PrintAndLogEx(INFO, " 00 MAD 1"); for (int i = 1; i < 16; i++) { uint16_t AID = madGetAID(sector, 1, i); - PrintAndLogEx(NORMAL, "%02d [%04X] %s", i, AID, GetAIDDescription(AID)); - }; + PrintAndLogEx(INFO, " %02d [%04X] %s", i, AID, GetAIDDescription(AID)); + } - return 0; + return PM3_SUCCESS; } int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) { - PrintAndLogEx(NORMAL, "16 MAD2"); + PrintAndLogEx(INFO, " 16 MAD 2"); int res = madCRCCheck(sector, true, 2); - - if (verbose && !res) - PrintAndLogEx(NORMAL, "CRC8-MAD2 OK."); + if (verbose) { + if (res == PM3_SUCCESS) + PrintAndLogEx(INFO, "CRC8-MAD2 (%s)", _GREEN_("ok")); + else + PrintAndLogEx(INFO, "CRC8-MAD2 (%s)", _RED_("fail")); + } uint8_t InfoByte = sector[1] & 0x3f; - PrintAndLogEx(NORMAL, "MAD2 Card publisher sector: 0x%02x", InfoByte); + if (InfoByte) { + PrintAndLogEx(INFO, "MAD2 Card publisher sector: " _GREEN_("0x%02x"), InfoByte); + } else { + if (verbose) + PrintAndLogEx(WARNING, "Card publisher sector not present"); + } for (int i = 1; i < 8 + 8 + 7 + 1; i++) { uint16_t AID = madGetAID(sector, 2, i); - PrintAndLogEx(NORMAL, "%02d [%04X] %s", i + 16, AID, GetAIDDescription(AID)); - }; + PrintAndLogEx(INFO, "%02d [%04X] %s", i + 16, AID, GetAIDDescription(AID)); + } - return 0; + return PM3_SUCCESS; } From 849be2376ca81f3a4139316c1aa23a2238aea808 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 9 Jun 2020 09:19:25 +0200 Subject: [PATCH 3/3] textual --- client/src/cmdhf14a.c | 60 +++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index baa2c66cf..7703fe849 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -1256,7 +1256,7 @@ int CmdHF14A(const char *Cmd) { } static void printTag(const char *tag) { - PrintAndLogEx(SUCCESS, "POSSIBLE TYPE:" _YELLOW_(" %s"), tag); + PrintAndLogEx(SUCCESS, " " _YELLOW_("%s"), tag); } @@ -1274,6 +1274,8 @@ typedef enum { static int detect_nxp_card(uint8_t sak, uint16_t atqa) { int type = MTNONE; + PrintAndLogEx(SUCCESS, "Possible types:"); + if (sak == 0x00) { printTag("NTAG 20x / 21x / 21x TT / I2C plus"); printTag("MIFARE Ultralight / C / EV1 / Nano"); @@ -1284,10 +1286,12 @@ static int detect_nxp_card(uint8_t sak, uint16_t atqa) { printTag("TNP3xxx (Activision Game Appliance)"); type = MTCLASSIC; } + if ((sak & 0x04) == 0x04) { printTag("Any MIFARE CL1 / NTAG424DNA"); type |= MTDESFIRE; } + if ((sak & 0x08) == 0x08) { printTag("MIFARE Classic 1K / Classic 1K CL2"); printTag("MIFARE Plus 2K / Plus EV1 2K"); @@ -1295,18 +1299,22 @@ static int detect_nxp_card(uint8_t sak, uint16_t atqa) { type |= MTCLASSIC; type |= MTPLUS; } + if ((sak & 0x09) == 0x09) { printTag("MIFARE Mini 0.3K / Mini CL2 0.3K"); type |= MTMINI; } + if ((sak & 0x10) == 0x10) { printTag("MIFARE Plus 2K / Plus CL2 2K"); type |= MTPLUS; } + if ((sak & 0x11) == 0x11) { printTag("MIFARE Plus 4K / Plus CL2 4K"); type |= MTPLUS; } + if ((sak & 0x18) == 0x18) { if (atqa == 0x0042) { printTag("MIFARE Plus 4K / Plus EV1 4K"); @@ -1316,8 +1324,8 @@ static int detect_nxp_card(uint8_t sak, uint16_t atqa) { printTag("MIFARE Classic 4K / Classic 4K CL2"); type |= MTCLASSIC; } - } + if ((sak & 0x20) == 0x20) { if (atqa == 0x0344) { printTag("MIFARE DESFire EV1 2K/4K/8K / DESFire EV1 CL2 2K/4K/8K"); @@ -1332,18 +1340,25 @@ static int detect_nxp_card(uint8_t sak, uint16_t atqa) { type |= MTPLUS; } } + if ((sak & 0x24) == 0x24) { if (atqa == 0x0344) { printTag("MIFARE DESFire CL1 / DESFire EV1 CL1"); type |= MTDESFIRE; } } + if ((sak & 0x28) == 0x28) { if (atqa == 0x0344) { printTag("MIFARE DESFire CL1 / DESFire EV1 CL1"); type |= MTDESFIRE; } } + + if (type == MTNONE) { + PrintAndLogEx(WARNING, " failed to fingerprint"); + } + return type; } @@ -1351,9 +1366,9 @@ typedef struct { uint8_t uid0; uint8_t uid1; const char *desc; -} uidname; +} uid_label_name; -const uidname uidmap[] = { +const uid_label_name uid_label_map[] = { // UID0, UID1, TEXT {0x02, 0x84, "M24SR64-Y"}, {0x02, 0xA3, "25TA02KB-P"}, @@ -1367,14 +1382,13 @@ const uidname uidmap[] = { static void getTagLabel(uint8_t uid0, uint8_t uid1) { int i = 0; - while (uidmap[i].uid0 != 0x00) { - if ((uidmap[i].uid0 == uid0) && (uidmap[i].uid1 == uid1)) { - PrintAndLogEx(SUCCESS, _YELLOW_(" %s"), uidmap[i].desc); + while (uid_label_map[i].uid0 != 0x00) { + if ((uid_label_map[i].uid0 == uid0) && (uid_label_map[i].uid1 == uid1)) { + PrintAndLogEx(SUCCESS, _YELLOW_(" %s"), uid_label_map[i].desc); return; } i += 1; } - return; } int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { @@ -1414,7 +1428,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { } if (verbose) { - PrintAndLogEx(SUCCESS, "-- ISO14443-a Information -----------------------------------"); + PrintAndLogEx(SUCCESS, "------ " _CYAN_("ISO14443-a Information") "------------------"); PrintAndLogEx(SUCCESS, "-------------------------------------------------------------"); } PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); @@ -1426,7 +1440,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { bool isMifarePlus = false; bool isMifareUltralight = false; int nxptype = MTNONE; - // Double & triple sized UID, can be mapped to a manufacturer. + if (card.uidlen <= 4) { nxptype = detect_nxp_card(card.sak, ((card.atqa[1] << 8) + card.atqa[0])); @@ -1437,9 +1451,12 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if ((nxptype & MTOTHER) == MTOTHER) isMifareClassic = true; - } - if (card.uidlen > 4) { + + } else { + + // Double & triple sized UID, can be mapped to a manufacturer. PrintAndLogEx(SUCCESS, "MANUFACTURER: " _YELLOW_("%s"), getTagInfo(card.uid[0])); + switch (card.uid[0]) { case 0x04: // NXP nxptype = detect_nxp_card(card.sak, ((card.atqa[1] << 8) + card.atqa[0])); @@ -1756,16 +1773,6 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported"); } - if (isMifareUltralight) { - PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu info`")); - } - if (isMifarePlus) { - PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfp info`")); - } - if (isMifareDESFire) { - PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfdes info`")); - } - if (isMifareClassic || isMifareUltralight) { detect_classic_magic(); @@ -1790,6 +1797,15 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { } } + if (isMifareUltralight) + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfu info`")); + + if (isMifarePlus) + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfp info`")); + + if (isMifareDESFire) + PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf mfdes info`")); + DropField(); return select_status; }