@@ -3849,45 +3849,74 @@ void picopass_elite_nextKey(uint8_t *key) {
3849
3849
memcpy (key , key_state , 8 );
3850
3850
}
3851
3851
3852
- static int CmdHFiClassRecover (uint8_t key [8 ]) {
3853
-
3854
- uint32_t payload_size = sizeof (iclass_recover_req_t );
3855
- uint8_t aa2_standard_key [PICOPASS_BLOCK_SIZE ] = {0 };
3856
- memcpy (aa2_standard_key , iClass_Key_Table [1 ], PICOPASS_BLOCK_SIZE );
3857
- iclass_recover_req_t * payload = calloc (1 , payload_size );
3858
- payload -> req .use_raw = true;
3859
- payload -> req .use_elite = false;
3860
- payload -> req .use_credit_key = false;
3861
- payload -> req .use_replay = true;
3862
- payload -> req .send_reply = true;
3863
- payload -> req .do_auth = true;
3864
- payload -> req .shallow_mod = false;
3865
- payload -> req2 .use_raw = false;
3866
- payload -> req2 .use_elite = false;
3867
- payload -> req2 .use_credit_key = true;
3868
- payload -> req2 .use_replay = false;
3869
- payload -> req2 .send_reply = true;
3870
- payload -> req2 .do_auth = true;
3871
- payload -> req2 .shallow_mod = false;
3872
- memcpy (payload -> req .key , key , 8 );
3873
- memcpy (payload -> req2 .key , aa2_standard_key , 8 );
3852
+ static int iclass_recover (uint8_t key [8 ], uint32_t index_start , uint32_t loop , uint8_t no_first_auth [8 ], bool debug , bool test , bool allnight ) {
3853
+
3854
+ int runs = 1 ;
3855
+ int cycle = 1 ;
3856
+ bool repeat = true;
3857
+ if (allnight ){
3858
+ runs = 10 ;
3859
+ }
3860
+
3861
+ while (repeat == true){
3862
+ uint32_t payload_size = sizeof (iclass_recover_req_t );
3863
+ uint8_t aa2_standard_key [PICOPASS_BLOCK_SIZE ] = {0 };
3864
+ memcpy (aa2_standard_key , iClass_Key_Table [1 ], PICOPASS_BLOCK_SIZE );
3865
+ iclass_recover_req_t * payload = calloc (1 , payload_size );
3866
+ payload -> req .use_raw = true;
3867
+ payload -> req .use_elite = false;
3868
+ payload -> req .use_credit_key = false;
3869
+ payload -> req .use_replay = true;
3870
+ payload -> req .send_reply = true;
3871
+ payload -> req .do_auth = true;
3872
+ payload -> req .shallow_mod = false;
3873
+ payload -> req2 .use_raw = false;
3874
+ payload -> req2 .use_elite = false;
3875
+ payload -> req2 .use_credit_key = true;
3876
+ payload -> req2 .use_replay = false;
3877
+ payload -> req2 .send_reply = true;
3878
+ payload -> req2 .do_auth = true;
3879
+ payload -> req2 .shallow_mod = false;
3880
+ payload -> index = index_start ;
3881
+ payload -> loop = loop ;
3882
+ payload -> debug = debug ;
3883
+ payload -> test = test ;
3884
+ memcpy (payload -> nfa , no_first_auth , PICOPASS_BLOCK_SIZE );
3885
+ memcpy (payload -> req .key , key , PICOPASS_BLOCK_SIZE );
3886
+ memcpy (payload -> req2 .key , aa2_standard_key , PICOPASS_BLOCK_SIZE );
3887
+
3888
+ PrintAndLogEx (INFO , "Recover started..." );
3874
3889
3875
- PrintAndLogEx (INFO , "Recover started..." );
3876
-
3877
- PacketResponseNG resp ;
3878
- clearCommandBuffer ();
3879
- SendCommandNG (CMD_HF_ICLASS_RECOVER , (uint8_t * )payload , payload_size );
3890
+ PacketResponseNG resp ;
3891
+ clearCommandBuffer ();
3892
+ SendCommandNG (CMD_HF_ICLASS_RECOVER , (uint8_t * )payload , payload_size );
3880
3893
3881
- WaitForResponse (CMD_HF_ICLASS_RECOVER , & resp );
3894
+ WaitForResponse (CMD_HF_ICLASS_RECOVER , & resp );
3882
3895
3883
- if (resp .status == PM3_SUCCESS ) {
3884
- PrintAndLogEx (SUCCESS , "iCLASS Key Bits Recovery " _GREEN_ ("successful" ));
3885
- } else {
3886
- PrintAndLogEx (WARNING , "iCLASS Key Bits Recovery " _RED_ ("failed" ));
3896
+ if (resp .status == PM3_SUCCESS ) {
3897
+ PrintAndLogEx (SUCCESS , "iCLASS Key Bits Recovery: " _GREEN_ ("completed!" ));
3898
+ repeat = false;
3899
+ } else if (resp .status == PM3_ESOFT ){
3900
+ PrintAndLogEx (WARNING , "iCLASS Key Bits Recovery: " _RED_ ("failed/errors" ));
3901
+ repeat = false;
3902
+ } else if (resp .status == PM3_EINVARG ){
3903
+ if (allnight ){
3904
+ if (runs <= cycle ){
3905
+ repeat = false;
3906
+ }else {
3907
+ index_start = index_start + loop ;
3908
+ cycle ++ ;
3909
+ }
3910
+ }else {
3911
+ repeat = false;
3912
+ }
3913
+ }
3914
+ free (payload );
3915
+ if (!repeat ){
3916
+ return resp .status ;
3917
+ }
3887
3918
}
3888
-
3889
- free (payload );
3890
- return resp .status ;
3919
+ return PM3_SUCCESS ;
3891
3920
}
3892
3921
3893
3922
void generate_key_block_inverted (const uint8_t * startingKey , uint64_t index , uint8_t * keyBlock ) {
@@ -3912,84 +3941,60 @@ static int CmdHFiClassLegRecLookUp(const char *Cmd) {
3912
3941
CLIParserContext * ctx ;
3913
3942
CLIParserInit (& ctx , "hf iclass legbrute" ,
3914
3943
"This command take sniffed trace data and partial raw key and bruteforces the remaining 40 bits of the raw key." ,
3915
- "hf iclass legbrute --csn 8D7BD711FEFF12E0 -- epurse feffffffffffffff --macs1 1306cad9b6c24466 --macs2 f0bf905e35f97923 --pk B4F12AADC5301225"
3944
+ "hf iclass legbrute --epurse feffffffffffffff --macs1 1306cad9b6c24466 --macs2 f0bf905e35f97923 --pk B4F12AADC5301225"
3916
3945
);
3917
3946
3918
3947
void * argtable [] = {
3919
3948
arg_param_begin ,
3920
- arg_str1 (NULL , "csn" , "<hex>" , "Specify CSN as 8 hex bytes" ),
3921
3949
arg_str1 (NULL , "epurse" , "<hex>" , "Specify ePurse as 8 hex bytes" ),
3922
3950
arg_str1 (NULL , "macs1" , "<hex>" , "MACs captured from the reader" ),
3923
3951
arg_str1 (NULL , "macs2" , "<hex>" , "MACs captured from the reader, different than the first set (with the same csn and epurse value)" ),
3924
3952
arg_str1 (NULL , "pk" , "<hex>" , "Partial Key from legrec or starting key of keyblock from legbrute" ),
3925
- arg_int0 (NULL , "index" , "<dec>" , "Where to start from to retrieve the key, default 0" ),
3953
+ arg_int0 (NULL , "index" , "<dec>" , "Where to start from to retrieve the key, default 0 - value in millions e.g. 1 is 1 million " ),
3926
3954
arg_param_end
3927
3955
};
3928
3956
CLIExecWithReturn (ctx , Cmd , argtable , false);
3929
3957
3930
- int csn_len = 0 ;
3931
- uint8_t csn [8 ] = {0 };
3932
- CLIGetHexWithReturn (ctx , 1 , csn , & csn_len );
3933
-
3934
- if (csn_len > 0 ) {
3935
- if (csn_len != 8 ) {
3936
- PrintAndLogEx (ERR , "CSN is incorrect length" );
3937
- CLIParserFree (ctx );
3938
- return PM3_EINVARG ;
3939
- }
3940
- }
3941
-
3942
3958
int epurse_len = 0 ;
3943
- uint8_t epurse [8 ] = {0 };
3944
- CLIGetHexWithReturn (ctx , 2 , epurse , & epurse_len );
3945
-
3946
- if (epurse_len > 0 ) {
3947
- if (epurse_len != 8 ) {
3948
- PrintAndLogEx (ERR , "ePurse is incorrect length" );
3949
- CLIParserFree (ctx );
3950
- return PM3_EINVARG ;
3951
- }
3952
- }
3959
+ uint8_t epurse [PICOPASS_BLOCK_SIZE ] = {0 };
3960
+ CLIGetHexWithReturn (ctx , 1 , epurse , & epurse_len );
3953
3961
3954
3962
int macs_len = 0 ;
3955
- uint8_t macs [8 ] = {0 };
3956
- CLIGetHexWithReturn (ctx , 3 , macs , & macs_len );
3957
-
3958
- if (macs_len > 0 ) {
3959
- if (macs_len != 8 ) {
3960
- PrintAndLogEx (ERR , "MAC1 is incorrect length" );
3961
- CLIParserFree (ctx );
3962
- return PM3_EINVARG ;
3963
- }
3964
- }
3963
+ uint8_t macs [PICOPASS_BLOCK_SIZE ] = {0 };
3964
+ CLIGetHexWithReturn (ctx , 2 , macs , & macs_len );
3965
3965
3966
3966
int macs2_len = 0 ;
3967
- uint8_t macs2 [8 ] = {0 };
3968
- CLIGetHexWithReturn (ctx , 4 , macs2 , & macs2_len );
3969
-
3970
- if (macs2_len > 0 ) {
3971
- if (macs2_len != 8 ) {
3972
- PrintAndLogEx (ERR , "MAC2 is incorrect length" );
3973
- CLIParserFree (ctx );
3974
- return PM3_EINVARG ;
3975
- }
3976
- }
3967
+ uint8_t macs2 [PICOPASS_BLOCK_SIZE ] = {0 };
3968
+ CLIGetHexWithReturn (ctx , 3 , macs2 , & macs2_len );
3977
3969
3978
3970
int startingkey_len = 0 ;
3979
- uint8_t startingKey [8 ] = {0 };
3980
- CLIGetHexWithReturn (ctx , 5 , startingKey , & startingkey_len );
3981
-
3982
- if (startingkey_len > 0 ) {
3983
- if (startingkey_len != 8 ) {
3984
- PrintAndLogEx (ERR , "Partial Key is incorrect length" );
3985
- CLIParserFree (ctx );
3986
- return PM3_EINVARG ;
3987
- }
3988
- }
3971
+ uint8_t startingKey [PICOPASS_BLOCK_SIZE ] = {0 };
3972
+ CLIGetHexWithReturn (ctx , 4 , startingKey , & startingkey_len );
3989
3973
3990
3974
uint64_t index = arg_get_int_def (ctx , 6 , 0 ); //has to be 64 as we're bruteforcing 40 bits
3975
+ index = index * 1000000 ;
3991
3976
3992
3977
CLIParserFree (ctx );
3978
+
3979
+ if (epurse_len && epurse_len != PICOPASS_BLOCK_SIZE ) {
3980
+ PrintAndLogEx (ERR , "ePurse is incorrect length" );
3981
+ return PM3_EINVARG ;
3982
+ }
3983
+
3984
+ if (macs_len && macs_len != PICOPASS_BLOCK_SIZE ) {
3985
+ PrintAndLogEx (ERR , "MAC1 is incorrect length" );
3986
+ return PM3_EINVARG ;
3987
+ }
3988
+
3989
+ if (macs2_len && macs2_len != PICOPASS_BLOCK_SIZE ) {
3990
+ PrintAndLogEx (ERR , "MAC2 is incorrect length" );
3991
+ return PM3_EINVARG ;
3992
+ }
3993
+
3994
+ if (startingkey_len && startingkey_len != PICOPASS_BLOCK_SIZE ) {
3995
+ PrintAndLogEx (ERR , "Partial Key is incorrect length" );
3996
+ return PM3_EINVARG ;
3997
+ }
3993
3998
//Standalone Command End
3994
3999
3995
4000
uint8_t CCNR [12 ];
@@ -4005,7 +4010,6 @@ static int CmdHFiClassLegRecLookUp(const char *Cmd) {
4005
4010
memcpy (MAC_TAG , macs + 4 , 4 );
4006
4011
memcpy (MAC_TAG2 , macs2 + 4 , 4 );
4007
4012
4008
- PrintAndLogEx (SUCCESS , " CSN: " _GREEN_ ("%s" ), sprint_hex (csn , 8 ));
4009
4013
PrintAndLogEx (SUCCESS , " Epurse: %s" , sprint_hex (epurse , 8 ));
4010
4014
PrintAndLogEx (SUCCESS , " MACS1: %s" , sprint_hex (macs , 8 ));
4011
4015
PrintAndLogEx (SUCCESS , " MACS2: %s" , sprint_hex (macs2 , 8 ));
@@ -4072,34 +4076,66 @@ static int CmdHFiClassLegacyRecover(const char *Cmd) {
4072
4076
4073
4077
CLIParserContext * ctx ;
4074
4078
CLIParserInit (& ctx , "hf iclass legrec" ,
4075
- "Attempts to recover the diversified key of a specific iClass card. This may take a long time. The Card must remain be on the PM3 antenna during the whole process! This process may brick the card!" ,
4076
- "hf iclass legrec --macs 0000000089cb984b"
4079
+ "Attempts to recover the diversified key of a specific iClass card. This may take a long time. The Card must remain be on the PM3 antenna during the whole process! This process may brick the card!" ,
4080
+ "hf iclass legrec --macs 0000000089cb984b\n"
4081
+ "hf iclass legrec --macs 0000000089cb984b --index 0 --loop 100 --notest"
4077
4082
);
4078
4083
4079
4084
void * argtable [] = {
4080
4085
arg_param_begin ,
4081
- arg_str1 (NULL , "macs" , "<hex>" , "MACs" ),
4086
+ arg_str1 (NULL , "macs" , "<hex>" , "AA1 Authentication MACs" ),
4087
+ arg_int0 (NULL , "index" , "<dec>" , "Where to start from to retrieve the key, default 0" ),
4088
+ arg_int0 (NULL , "loop" , "<dec>" , "The number of key retrieval cycles to perform, max 10000, default 100" ),
4089
+ arg_lit0 (NULL , "debug" , "Re-enables tracing for debugging. Limits cycles to 1." ),
4090
+ arg_lit0 (NULL , "notest" , "Perform real writes on the card!" ),
4091
+ arg_lit0 (NULL , "allnight" , "Loops the loop for 10 times, recommended loop value of 5000." ),
4082
4092
arg_param_end
4083
4093
};
4084
4094
CLIExecWithReturn (ctx , Cmd , argtable , false);
4085
4095
4086
4096
int macs_len = 0 ;
4087
- uint8_t macs [8 ] = {0 };
4097
+ uint8_t macs [PICOPASS_BLOCK_SIZE ] = {0 };
4088
4098
CLIGetHexWithReturn (ctx , 1 , macs , & macs_len );
4099
+ uint32_t index = arg_get_int_def (ctx , 2 , 0 );
4100
+ uint32_t loop = arg_get_int_def (ctx , 3 , 100 );
4101
+ uint8_t no_first_auth [PICOPASS_BLOCK_SIZE ] = {0 };
4102
+ bool debug = arg_get_lit (ctx , 4 );
4103
+ bool test = true;
4104
+ bool no_test = arg_get_lit (ctx , 5 );
4105
+ bool allnight = arg_get_lit (ctx , 6 );
4089
4106
4090
- if (macs_len > 0 ) {
4091
- if (macs_len != 8 ) {
4092
- PrintAndLogEx (ERR , "MAC is incorrect length" );
4093
- CLIParserFree (ctx );
4094
- return PM3_EINVARG ;
4095
- }
4107
+ if (no_test ){
4108
+ test = false;
4096
4109
}
4097
4110
4111
+ if (loop > 10000 ){
4112
+ PrintAndLogEx (ERR , "Too many loops, arm prone to crashes. For safety specify a number lower than 10000" );
4113
+ CLIParserFree (ctx );
4114
+ return PM3_EINVARG ;
4115
+ }else if (debug || test ){
4116
+ loop = 1 ;
4117
+ }
4118
+
4119
+ uint8_t csn [PICOPASS_BLOCK_SIZE ] = {0 };
4120
+ uint8_t new_div_key [PICOPASS_BLOCK_SIZE ] = {0 };
4121
+ uint8_t CCNR [12 ] = {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 };
4122
+ if (select_only (csn , CCNR , true, false) == false) {
4123
+ DropField ();
4124
+ return PM3_ESOFT ;
4125
+ }
4126
+ HFiClassCalcDivKey (csn , iClass_Key_Table [1 ], new_div_key , false);
4127
+ memcpy (no_first_auth ,new_div_key ,PICOPASS_BLOCK_SIZE );
4128
+
4098
4129
CLIParserFree (ctx );
4099
4130
4100
- CmdHFiClassRecover (macs );
4131
+ if (macs_len && macs_len != PICOPASS_BLOCK_SIZE ) {
4132
+ PrintAndLogEx (ERR , "MAC is incorrect length" );
4133
+ return PM3_EINVARG ;
4134
+ }
4135
+
4136
+ iclass_recover (macs ,index ,loop ,no_first_auth ,debug ,test ,allnight );
4101
4137
4102
- PrintAndLogEx (WARNING , _YELLOW_ ("If the process completed, you can now run 'hf iclass legrecbrute ' with the partial key found." ));
4138
+ PrintAndLogEx (WARNING , _YELLOW_ ("If the process completed successfully , you can now run 'hf iclass legbrute ' with the partial key found." ));
4103
4139
4104
4140
PrintAndLogEx (NORMAL , "" );
4105
4141
return PM3_SUCCESS ;
0 commit comments