├── .gitignore ├── AUTHORS ├── COPYING ├── ChangeLog ├── INSTALL ├── LICENSE ├── Makefile.am ├── NEWS ├── README ├── TODO ├── configure.ac ├── src ├── Makefile.am ├── build_cygwin.sh ├── crapto1.c ├── crapto1.h ├── crypto1.c ├── data │ ├── logs_proxmark3 │ │ ├── trace1.txt │ │ ├── trace2.txt │ │ └── trace3.txt │ └── tmpls_fingerprints │ │ ├── mfcuk_tmpl_oyster.mfd │ │ ├── mfcuk_tmpl_ratb.mfd │ │ └── mfcuk_tmpl_skgt.mfd ├── mfcuk.c ├── mfcuk.h ├── mfcuk_finger.c ├── mfcuk_finger.h ├── mfcuk_mifare.c ├── mfcuk_mifare.h ├── mfcuk_utils.c ├── mfcuk_utils.h ├── mifare.c ├── mifare.h ├── nfc-utils.c ├── nfc-utils.h ├── pm3_mfc_parser.py ├── trace1.txt ├── xgetopt.c └── xgetopt.h └── tools └── proxmark3_parser.py /.gitignore: -------------------------------------------------------------------------------- 1 | .svn 2 | *.o 3 | *~ 4 | aclocal.m4 5 | autom4te.cache/* 6 | compile 7 | config.h 8 | config.h.in 9 | config.log 10 | config.status 11 | configure 12 | depcomp 13 | install-sh 14 | Makefile 15 | Makefile.in 16 | missing 17 | src/.deps/ 18 | src/mfcuk.exe 19 | src/mfcuk 20 | stamp-h1 21 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | = Author 2 | Andrei Costin , http://andreicostin.com 3 | 4 | = Contributors 5 | 6 | Romuald Conty - porting to libnfc 1.3.x, 1.4.x, 1.5.x 7 | Nethemba Core Team - core AC, AM, configure and packaging 8 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nfc-tools/mfcuk/b333a7925a3be80d9496c88c9fef816777827a83/ChangeLog -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | If you use a development version (SVN), you have to run: 2 | autoreconf -is 3 | ./configure 4 | make 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = src 2 | 3 | style: 4 | find . -name "*.[ch]" -exec perl -pi -e 's/[ \t]+$$//' {} \; 5 | find . -name "*.[ch]" -exec astyle --formatted --mode=c --suffix=none \ 6 | --indent=spaces=2 --indent-switches --indent-preprocessor \ 7 | --keep-one-line-blocks --max-instatement-indent=60 \ 8 | --brackets=linux --pad-oper --unpad-paren --pad-header \ 9 | --align-pointer=name {} \; 10 | 11 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nfc-tools/mfcuk/b333a7925a3be80d9496c88c9fef816777827a83/NEWS -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | README 2 | ====== 3 | 4 | Compiling: 5 | autoreconf -is 6 | ./configure 7 | make 8 | 9 | Running (most basic): 10 | ./mfcuk -C -R 0:A -v 2 11 | 12 | PACKAGE 13 | ------- 14 | MiFare Classic Universal toolKit (MFCUK) 15 | 16 | TOOL(S) 17 | ------- 18 | Mifare Classic DarkSide Key Recovery Tool (mfcuk_keyrecovery_darkside.c) (previously known as zv_mf_dark_side) 19 | ... 20 | 21 | LICENSE 22 | ------- 23 | GPL. See MFCUK_LICENSE for more information. 24 | 25 | 26 | BIBLIOGRAPHY (no specific order) 27 | --------------------------------- 28 | 1. [WPMCC09] - "Wirelessly Pickpocketing a Mifare Classic Card" 29 | 2. [ESO08] - "2008-esorics.pdf" 30 | 3. [ESOSL08] - "2008-esorics-slides-updated.pdf" 31 | 4. [KON08] - "2008-koning-thesis.pdf" 32 | 5. [VER08] - "2008-verdult-thesis.pdf" 33 | 6. [PATMC] - "A Practical Attack on the MIFARE Classic.pdf" 34 | 7. [NCOURFIDSEC09] - "mifare_courtois_rfidsec09.pdf" 35 | 8. [MFCLTRB09] - "MifareClassicTroubles.ppt" 36 | 9. [TEEP08] - "p2008-teepe-classic_mistakes.pdf" 37 | 10. [RFIDSANJ] - "RFID Attacks_WCA_San_Jose.pdf" 38 | 11. [ROSS] - "rossum-mifare.pdf" 39 | 12. [PLOTZ08] - "SAR-PR-2008-21_.pdf" 40 | 13. [ROSSSASG] - "SASG35_Peter_v_Rossum_Mifare.pdf" 41 | 14. [DARK2009] - "THE DARK SIDE OF SECURITY BY OBSCURITY and Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime" 42 | 43 | KUDOS and HATS-OFF to (no specific order) (for all the knowledge, time spent researching and all the things) 44 | --------------------- 45 | - blapost@gmail.com - this man is a genius and a technical artist. crapto1 3.1 is the horse power of this tool. PS: you somehow resemble I.C.Wiener anonymous&smart hacker 46 | - Roel and RConty @ libnfc/proxmark - these guys are true advisers, helpful. Thanks for providing a powerfull platform for NFC 47 | - N.Curtois - also a crypto-artist in differential analysis. The 29bit prefix attack is pure genius of theoretical analysis. 48 | - RU University Staff for working out different aspects and papers for Crypto1 analysis 49 | - Nohl, Plotz, Evans - how the "F" did you get those slicers and microscopes :))? 50 | - Milosch M et al. - for pushing the limits for open-source hardware (OpenPCD and OpenPICC) 51 | - Jonathan Westhues - for giving the open-source community the: Proxmark schematics/sources and RFID knowledge 52 | - Nethemba team - for first open-source/GPL nested authentication attack key recovery implementation in MFOC 53 | - hat, schwa226, pgrahamm, marcus2608, phadom - for useful samples, advices, traces and all the things 54 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | TODO 2 | ==== 3 | 4 | PACKAGE 5 | ------- 6 | MiFare Classic Universal toolKit (MFCUK) 7 | 8 | TOOL(S) 9 | ------- 10 | Mifare Classic DarkSide Key Recovery Tool (mfcuk_keyrecovery_darkside.c) (previously known as zv_mf_dark_side) 11 | ... 12 | 13 | ITEMS 14 | ===== 15 | 0. Integrate with MFOC into MFCUK 16 | 1. Improve the performance (though not bad) 17 | 2. Optimize bits operations 18 | 3. Remove dead-code/commented block after testing 19 | 4. Proper error handling in some cases (not critical errors, but nice to have checks in place) 20 | 5. Periodically save the state (or most important part of it at least) such as of Nt/Nr arrays, etc., so that it can later be resumed on the same card 21 | 6. Calibration methodology and routine for MFCUK to determine best field on/off delays so that it generates the lowest entropy for tag's Nt values -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([mfcuk], [0.3.8], [zveriu@gmail.com]) 2 | 3 | AM_INIT_AUTOMAKE 4 | 5 | AC_PROG_CC 6 | 7 | AC_CONFIG_HEADERS([config.h]) 8 | 9 | m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) 10 | 11 | # Checks for pkg-config modules. 12 | LIBNFC_REQUIRED_VERSION=1.7.0 13 | PKG_CHECK_MODULES([libnfc], [libnfc >= $LIBNFC_REQUIRED_VERSION], [], [AC_MSG_ERROR([libnfc >= $LIBNFC_REQUIRED_VERSION is mandatory.])]) 14 | 15 | PKG_CONFIG_REQUIRES="libnfc" 16 | AC_SUBST([PKG_CONFIG_REQUIRES]) 17 | 18 | # Checks for typedefs, structures, and compiler characteristics. 19 | AC_C_INLINE 20 | AC_HEADER_STDBOOL 21 | AC_TYPE_SIZE_T 22 | AC_TYPE_UINT16_T 23 | AC_TYPE_UINT32_T 24 | AC_TYPE_UINT64_T 25 | AC_TYPE_UINT8_T 26 | 27 | # Checks for library functions. 28 | AC_FUNC_MALLOC 29 | AC_FUNC_REALLOC 30 | 31 | AC_CHECK_FUNCS([memset strchr strtoul]) 32 | 33 | # Checks for endianness convertion 34 | AC_CHECK_HEADERS([endian.h sys/endian.h CoreFoundation/CoreFoundation.h]) 35 | if test $ac_cv_header_endian_h = "no" -a $ac_cv_header_sys_endian_h = "no" -a $ac_cv_header_CoreFoundation_CoreFoundation_h = "no"; then 36 | AC_MSG_ERROR(["Can't locate usable header file for endianness convertions."]); 37 | fi 38 | 39 | AC_CHECK_HEADERS([byteswap.h]) 40 | 41 | AC_CHECK_HEADERS([unistd.h]) 42 | AM_CONDITIONAL([HAVE_UNISTD], [test $ac_cv_header_unistd_h = "yes"]) 43 | 44 | AC_DEFINE([_XOPEN_SOURCE], [600], [Define to 500 if Single Unix conformance is wanted, 600 for sixth revision.]) 45 | 46 | # Help us to write great code ;-) 47 | CFLAGS="$CFLAGS -Wall -pedantic -Wextra -std=c99" 48 | 49 | AC_CONFIG_FILES([Makefile 50 | src/Makefile]) 51 | AC_OUTPUT 52 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CFLAGS = @libnfc_CFLAGS@ 2 | 3 | bin_PROGRAMS = mfcuk 4 | 5 | noinst_HEADERS = crapto1.h mifare.h nfc-utils.h mfcuk_mifare.h mfcuk_finger.h mfcuk_utils.h mfcuk.h xgetopt.h 6 | 7 | mfcuk_SOURCES = crapto1.c crypto1.c mifare.c nfc-utils.c mfcuk_mifare.c mfcuk_finger.c mfcuk_utils.c mfcuk.c 8 | mfcuk_LDADD = @libnfc_LIBS@ 9 | 10 | # If system does not have unistd.h, use our own getopt function from xgetopt.c 11 | if ! HAVE_UNISTD 12 | mfcuk_SOURCES += xgetopt.c 13 | endif 14 | 15 | # dist_man_MANS = mfcuk.1 16 | -------------------------------------------------------------------------------- /src/build_cygwin.sh: -------------------------------------------------------------------------------- 1 | MAIN_FILE=mfcuk_keyrecovery_darkside 2 | LIBNFC=libnfc 3 | CFLAGS=`pkg-config --cflags ${LIBNFC}` 4 | CFLAGS_LIBNFC=`pkg-config --cflags libnfc | cut -d ' ' -f 1`/${LIBNFC} 5 | 6 | gcc ./${MAIN_FILE}.c ./mfcuk_mifare.c ./mfcuk_utils.c ./mfcuk_finger.c ./crapto1.c ./crypto1.c ./bin/libnfc.lib ${CFLAGS} ${CFLAGS_LIBNFC} -o ./bin/${MAIN_FILE}_cygwin.exe 7 | -------------------------------------------------------------------------------- /src/crapto1.c: -------------------------------------------------------------------------------- 1 | /* crapto1.c 2 | 3 | This program is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU General Public License 5 | as published by the Free Software Foundation; either version 2 6 | of the License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, 16 | Boston, MA 02110-1301, US$ 17 | 18 | Copyright (C) 2008-2008 bla 19 | */ 20 | #include "crapto1.h" 21 | #include 22 | 23 | #if !defined LOWMEM && defined __GNUC__ 24 | static uint8_t filterlut[1 << 20]; 25 | static void __attribute__((constructor)) fill_lut(void) 26 | { 27 | uint32_t i; 28 | for (i = 0; i < 1 << 20; ++i) 29 | filterlut[i] = filter(i); 30 | } 31 | #define filter(x) (filterlut[(x) & 0xfffff]) 32 | #endif 33 | 34 | static void quicksort(uint32_t *const start, uint32_t *const stop) 35 | { 36 | uint32_t *it = start + 1, *rit = stop; 37 | 38 | if (it > rit) 39 | return; 40 | 41 | while (it < rit) 42 | if (*it <= *start) 43 | ++it; 44 | else if (*rit > *start) 45 | --rit; 46 | else { 47 | uint32_t x = *it; 48 | *it = *rit; 49 | *rit = x; 50 | } 51 | 52 | if (*rit >= *start) 53 | --rit; 54 | if (rit != start) { 55 | uint32_t x = *it; 56 | *it = *rit; 57 | *rit = x; 58 | } 59 | 60 | quicksort(start, rit - 1); 61 | quicksort(rit + 1, stop); 62 | } 63 | /** binsearch 64 | * Binary search for the first occurence of *stop's MSB in sorted [start,stop] 65 | */ 66 | static inline uint32_t * 67 | binsearch(uint32_t *start, uint32_t *stop) 68 | { 69 | uint32_t mid, val = *stop & 0xff000000; 70 | while (start != stop) 71 | if (start[mid = (stop - start) >> 1] > val) 72 | stop = &start[mid]; 73 | else 74 | start += mid + 1; 75 | 76 | return start; 77 | } 78 | 79 | /** update_contribution 80 | * helper, calculates the partial linear feedback contributions and puts in MSB 81 | */ 82 | static inline void 83 | update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) 84 | { 85 | uint32_t p = *item >> 25; 86 | 87 | p = p << 1 | parity(*item & mask1); 88 | p = p << 1 | parity(*item & mask2); 89 | *item = p << 24 | (*item & 0xffffff); 90 | } 91 | 92 | /** extend_table 93 | * using a bit of the keystream extend the table of possible lfsr states 94 | */ 95 | static inline void 96 | extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in) 97 | { 98 | in <<= 24; 99 | for (*tbl <<= 1; tbl <= *end; *++tbl <<= 1) 100 | if (filter(*tbl) ^ filter(*tbl | 1)) { 101 | *tbl |= filter(*tbl) ^ bit; 102 | update_contribution(tbl, m1, m2); 103 | *tbl ^= in; 104 | } else if (filter(*tbl) == bit) { 105 | *++*end = tbl[1]; 106 | tbl[1] = tbl[0] | 1; 107 | update_contribution(tbl, m1, m2); 108 | *tbl++ ^= in; 109 | update_contribution(tbl, m1, m2); 110 | *tbl ^= in; 111 | } else 112 | *tbl-- = *(*end)--; 113 | } 114 | /** extend_table_simple 115 | * using a bit of the keystream extend the table of possible lfsr states 116 | */ 117 | static inline void 118 | extend_table_simple(uint32_t *tbl, uint32_t **end, int bit) 119 | { 120 | for (*tbl <<= 1; tbl <= *end; *++tbl <<= 1) 121 | if (filter(*tbl) ^ filter(*tbl | 1)) { 122 | *tbl |= filter(*tbl) ^ bit; 123 | } else if (filter(*tbl) == bit) { 124 | *++*end = *++tbl; 125 | *tbl = tbl[-1] | 1; 126 | } else 127 | *tbl-- = *(*end)--; 128 | } 129 | /** recover 130 | * recursively narrow down the search space, 4 bits of keystream at a time 131 | */ 132 | static struct Crypto1State * 133 | recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, 134 | uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, 135 | struct Crypto1State *sl, uint32_t in) { 136 | uint32_t *o, *e, i; 137 | 138 | if (rem == -1) { 139 | for (e = e_head; e <= e_tail; ++e) { 140 | *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4); 141 | for (o = o_head; o <= o_tail; ++o, ++sl) { 142 | sl->even = *o; 143 | sl->odd = *e ^ parity(*o & LF_POLY_ODD); 144 | sl[1].odd = sl[1].even = 0; 145 | } 146 | } 147 | return sl; 148 | } 149 | 150 | for (i = 0; i < 4 && rem--; i++) { 151 | extend_table(o_head, &o_tail, (oks >>= 1) & 1, 152 | LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); 153 | if (o_head > o_tail) 154 | return sl; 155 | 156 | extend_table(e_head, &e_tail, (eks >>= 1) & 1, 157 | LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, (in >>= 2) & 3); 158 | if (e_head > e_tail) 159 | return sl; 160 | } 161 | 162 | quicksort(o_head, o_tail); 163 | quicksort(e_head, e_tail); 164 | 165 | while (o_tail >= o_head && e_tail >= e_head) 166 | if (((*o_tail ^ *e_tail) >> 24) == 0) { 167 | o_tail = binsearch(o_head, o = o_tail); 168 | e_tail = binsearch(e_head, e = e_tail); 169 | sl = recover(o_tail--, o, oks, 170 | e_tail--, e, eks, rem, sl, in); 171 | } else if (*o_tail > *e_tail) 172 | o_tail = binsearch(o_head, o_tail) - 1; 173 | else 174 | e_tail = binsearch(e_head, e_tail) - 1; 175 | 176 | return sl; 177 | } 178 | /** lfsr_recovery 179 | * recover the state of the lfsr given 32 bits of the keystream 180 | * additionally you can use the in parameter to specify the value 181 | * that was fed into the lfsr at the time the keystream was generated 182 | */ 183 | struct Crypto1State *lfsr_recovery32(uint32_t ks2, uint32_t in) { 184 | struct Crypto1State *statelist; 185 | uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; 186 | uint32_t *even_head = 0, *even_tail = 0, eks = 0; 187 | int i; 188 | 189 | for (i = 31; i >= 0; i -= 2) 190 | oks = oks << 1 | BEBIT(ks2, i); 191 | for (i = 30; i >= 0; i -= 2) 192 | eks = eks << 1 | BEBIT(ks2, i); 193 | 194 | odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); 195 | even_head = even_tail = malloc(sizeof(uint32_t) << 21); 196 | statelist = malloc(sizeof(struct Crypto1State) << 18); 197 | if (!odd_tail-- || !even_tail-- || !statelist) 198 | goto out; 199 | 200 | statelist->odd = statelist->even = 0; 201 | 202 | for (i = 1 << 20; i >= 0; --i) { 203 | if (filter(i) == (oks & 1)) 204 | *++odd_tail = i; 205 | if (filter(i) == (eks & 1)) 206 | *++even_tail = i; 207 | } 208 | 209 | for (i = 0; i < 4; i++) { 210 | extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); 211 | extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); 212 | } 213 | 214 | in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); 215 | recover(odd_head, odd_tail, oks, 216 | even_head, even_tail, eks, 11, statelist, in << 1); 217 | 218 | out: 219 | free(odd_head); 220 | free(even_head); 221 | return statelist; 222 | } 223 | 224 | static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214, 225 | 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, 226 | 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA 227 | }; 228 | static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60, 229 | 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, 230 | 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, 231 | 0x7EC7EE90, 0x7F63F748, 0x79117020 232 | }; 233 | static const uint32_t T1[] = { 234 | 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, 235 | 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, 236 | 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, 237 | 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C 238 | }; 239 | static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0, 240 | 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, 241 | 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, 242 | 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, 243 | 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, 244 | 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0 245 | }; 246 | static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD}; 247 | static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; 248 | /** Reverse 64 bits of keystream into possible cipher states 249 | * Variation mentioned in the paper. Somewhat optimized version 250 | */ 251 | struct Crypto1State *lfsr_recovery64(uint32_t ks2, uint32_t ks3) { 252 | struct Crypto1State *statelist, *sl; 253 | uint8_t oks[32], eks[32], hi[32]; 254 | uint32_t low = 0, win = 0; 255 | uint32_t *tail, table[1 << 16]; 256 | int i, j; 257 | 258 | sl = statelist = malloc(sizeof(struct Crypto1State) << 4); 259 | if (!sl) 260 | return 0; 261 | sl->odd = sl->even = 0; 262 | 263 | for (i = 30; i >= 0; i -= 2) { 264 | oks[i >> 1] = BIT(ks2, i ^ 24); 265 | oks[16 + (i >> 1)] = BIT(ks3, i ^ 24); 266 | } 267 | for (i = 31; i >= 0; i -= 2) { 268 | eks[i >> 1] = BIT(ks2, i ^ 24); 269 | eks[16 + (i >> 1)] = BIT(ks3, i ^ 24); 270 | } 271 | 272 | for (i = 0xfffff; i >= 0; --i) { 273 | if (filter(i) != oks[0]) 274 | continue; 275 | 276 | *(tail = table) = i; 277 | for (j = 1; tail >= table && j < 29; ++j) 278 | extend_table_simple(table, &tail, oks[j]); 279 | 280 | if (tail < table) 281 | continue; 282 | 283 | for (j = 0; j < 19; ++j) 284 | low = low << 1 | parity(i & S1[j]); 285 | for (j = 0; j < 32; ++j) 286 | hi[j] = parity(i & T1[j]); 287 | 288 | for (; tail >= table; --tail) { 289 | for (j = 0; j < 3; ++j) { 290 | *tail = *tail << 1; 291 | *tail |= parity((i & C1[j]) ^(*tail & C2[j])); 292 | if (filter(*tail) != oks[29 + j]) 293 | goto continue2; 294 | } 295 | 296 | for (j = 0; j < 19; ++j) 297 | win = win << 1 | parity(*tail & S2[j]); 298 | 299 | win ^= low; 300 | for (j = 0; j < 32; ++j) { 301 | win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]); 302 | if (filter(win) != eks[j]) 303 | goto continue2; 304 | } 305 | 306 | *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail); 307 | sl->odd = *tail ^ parity(LF_POLY_ODD & win); 308 | sl->even = win; 309 | ++sl; 310 | sl->odd = sl->even = 0; 311 | continue2: 312 | ; 313 | } 314 | } 315 | return statelist; 316 | } 317 | 318 | uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb); 319 | uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb); 320 | uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd); 321 | 322 | /** lfsr_rollback_bit 323 | * Rollback the shift register in order to get previous states 324 | */ 325 | uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) 326 | { 327 | int out; 328 | uint8_t ret; 329 | 330 | s->odd &= 0xffffff; 331 | uint32_t x = s->odd; 332 | s->odd = s->even; 333 | s->even = x; 334 | 335 | out = s->even & 1; 336 | out ^= LF_POLY_EVEN & (s->even >>= 1); 337 | out ^= LF_POLY_ODD & s->odd; 338 | out ^= !!in; 339 | out ^= (ret = filter(s->odd)) & !!fb; 340 | 341 | s->even |= parity(out) << 23; 342 | return ret; 343 | } 344 | /** lfsr_rollback_byte 345 | * Rollback the shift register in order to get previous states 346 | */ 347 | uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) 348 | { 349 | int i; 350 | uint8_t ret = 0; 351 | for (i = 7; i >= 0; --i) 352 | ret |= lfsr_rollback_bit(s, BIT(in, i), fb) << i; 353 | return ret; 354 | } 355 | /** lfsr_rollback_word 356 | * Rollback the shift register in order to get previous states 357 | */ 358 | uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) 359 | { 360 | int i; 361 | uint32_t ret = 0; 362 | for (i = 31; i >= 0; --i) 363 | ret |= lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24); 364 | return ret; 365 | } 366 | 367 | /** nonce_distance 368 | * x,y valid tag nonces, then prng_successor(x, nonce_distance(x, y)) = y 369 | */ 370 | static uint16_t *dist = 0; 371 | int nonce_distance(uint32_t from, uint32_t to) 372 | { 373 | uint16_t x, i; 374 | if (!dist) { 375 | dist = malloc(2 << 16); 376 | if (!dist) 377 | return -1; 378 | for (x = i = 1; i; ++i) { 379 | dist[(x & 0xff) << 8 | x >> 8] = i; 380 | x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; 381 | } 382 | } 383 | return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; 384 | } 385 | 386 | 387 | static uint32_t fastfwd[2][8] = { 388 | { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, 389 | { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980} 390 | }; 391 | 392 | 393 | /** lfsr_prefix_ks 394 | * 395 | * Is an exported helper function from the common prefix attack 396 | * Described in the "dark side" paper. It returns an -1 terminated array 397 | * of possible partial(21 bit) secret state. 398 | * The required keystream(ks) needs to contain the keystream that was used to 399 | * encrypt the NACK which is observed when varying only the 4 last bits of Nr 400 | * only correct iff [NR_3] ^ NR_3 does not depend on Nr_3 401 | */ 402 | uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) 403 | { 404 | uint32_t c, entry, *candidates = malloc(4 << 21); 405 | int i, size = (1 << 21) - 1; 406 | 407 | if (!candidates) 408 | return 0; 409 | 410 | for (i = 0; i <= size; ++i) 411 | candidates[i] = i; 412 | 413 | for (c = 0; c < 8; ++c) 414 | for (i = 0; i <= size; ++i) { 415 | entry = candidates[i] ^ fastfwd[isodd][c]; 416 | 417 | if (filter(entry >> 1) != BIT(ks[c], isodd) || 418 | filter(entry) != BIT(ks[c], isodd + 2)) 419 | candidates[i--] = candidates[size--]; 420 | } 421 | 422 | candidates[size + 1] = -1; 423 | 424 | return candidates; 425 | } 426 | 427 | /** check_pfx_parity 428 | * helper function which eliminates possible secret states using parity bits 429 | */ 430 | static struct Crypto1State * 431 | check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], 432 | uint32_t odd, uint32_t even, struct Crypto1State *sl) { 433 | uint32_t ks1, nr, ks2, rr, ks3, c, good = 1; 434 | 435 | for (c = 0; good && c < 8; ++c) { 436 | sl->odd = odd ^ fastfwd[1][c]; 437 | sl->even = even ^ fastfwd[0][c]; 438 | 439 | lfsr_rollback_bit(sl, 0, 0); 440 | lfsr_rollback_bit(sl, 0, 0); 441 | 442 | ks3 = lfsr_rollback_bit(sl, 0, 0); 443 | ks2 = lfsr_rollback_word(sl, 0, 0); 444 | ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); 445 | 446 | nr = ks1 ^(prefix | c << 5); 447 | rr = ks2 ^ rresp; 448 | 449 | good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); 450 | good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); 451 | good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); 452 | good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); 453 | good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3; 454 | } 455 | 456 | return sl + good; 457 | } 458 | 459 | 460 | /** lfsr_common_prefix 461 | * Implentation of the common prefix attack. 462 | * Requires the 29 bit constant prefix used as reader nonce (pfx) 463 | * The reader response used (rr) 464 | * The keystream used to encrypt the observed NACK's (ks) 465 | * The parity bits (par) 466 | * It returns a zero terminated list of possible cipher states after the 467 | * tag nonce was fed in 468 | */ 469 | struct Crypto1State * 470 | lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]) { 471 | struct Crypto1State *statelist, *s; 472 | uint32_t *odd, *even, *o, *e, top; 473 | 474 | odd = lfsr_prefix_ks(ks, 1); 475 | even = lfsr_prefix_ks(ks, 0); 476 | 477 | s = statelist = malloc((sizeof *statelist) << 20); 478 | if (!s || !odd || !even) { 479 | free(odd); 480 | free(even); 481 | free(statelist); 482 | return 0; 483 | } 484 | 485 | for (o = odd; *o + 1; ++o) 486 | for (e = even; *e + 1; ++e) 487 | for (top = 0; top < 64; ++top) { 488 | *o += 1 << 21; 489 | *e += (!(top & 7) + 1) << 21; 490 | s = check_pfx_parity(pfx, rr, par, *o, *e, s); 491 | } 492 | 493 | s->odd = s->even = 0; 494 | 495 | free(odd); 496 | free(even); 497 | 498 | return statelist; 499 | } 500 | -------------------------------------------------------------------------------- /src/crapto1.h: -------------------------------------------------------------------------------- 1 | /* crapto1.h 2 | 3 | This program is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU General Public License 5 | as published by the Free Software Foundation; either version 2 6 | of the License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 16 | MA 02110-1301, US$ 17 | 18 | Copyright (C) 2008-2009 bla 19 | */ 20 | #ifndef CRAPTO1_INCLUDED 21 | #define CRAPTO1_INCLUDED 22 | #include 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | struct Crypto1State {uint32_t odd, even;}; 28 | struct Crypto1State *crypto1_create(uint64_t); 29 | void crypto1_destroy(struct Crypto1State *); 30 | void crypto1_get_lfsr(struct Crypto1State *, uint64_t *); 31 | uint8_t crypto1_bit(struct Crypto1State *, uint8_t, int); 32 | uint8_t crypto1_byte(struct Crypto1State *, uint8_t, int); 33 | uint32_t crypto1_word(struct Crypto1State *, uint32_t, int); 34 | uint32_t prng_successor(uint32_t x, uint32_t n); 35 | 36 | struct Crypto1State *lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]); 37 | struct Crypto1State *lfsr_recovery32(uint32_t ks2, uint32_t in); 38 | struct Crypto1State *lfsr_recovery64(uint32_t ks2, uint32_t ks3); 39 | 40 | void lfsr_rollback(struct Crypto1State *s, uint32_t in, int fb); 41 | uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb); 42 | int nonce_distance(uint32_t from, uint32_t to); 43 | #define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\ 44 | uint32_t __n = 0,__M = 0, N = 0;\ 45 | int __i;\ 46 | for(; __n < 1 << 16; N = prng_successor(__M = ++__n, 16))\ 47 | for(__i = FSIZE - 1; __i >= 0; __i--)\ 48 | if(BIT(FILTER, __i) ^ parity(__M & 0xFF01))\ 49 | break;\ 50 | else if(__i)\ 51 | __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ 52 | else 53 | 54 | #define LF_POLY_ODD (0x29CE5C) 55 | #define LF_POLY_EVEN (0x870804) 56 | #define BIT(x, n) ((x) >> (n) & 1) 57 | #define BEBIT(x, n) BIT(x, (n) ^ 24) 58 | static inline int parity(uint32_t x) 59 | { 60 | #if !defined __i386__ || !defined __GNUC__ 61 | x ^= x >> 16; 62 | x ^= x >> 8; 63 | x ^= x >> 4; 64 | return BIT(0x6996, x & 0xf); 65 | #else 66 | __asm__("movl %1, %%eax\n" 67 | "mov %%ax, %%cx\n" 68 | "shrl $0x10, %%eax\n" 69 | "xor %%ax, %%cx\n" 70 | "xor %%ch, %%cl\n" 71 | "setpo %%al\n" 72 | "movzx %%al, %0\n": "=r"(x) : "r"(x): "eax", "ecx"); 73 | return x; 74 | #endif 75 | } 76 | static inline int filter(uint32_t const x) 77 | { 78 | uint32_t f; 79 | 80 | f = 0xf22c0 >> (x & 0xf) & 16; 81 | f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8; 82 | f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4; 83 | f |= 0x1e458 >> (x >> 12 & 0xf) & 2; 84 | f |= 0x0d938 >> (x >> 16 & 0xf) & 1; 85 | return BIT(0xEC57E80A, f); 86 | } 87 | #ifdef __cplusplus 88 | } 89 | #endif 90 | #endif 91 | -------------------------------------------------------------------------------- /src/crypto1.c: -------------------------------------------------------------------------------- 1 | /* crypto1.c 2 | 3 | This program is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU General Public License 5 | as published by the Free Software Foundation; either version 2 6 | of the License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 16 | MA 02110-1301, US 17 | 18 | Copyright (C) 2008-2008 bla 19 | */ 20 | #include "crapto1.h" 21 | #include 22 | 23 | #define SWAPENDIAN(x)\ 24 | (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) 25 | 26 | struct Crypto1State *crypto1_create(uint64_t key) { 27 | struct Crypto1State *s = malloc(sizeof(*s)); 28 | int i; 29 | 30 | for (i = 47; s && i > 0; i -= 2) { 31 | s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7); 32 | s->even = s->even << 1 | BIT(key, i ^ 7); 33 | } 34 | return s; 35 | } 36 | void crypto1_destroy(struct Crypto1State *state) 37 | { 38 | free(state); 39 | } 40 | void crypto1_get_lfsr(struct Crypto1State *state, uint64_t *lfsr) 41 | { 42 | int i; 43 | for (*lfsr = 0, i = 23; i >= 0; --i) { 44 | *lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3); 45 | *lfsr = *lfsr << 1 | BIT(state->even, i ^ 3); 46 | } 47 | } 48 | uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted) 49 | { 50 | uint32_t feedin; 51 | uint8_t ret = filter(s->odd); 52 | 53 | feedin = ret & !!is_encrypted; 54 | feedin ^= !!in; 55 | feedin ^= LF_POLY_ODD & s->odd; 56 | feedin ^= LF_POLY_EVEN & s->even; 57 | s->even = s->even << 1 | parity(feedin); 58 | 59 | uint32_t x = s->odd; 60 | s->odd = s->even; 61 | s->even = x; 62 | 63 | return ret; 64 | } 65 | uint8_t crypto1_byte(struct Crypto1State *s, uint8_t in, int is_encrypted) 66 | { 67 | uint8_t i, ret = 0; 68 | 69 | for (i = 0; i < 8; ++i) 70 | ret |= crypto1_bit(s, BIT(in, i), is_encrypted) << i; 71 | 72 | return ret; 73 | } 74 | uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) 75 | { 76 | uint32_t i, ret = 0; 77 | 78 | for (i = 0; i < 32; ++i) 79 | ret |= crypto1_bit(s, BEBIT(in, i), is_encrypted) << (i ^ 24); 80 | 81 | return ret; 82 | } 83 | 84 | /* prng_successor 85 | * helper used to obscure the keystream during authentication 86 | */ 87 | uint32_t prng_successor(uint32_t x, uint32_t n) 88 | { 89 | SWAPENDIAN(x); 90 | while (n--) 91 | x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; 92 | 93 | return SWAPENDIAN(x); 94 | } 95 | -------------------------------------------------------------------------------- /src/data/logs_proxmark3/trace1.txt: -------------------------------------------------------------------------------- 1 | + 561882: 1 : 26 2 | + 64: 2 : TAG 04 00 3 | + 10217: 2 : 93 20 4 | + 64: 5 : TAG 9c 59 9b 32 6c 5 | + 12313: 9 : 93 70 9c 59 9b 32 6c 6b 30 6 | + 64: 3 : TAG 08 b6 dd 7 | + 923318: 4 : 60 00 f5 7b 8 | + 112: 4 : TAG 82 a4 16 6c 9 | + 6985: 8 : a1 e4! 58 ce! 6e ea! 41 e0! !crc 10 | + 64: 4 : TAG 5c! ad f4 39! 11 | + 811513: 4 : 8e 0e! 5d! b9 !crc 12 | + 112: 4 : TAG 5a! 92 0d! 85! 13 | + 6946: 8 : 98! d7 6b! 77 d6 c6 e8 70 !crc 14 | + 64: 4 : TAG ca 7e! 0b! 63! 15 | + 670868: 4 : 3e! 70 9c! 8a !crc 16 | + 112: 4 : TAG 36! 41 24! 79 17 | + 9505: 8 : 1b! 8c 3a! 48! 83 5a 4a! 27 !crc 18 | + 64: 4 : TAG 40! 6a! 99! 4b 19 | + 905612: 4 : c9 7c 64! 13! !crc 20 | + 112: 4 : TAG b5! ab! 1d! 2b 21 | + 6936: 8 : 7e! d2 5c! ca! 4b! 50! 88! c4 !crc 22 | + 64: 4 : TAG bf dd 01 be! 23 | + 987853: 4 : 56 98 49 d6! !crc 24 | + 72: 18 : TAG 09 bf! f5! f6! fc! b9! 5e! 51! 07 ac f6 72 f8 73 3b! 1b 73! ad! !crc 25 | + 94864: 4 : 5c! 7b 24! 02 !crc 26 | + 72: 18 : TAG a0 1f! 0b! b7 0d! ba c9 e7! fa! 36! 47 d2 a0! 01! 40! 87 ff 95! !crc 27 | + 94827: 4 : c9 90 dc! a3 !crc 28 | + 72: 18 : TAG df b8! 7a bc! 17! 99 82! 5c 55 d5! 98! 68 8b f8 e7 89 dc 42! !crc 29 | + 99081: 4 : 9f! d5 0f! d8! !crc 30 | + 72: 18 : TAG ca! 40 fa! 34 82 cc 3e de 1f! 7f f7! f0 62! 18! 77! 34 30 07 !crc 31 | + 93995: 4 : ad 7f! 3e 0c! !crc 32 | + 72: 18 : TAG f4! 2b 17! 4c a2! 5a 0c! a0! d8 03! 05 cc cc 4c 1f 12! 0c! 78! !crc 33 | + 94857: 4 : f1! b4 f0 3b! !crc 34 | + 72: 18 : TAG 8f da ca 17! 42 8e 24 c9! 8e fb! 38! aa! 39 e2! dd dd! a8 a6 !crc 35 | + 94850: 4 : c4 03! 7b! 9a !crc 36 | + 72: 18 : TAG 9f! 42! 42 49! cd d1! 3d! fd 8e 8f d3 8d! d5! ca! ef! 15 84 c9! !crc 37 | + 93961: 4 : 33! 3b! ae 0a! !crc 38 | + 72: 18 : TAG 74 ed! 58 46! e7 cc 48 d1! 5a 4b b0! 3a! c1 79! 8a! bf! e7! 42 !crc 39 | + 93193: 4 : f6 ec! 36 91! !crc 40 | + 72: 18 : TAG 79! 63 89! 21! 24 1e 3e! 03! a8! c3! 9b 95! a1 ad! 6c! 34 52 94 !crc 41 | + 94866: 4 : ad! 5c! 47 c5! !crc 42 | + 72: 18 : TAG 68 d4 9d c2! 2b 18 46! f7 e8! 28 ea 03 a4 df d5! 9f 23 00! !crc 43 | + 93994: 4 : 41 4c! 40! 11 !crc 44 | + 72: 18 : TAG b1 95 17! 84! ac fc! 31 b8! 02 40 97! ec! 4c 19 6f e9 f0! 8c! !crc 45 | + 94818: 4 : b8! b5! 5c! 74! !crc 46 | + 72: 18 : TAG c6 03 b9 92! 7d! eb! 13 8a 56 b7 9c 7c 07 3d! 6a 95! 7e! 44 !crc 47 | 48 | # http://www.proxmark.org/forum/post/550/#p550 49 | # UID = 0x9c599b32 50 | # KEY = 0xffffffffffff 51 | # 0x9c599b32 0x82a4166c 0xa1e458ce 0x6eea41e0 0x5cadf439 52 | -------------------------------------------------------------------------------- /src/data/logs_proxmark3/trace2.txt: -------------------------------------------------------------------------------- 1 | + 0: 0: TAG 00! 2 | + 337281: : 30 00 02 a8 3 | + 5032: : 50 00 57 cd 4 | + 9952: : 52 5 | + 141825: : 30 00 02 a8 6 | + 5040: : 50 00 57 cd 7 | + 10528: : 52 8 | + 7624: : 93 20 9 | + 64: 0: TAG ca fd ca 13 ee 10 | + 10656: : 93 70 ca fd ca 13 ee 8e ea 11 | + 64: 0: TAG 08 b6 dd 12 | + 89345: : 30 00 02 a8 13 | + 72: 0: TAG 04 14 | + 4976: : 50 00 57 cd 15 | + 9952: : 52 16 | + 64: 0: TAG 04 00 17 | + 7720: : 93 20 18 | + 64: 0: TAG ca fd ca 13 ee 19 | + 14120: : 93 70 ca fd ca 13 ee 8e ea 20 | + 64: 0: TAG 08 b6 dd 21 | + 105352: : 30 00 02 a8 22 | + 72: 0: TAG 04 23 | + 21952: : 50 00 57 cd 24 | + 9944: : 52 25 | + 64: 0: TAG 04 00 26 | + 14448: : 93 20 27 | + 64: 0: TAG ca fd ca 13 ee 28 | + 10736: : 93 70 ca fd ca 13 ee 8e ea 29 | + 64: 0: TAG 08 b6 dd 30 | + 124904: : 30 00 02 a8 31 | + 72: 0: TAG 04 32 | + 4968: : 50 00 57 cd 33 | + 10346: : 52 34 | + 64: 0: TAG 04 00 35 | + 7272: : 93 20 36 | + 64: 0: TAG ca fd ca 13 ee 37 | + 13240: : 93 70 ca fd ca 13 ee 8e ea 38 | + 64: 0: TAG 08 b6 dd 39 | + 89320: : 30 00 02 a8 40 | + 72: 0: TAG 04 41 | + 5000: : 50 00 57 cd 42 | + 10784: : 52 43 | + 64: 0: TAG 04 00 44 | + 7680: : 93 20 45 | + 64: 0: TAG ca fd ca 13 ee 46 | + 11560: : 93 70 ca fd ca 13 ee 8e ea 47 | + 64: 0: TAG 08 b6 dd 48 | + 89305: : 30 00 02 a8 49 | + 72: 0: TAG 04 50 | + 4960: : 50 00 57 cd 51 | + 10040: : 52 52 | + 64: 0: TAG 04 00 53 | + 43208: : 93 20 54 | + 64: 0: TAG ca fd ca 13 ee 55 | + 10696: : 93 70 ca fd ca 13 ee 8e ea 56 | + 64: 0: TAG 08 b6 dd 57 | + 89305: : 30 00 02 a8 58 | + 72: 0: TAG 04 59 | + 4984: : 50 00 57 cd 60 | + 10824: : 52 61 | + 64: 0: TAG 04 00 62 | + 9352: : 93 20 63 | + 64: 0: TAG ca fd ca 13 ee 64 | + 10680: : 93 70 ca fd ca 13 ee 8e ea 65 | + 64: 0: TAG 08 b6 dd 66 | + 90184: : 30 00 02 a8 67 | + 72: 0: TAG 04 68 | + 4984: : 50 00 57 cd 69 | + 9944: : 52 70 | + 64: 0: TAG 04 00 71 | + 102224: : 93 20 72 | + 64: 0: TAG ca fd ca 13 ee 73 | + 939902: : 93 70 ca fd ca 13 ee 8e ea 74 | + 64: 0: TAG 08 b6 dd 75 | + 752874: : 60 00 f5 7b 76 | + 112: 0: TAG e9 01 a1 69 77 | + 10352: : 71 03 4a be f9 2f 51 2f !crc 78 | + 64: 0: TAG 99 25! ef! 9d! 79 | + 864094: : dc 9f f9 65 !crc 80 | + 72: 0: TAG e5 82 07 a2! e1 ea c5 cd 14 85! aa! 97! 58! 17 0e b5 ab! ff !crc 81 | + 312194: : 4b de 1d e9 !crc 82 | + 72: 0: TAG 04 0a! 1c! ad 54! 3e ed 03! 60! 82 42 e4 da! 83! 98! 22 14! f2 !crc 83 | + 290616: : cc 06 39 d7 !crc 84 | + 72: 0: TAG 0a a3 f1 86 34 8f 9d! 1f! 4d! 7e! f1! 56 8e 9f ee 32! 88 89 !crc 85 | + 204658: : 80 f4 eb 55 !crc 86 | + 72: 0: TAG 9d 6e 88 db! fc 88 14! fa af dd 10! cc 74 81! 71 52 fd! d9 !crc 87 | + 543394: : 26 f0 ea aa !crc 88 | + 72: 0: TAG d5! a1! ed 8d 73! fe! 3e 94 56 db! 39! ad! dc! ff 9c! a3 f2 24! !crc 89 | + 299722: : 56 00 9a 4d !crc 90 | + 72: 0: TAG 58! cf 13 c4 78 50! 0f! b8 73 1c 33! 25 23 12 1e a2! 4a 32! !crc 91 | + 215834: : db a2 ec 42 !crc 92 | + 72: 0: TAG 78 3f! 30! 02 64 85 63! fe! 81! 9e 27 70 f7 cc b0 77 ce! 4b !crc 93 | + 97112: : a5 78 3e 3d !crc 94 | + 72: 0: TAG ef! fd! 47! 36 e5 c3! c1 96 c5 97 7b! 3d! ce! ab! 6e! 5e bd 8b !crc 95 | + 87752: : a1 9b 41 09 !crc 96 | + 72: 0: TAG e5! e1! 28 7d! ee ae! 60 d7 29 96! d7! a1! 6e 4e da! 66! 93 bd! !crc 97 | + 89104: : 70 ff 99 6c !crc 98 | + 72: 0: TAG 17 97 04 0a! 92! 66! 7d e7! 62 a8 b5! 56 d4 a1 ab! b8 70 4e! !crc 99 | + 87928: : 5e 6c 03 09 !crc 100 | + 72: 0: TAG c5! da 86 a4 a0 24! ab da! f3 d9 95! f3! 2d! 8e! b7! 07 a5! e6 !crc 101 | + 88434: : 2e 91 6d 54 !crc 102 | + 72: 0: TAG b4 37 84 6b! fd! c8 71 f9 bf! a1! 96! af! 85! d3 b9! f0! 5b! 57! !crc 103 | + 87648: : 25 ad 12 4f !crc 104 | + 72: 0: TAG 7a! 21! 36 81 d1! eb d6! 39! 04! b7 28! 3f! b1 19! 2e b2 b4 23! !crc 105 | + 87649: : f1 94 78 4b !crc 106 | + 72: 0: TAG 5f! e4 b5 6c c1 3f ce e4 49 d0! e0! 78 bc 46! 92 0f 7a! e5! !crc 107 | + 104544: : 01 6b c7 c4 !crc 108 | + 72: 0: TAG 95! 78! ca 79! ab! 32 47 8d! 1c! 81! 3d! 26 85 5e f3 02 71 3f! !crc 109 | + 99737: : f6 67 6d 48 !crc 110 | + 72: 0: TAG 4b! 6e fa 87 51 7d 92 a2! fb! 1b! 1d 62! f8! 7b! 2d! cf! c1 20 !crc 111 | + 360330: : b8 59 c0 94 !crc 112 | + 72: 0: TAG b0! 05 25! 4b! 94 8d! 75 62 70! 85 77! e7 a6 1f! 9e! 54 07! d5! !crc 113 | + 443146: : 7f 3a fa 6a !crc 114 | + 72: 0: TAG ac c9 81! b4! de ee! e5! 0b! 73! 79! 6c fe! d8 53 00! e1 3c! f0 !crc 115 | + 198008: : 47 e6 ec f7 !crc 116 | + 72: 0: TAG a6 b1! 1e! 8e! 86! ee d0 4a 4c ee 34 df 6b e6! da 45! d6! ed !crc 117 | + 455019: : 49 13 9c fb !crc 118 | + 72: 0: TAG 31! 1d 7d 21! 22! e3 af! bc ce 6e! 6c! 9f 48 c1! 16! 28! f3! 18 !crc 119 | + 223097: : ff 43 e9 35 !crc 120 | + 72: 0: TAG e5! 41 d7 99! 46 8d! ff e7! 1e! 22 32! d0 93! 9e a1 c5 5c! 32! !crc 121 | 122 | # http://www.proxmark.org/forum/topic/385/error-with-mifarecrackpy/ 123 | # real uid is: ca fd ca 13 124 | # 0xcafdca13 0xe901a169 0x71034abe 0xf92f512f 0x9925ef9d 125 | -------------------------------------------------------------------------------- /src/data/logs_proxmark3/trace3.txt: -------------------------------------------------------------------------------- 1 | +2770194: : 26 2 | + 64: 0: TAG 04 00 3 | + 1432: : 93 20 4 | + 64: 0: TAG 5e c2 1c 61 e1 5 | + 2168: : 93 70 5e c2 1c 61 e1 d5 65 6 | + 64: 0: TAG 08 b6 dd 7 | + 31064: : 60 08 bd f7 8 | + 112: 0: TAG d7 b2 ae bd 9 | + 1976: : 60 d1 57 7f aa 02 78 ea !crc 10 | + 599060: : 26 11 | + 64: 0: TAG 04 00 12 | + 1424: : 93 20 13 | + 64: 0: TAG 5e c2 1c 61 e1 14 | + 2168: : 93 70 5e c2 1c 61 e1 d5 65 15 | + 64: 0: TAG 08 b6 dd 16 | + 31160: : 60 08 bd f7 17 | + 112: 0: TAG cc ec 00 cd 18 | + 1976: : 86 ae b4 79 69 34 ed 50 !crc 19 | + 545300: : 26 20 | + 64: 0: TAG 04 00 21 | + 1440: : 93 20 22 | + 64: 0: TAG 5e c2 1c 61 e1 23 | + 2168: : 93 70 5e c2 1c 61 e1 d5 65 24 | + 64: 0: TAG 08 b6 dd 25 | + 31144: : 60 08 bd f7 26 | + 112: 0: TAG 9c 6a 3c 1e 27 | + 1976: : 33 aa 1e 4c 8a a1 58 ed !crc 28 | 29 | # http://www.proxmark.org/forum/post/2346/#p2346 30 | # 0x5ec21c61 0xd7b2aebd 0x60d1577f 0xaa0278ea 0x26 -------------------------------------------------------------------------------- /src/data/tmpls_fingerprints/mfcuk_tmpl_oyster.mfd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nfc-tools/mfcuk/b333a7925a3be80d9496c88c9fef816777827a83/src/data/tmpls_fingerprints/mfcuk_tmpl_oyster.mfd -------------------------------------------------------------------------------- /src/data/tmpls_fingerprints/mfcuk_tmpl_ratb.mfd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nfc-tools/mfcuk/b333a7925a3be80d9496c88c9fef816777827a83/src/data/tmpls_fingerprints/mfcuk_tmpl_ratb.mfd -------------------------------------------------------------------------------- /src/data/tmpls_fingerprints/mfcuk_tmpl_skgt.mfd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nfc-tools/mfcuk/b333a7925a3be80d9496c88c9fef816777827a83/src/data/tmpls_fingerprints/mfcuk_tmpl_skgt.mfd -------------------------------------------------------------------------------- /src/mfcuk.h: -------------------------------------------------------------------------------- 1 | /* 2 | Package: 3 | MiFare Classic Universal toolKit (MFCUK) 4 | 5 | Filename: 6 | mfcuk_keyrecovery_darkside.h 7 | 8 | Description: 9 | MFCUK DarkSide Key Recovery specific typedefs and defines 10 | 11 | Contact, bug-reports: 12 | http://andreicostin.com/ 13 | mailto:zveriu@gmail.com 14 | 15 | License: 16 | GPL2 (see below), Copyright (C) 2009, Andrei Costin 17 | 18 | * @file mfcuk_keyrecovery_darkside.h 19 | * @brief 20 | */ 21 | 22 | /* 23 | VERSION HISTORY 24 | -------------------------------------------------------------------------------- 25 | | Number : 0.1 26 | | dd/mm/yyyy : 23/11/2009 27 | | Author : zveriu@gmail.com, http://andreicostin.com 28 | | Description: Moved bulk of defines and things from "mfcuk_keyrecovery_darkside.c" 29 | -------------------------------------------------------------------------------- 30 | */ 31 | 32 | /* 33 | LICENSE 34 | 35 | This program is free software: you can redistribute it and/or modify 36 | it under the terms of the GNU General Public License as published by 37 | the Free Software Foundation, either version 2 of the License, or 38 | (at your option) any later version. 39 | 40 | This program is distributed in the hope that it will be useful, 41 | but WITHOUT ANY WARRANTY; without even the implied warranty of 42 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 43 | GNU General Public License for more details. 44 | 45 | You should have received a copy of the GNU General Public License 46 | along with this program. If not, see . 47 | */ 48 | 49 | #ifndef _MFCUK_KEYRECOVERY_DARKSIDE_H_ 50 | #define _MFCUK_KEYRECOVERY_DARKSIDE_H_ 51 | 52 | // Define package and executable related info 53 | #define BUILD_NAME "Mifare Classic DarkSide Key Recovery Tool" 54 | #define BUILD_VERSION "0.3" 55 | #define BUILD_AUTHOR "Andrei Costin, zveriu@gmail.com, http://andreicostin.com" 56 | 57 | // Define return statuses 58 | #define MFCUK_SUCCESS 0x0 59 | #define MFCUK_OK_KEY_RECOVERED (MFCUK_SUCCESS+1) 60 | #define MFCUK_FAIL_AUTH (MFCUK_OK_KEY_RECOVERED+1) 61 | #define MFCUK_FAIL_CRAPTO (MFCUK_FAIL_AUTH+1) 62 | #define MFCUK_FAIL_TAGTYPE_INVALID (MFCUK_FAIL_CRAPTO+1) 63 | #define MFCUK_FAIL_KEYTYPE_INVALID (MFCUK_FAIL_TAGTYPE_INVALID+1) 64 | #define MFCUK_FAIL_BLOCK_INVALID (MFCUK_FAIL_KEYTYPE_INVALID+1) 65 | #define MFCUK_FAIL_SECTOR_INVALID (MFCUK_FAIL_BLOCK_INVALID+1) 66 | #define MFCUK_FAIL_COMM (MFCUK_FAIL_SECTOR_INVALID+1) 67 | #define MFCUK_FAIL_MEMORY (MFCUK_FAIL_COMM+1) 68 | 69 | // There are 4 bytes in ACBITS, use each byte as below 70 | #define ACTIONS_KEY_A 0 // Specifies the byte index where actions for key A are stored 71 | #define RESULTS_KEY_A 1 // Specifies the byte index where results for key A are stored 72 | #define ACTIONS_KEY_B 2 // Specifies the byte index where actions for key B are stored 73 | #define RESULTS_KEY_B 3 // Specifies the byte index where results for key B are stored 74 | 75 | // The action/result byte can contain any combination of these 76 | #define ACTIONS_VERIFY 0x1 // Specifies whether the key should be first verified 77 | #define ACTIONS_RECOVER 0x2 // Specifies whether the key should be recovered. If a key has verify action and the key was verified, RESULTS_ byte will indicate that and recovery will not take place 78 | #define ACTIONS_KEYSET 0x4 // Specifies whether the key was set from command line rather that should be loaded from the eventual -i/-I dump 79 | 80 | // Implementation specific, since we are not 100% sure we can fix the tag nonce 81 | // Suppose from 2^32, only MAX 2^16 tag nonces will appear given current SLEEP_ values 82 | #define MAX_TAG_NONCES 65536 83 | // Maximum possible states allocated and returned by lsfr_common_prefix(). Used this value in the looping 84 | #define MAX_COMMON_PREFIX_STATES (1<<20) 85 | // 10 ms, though {WPMCC09} claims 30 us is enough 86 | #define SLEEP_AT_FIELD_OFF 10 87 | // 50 ms, seems pretty good constant, though if you don't like it - make it even 3.1415..., we don't care 88 | #define SLEEP_AFTER_FIELD_ON 50 89 | // Since the 29 bits of {Nr} are constant, darkside varies only "last" (0xFFFFFF1F) 3 bits, thus we have 8 possible parity bits arrays 90 | #define MFCUK_DARKSIDE_MAX_LEVELS 8 91 | 92 | #define MFCUK_DARKSIDE_START_NR 0xDEADBEEF 93 | #define MFCUK_DARKSIDE_START_AR 0xFACECAFE 94 | 95 | typedef struct tag_nonce_entry { 96 | uint32_t tagNonce; // Tag nonce we target for fixation 97 | uint8_t spoofFlag; // No spoofing until we have a successful auth with this tagNonce. Once we have, we want to spoof to get the encrypted 0x5 value 98 | uint32_t num_of_appearances; // For statistics, how many times this tag nonce appeared for the given SLEEP_ values 99 | 100 | // STAGE1 data for "dark side" and lsfr_common_prefix() 101 | uint32_t spoofNrPfx; // PARAM: used as pfx, calculated from (spoofNrEnc & 0xFFFFFF1F). BUG: weird way to denote "first 29 prefix bits" in "dark side" paper. Perhaps I see the world different 102 | uint32_t spoofNrEnc; // {Nr} value which we will be using to make the tag respond with 4 bits 103 | uint32_t spoofArEnc; // PARAM: used as rr 104 | uint8_t spoofParBitsEnc; // parity bits we are trying to guess for the first time 105 | uint8_t spoofNackEnc; // store here the encrypted NACK returned first time we match the parity bits 106 | uint8_t spoofKs; // store here the keystream ks used for encryptying spoofNackEnc, specifically spoofKs = spoofNackEnc ^ 0x5 107 | 108 | // STAGE2 data for "dark side" and lsfr_common_prefix() 109 | int current_out_of_8; // starting from -1 until we find parity for chosen spoofNrEnc,spoofArEnc 110 | uint8_t parBitsCrntCombination[MFCUK_DARKSIDE_MAX_LEVELS]; // Loops over 32 combinations of the last 5 parity bits which generated the 4 bit NACK in STAGE1 111 | uint32_t nrEnc[MFCUK_DARKSIDE_MAX_LEVELS]; // the 29 bits constant prefix, varying only 3 bits, thus 8 possible values 112 | uint32_t arEnc[MFCUK_DARKSIDE_MAX_LEVELS]; // the same reader response as spoofArEnc; redundant but... :) 113 | uint8_t ks[MFCUK_DARKSIDE_MAX_LEVELS]; // PARAM: used as ks, obtained as (ks[i] = nackEnc[i] ^ 0x5) 114 | uint8_t nackEnc[MFCUK_DARKSIDE_MAX_LEVELS]; // store here the encrypted 4 bits values which tag responded 115 | uint8_t parBits[MFCUK_DARKSIDE_MAX_LEVELS]; // store here the values based on spoofParBitsEnc, varying only last 5 bits 116 | uint8_t parBitsArr[MFCUK_DARKSIDE_MAX_LEVELS][8]; // PARAM: used as par, contains value of parBits byte-bit values just splitted out one bit per byte thus second pair of braces [8] 117 | } tag_nonce_entry_t; 118 | 119 | #endif // _MFCUK_KEYRECOVERY_DARKSIDE_H_ 120 | -------------------------------------------------------------------------------- /src/mfcuk_finger.c: -------------------------------------------------------------------------------- 1 | /* 2 | LICENSE 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | /* 19 | Package: 20 | MiFare Classic Universal toolKit (MFCUK) 21 | 22 | Package version: 23 | 0.1 24 | 25 | Filename: 26 | mfcuk_finger.c 27 | 28 | Description: 29 | MFCUK fingerprinting and specific data-decoding functionality. 30 | 31 | License: 32 | GPL2, Copyright (C) 2009, Andrei Costin 33 | 34 | * @file mfcuk_finger.c 35 | * @brief MFCUK fingerprinting and specific data-decoding functionality. 36 | * @todo add proper error codes 37 | */ 38 | 39 | #include "mfcuk_finger.h" 40 | 41 | mfcuk_finger_tmpl_entry mfcuk_finger_db[] = { 42 | { "./data/tmpls_fingerprints/mfcuk_tmpl_skgt.mfd", "Sofia SKGT", mfcuk_finger_default_comparator, mfcuk_finger_skgt_decoder, NULL }, 43 | { "./data/tmpls_fingerprints/mfcuk_tmpl_ratb.mfd", "Bucharest RATB", mfcuk_finger_default_comparator, mfcuk_finger_default_decoder, NULL }, 44 | { "./data/tmpls_fingerprints/mfcuk_tmpl_oyster.mfd", "London OYSTER", mfcuk_finger_default_comparator, mfcuk_finger_default_decoder, NULL }, 45 | }; 46 | 47 | int mfcuk_finger_db_entries = sizeof(mfcuk_finger_db) / sizeof(mfcuk_finger_db[0]); 48 | 49 | int mfcuk_finger_default_decoder(mifare_classic_tag *dump) 50 | { 51 | if (!dump) { 52 | fprintf(stderr, "ERROR: cannot decode a NULL pointer :)\n"); 53 | return 0; 54 | } 55 | 56 | printf("UID:\t%02x%02x%02x%02x\n", dump->amb[0].mbm.abtUID[0], dump->amb[0].mbm.abtUID[1], dump->amb[0].mbm.abtUID[2], dump->amb[0].mbm.abtUID[3]); 57 | printf("TYPE:\t%02x\n", dump->amb[0].mbm.btUnknown); 58 | 59 | return 1; 60 | } 61 | 62 | // Yes, I know C++ class inheritance would perfectly fit the decoders/comparators... Though C is more to my heart. Anyone to rewrite in C++? 63 | int mfcuk_finger_skgt_decoder(mifare_classic_tag *dump) 64 | { 65 | if (!dump) { 66 | fprintf(stderr, "ERROR: cannot decode a NULL pointer :)\n"); 67 | return 0; 68 | } 69 | 70 | printf("Bulgaria/Sofia/SKGT public transport card information decoder (info credits to Andy)\n"); 71 | mfcuk_finger_default_decoder(dump); 72 | 73 | printf("LAST TRAVEL DATA\n"); 74 | 75 | // TODO: get proper information 76 | 77 | return 1; 78 | } 79 | 80 | int mfcuk_finger_default_comparator(mifare_classic_tag *dump, mfcuk_finger_template *tmpl, float *score) 81 | { 82 | int max_bytes = 0; 83 | int i; 84 | int num_bytes_tomatch = 0; 85 | int num_bytes_matched = 0; 86 | 87 | if ((!dump) || (!tmpl) || (!score)) { 88 | return 0; 89 | } 90 | 91 | if (IS_MIFARE_CLASSIC_1K_TAG(dump)) { 92 | max_bytes = MIFARE_CLASSIC_BYTES_PER_BLOCK * MIFARE_CLASSIC_1K_MAX_BLOCKS; 93 | } else if (IS_MIFARE_CLASSIC_4K_TAG(dump)) { 94 | max_bytes = MIFARE_CLASSIC_BYTES_PER_BLOCK * MIFARE_CLASSIC_4K_MAX_BLOCKS; 95 | } else { 96 | return 0; 97 | } 98 | 99 | for (i = 0; i < max_bytes; i++) { 100 | if (((char *)(&tmpl->mask))[i] == 0x0) { 101 | continue; 102 | } 103 | 104 | num_bytes_tomatch++; 105 | 106 | if (((char *)(&tmpl->values))[i] == ((char *)dump)[i]) { 107 | num_bytes_matched++; 108 | } 109 | } 110 | 111 | if (num_bytes_tomatch == 0) { 112 | return 0; 113 | } else { 114 | *score = (float)(num_bytes_matched) / num_bytes_tomatch; 115 | } 116 | 117 | return 1; 118 | } 119 | 120 | int mfcuk_finger_load(void) 121 | { 122 | int i; 123 | mifare_classic_tag mask; 124 | mifare_classic_tag values; 125 | FILE *fp = NULL; 126 | size_t result = 0; 127 | mfcuk_finger_template *tmpl_new = NULL; 128 | 129 | int template_loaded_count = 0; 130 | for (i = 0; i < mfcuk_finger_db_entries; i++) { 131 | fp = fopen(mfcuk_finger_db[i].tmpl_filename, "rb"); 132 | 133 | if (!fp) { 134 | fprintf(stderr, "WARN: cannot open template file '%s'\n", mfcuk_finger_db[i].tmpl_filename); 135 | continue; 136 | } 137 | 138 | // If not read exactly 1 record, something is wrong 139 | if ((result = fread((void *)(&mask), sizeof(mask), 1, fp)) != 1) { 140 | fprintf(stderr, "WARN: cannot read MASK from template file '%s'\n", mfcuk_finger_db[i].tmpl_filename); 141 | fclose(fp); 142 | continue; 143 | } 144 | 145 | // If not read exactly 1 record, something is wrong 146 | if ((result = fread((void *)(&values), sizeof(values), 1, fp)) != 1) { 147 | fprintf(stderr, "WARN: cannot read VALUES template file '%s'\n", mfcuk_finger_db[i].tmpl_filename); 148 | fclose(fp); 149 | continue; 150 | } 151 | 152 | if (mfcuk_finger_db[i].tmpl_data == NULL) { 153 | if ((tmpl_new = (mfcuk_finger_template *) malloc(sizeof(mfcuk_finger_template))) == NULL) { 154 | fprintf(stderr, "WARN: cannot allocate memory to template record %d\n", i); 155 | fclose(fp); 156 | continue; 157 | } 158 | 159 | memcpy(&(tmpl_new->mask), &(mask), sizeof(mask)); 160 | memcpy(&(tmpl_new->values), &(values), sizeof(values)); 161 | 162 | mfcuk_finger_db[i].tmpl_data = tmpl_new; 163 | template_loaded_count++; 164 | } 165 | 166 | if (fp) { 167 | fclose(fp); 168 | fp = NULL; 169 | } 170 | } 171 | 172 | return template_loaded_count; 173 | } 174 | 175 | int mfcuk_finger_unload(void) 176 | { 177 | int i; 178 | 179 | for (i = 0; i < mfcuk_finger_db_entries; i++) { 180 | if (mfcuk_finger_db[i].tmpl_data != NULL) { 181 | free(mfcuk_finger_db[i].tmpl_data); 182 | mfcuk_finger_db[i].tmpl_data = NULL; 183 | } 184 | } 185 | 186 | return 1; 187 | } 188 | -------------------------------------------------------------------------------- /src/mfcuk_finger.h: -------------------------------------------------------------------------------- 1 | /* 2 | LICENSE 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | /* 19 | Package: 20 | MiFare Classic Universal toolKit (MFCUK) 21 | 22 | Package version: 23 | 0.1 24 | 25 | Filename: 26 | mfcuk_finger.h 27 | 28 | Description: 29 | MFCUK fingerprinting and specific data-decoding functionality. 30 | 31 | License: 32 | GPL2, Copyright (C) 2009, Andrei Costin 33 | 34 | * @file mfcuk_finger.h 35 | * @brief MFCUK fingerprinting and specific data-decoding functionality. 36 | */ 37 | 38 | #ifndef _MFCUK_FINGER_H_ 39 | #define _MFCUK_FINGER_H_ 40 | 41 | #include 42 | #include 43 | #include 44 | 45 | #include "mfcuk_mifare.h" 46 | 47 | // Wrapping an ugly template into an externally pleasant name. To implement proper template later. 48 | typedef struct _mfcuk_finger_template_ { 49 | mifare_classic_tag mask; 50 | mifare_classic_tag values; 51 | } mfcuk_finger_template; 52 | 53 | // Function type definition, to be used for custom decoders/comparators 54 | typedef int (*mfcuk_finger_comparator)(mifare_classic_tag *dump, mfcuk_finger_template *tmpl, float *score); 55 | typedef int (*mfcuk_finger_decoder)(mifare_classic_tag *dump); 56 | 57 | // Naive implementation of a self-contained fingerprint database entry 58 | typedef struct _mfcuk_finger_tmpl_entry_ { 59 | const char *tmpl_filename; 60 | const char *tmpl_name; 61 | mfcuk_finger_comparator tmpl_comparison_func; 62 | mfcuk_finger_decoder tmpl_decoder_func; 63 | mfcuk_finger_template *tmpl_data; 64 | } mfcuk_finger_tmpl_entry; 65 | 66 | int mfcuk_finger_default_comparator(mifare_classic_tag *dump, mfcuk_finger_template *tmpl, float *score); 67 | int mfcuk_finger_default_decoder(mifare_classic_tag *dump); 68 | int mfcuk_finger_skgt_decoder(mifare_classic_tag *dump); 69 | 70 | // "Housekeeping" functions 71 | int mfcuk_finger_load(void); 72 | int mfcuk_finger_unload(void); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/mfcuk_mifare.c: -------------------------------------------------------------------------------- 1 | /* 2 | Package: 3 | MiFare Classic Universal toolKit (MFCUK) 4 | 5 | Package version: 6 | 0.1 7 | 8 | Filename: 9 | mfcuk_mifare.c 10 | 11 | Description: 12 | MFCUK defines and function implementation file extending 13 | mainly libnfc's "mifare.h" interface/functionality. 14 | 15 | Contact, bug-reports: 16 | http://andreicostin.com/ 17 | mailto:zveriu@gmail.com 18 | 19 | License: 20 | GPL2 (see below), Copyright (C) 2009, Andrei Costin 21 | 22 | * @file mfcuk_mifare.c 23 | * @brief 24 | */ 25 | 26 | /* 27 | VERSION HISTORY 28 | -------------------------------------------------------------------------------- 29 | | Number : 0.1 30 | | dd/mm/yyyy : 23/11/2009 31 | | Author : zveriu@gmail.com, http://andreicostin.com 32 | | Description: Moved bulk of defines and functions from "mfcuk_keyrecovery_darkside.c" 33 | -------------------------------------------------------------------------------- 34 | */ 35 | 36 | /* 37 | LICENSE 38 | 39 | This program is free software: you can redistribute it and/or modify 40 | it under the terms of the GNU General Public License as published by 41 | the Free Software Foundation, either version 2 of the License, or 42 | (at your option) any later version. 43 | 44 | This program is distributed in the hope that it will be useful, 45 | but WITHOUT ANY WARRANTY; without even the implied warranty of 46 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 47 | GNU General Public License for more details. 48 | 49 | You should have received a copy of the GNU General Public License 50 | along with this program. If not, see . 51 | */ 52 | 53 | #include "mfcuk_mifare.h" 54 | 55 | // Default keys used as a *BIG* mistake in many applications - especially System Integrators should pay attention! 56 | uint8_t mfcuk_default_keys[][MIFARE_CLASSIC_KEY_BYTELENGTH] = { 57 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Place-holder for current key to verify 58 | {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 59 | {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}, 60 | {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5}, 61 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 62 | {0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd}, 63 | {0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a}, 64 | {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}, 65 | {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, 66 | }; 67 | 68 | int mfcuk_default_keys_num = sizeof(mfcuk_default_keys) / sizeof(mfcuk_default_keys[0]); 69 | 70 | bool is_valid_block(uint8_t bTagType, uint32_t uiBlock) 71 | { 72 | if (IS_MIFARE_CLASSIC_1K(bTagType) && (uiBlock < MIFARE_CLASSIC_1K_MAX_BLOCKS)) { 73 | return true; 74 | } 75 | 76 | if (IS_MIFARE_CLASSIC_4K(bTagType) && (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS)) { 77 | return true; 78 | } 79 | 80 | return false; 81 | } 82 | 83 | bool is_valid_sector(uint8_t bTagType, uint32_t uiSector) 84 | { 85 | if (IS_MIFARE_CLASSIC_1K(bTagType) && (uiSector < MIFARE_CLASSIC_1K_MAX_SECTORS)) { 86 | return true; 87 | } 88 | 89 | if (IS_MIFARE_CLASSIC_4K(bTagType) && (uiSector < MIFARE_CLASSIC_4K_MAX_SECTORS)) { 90 | return true; 91 | } 92 | 93 | return false; 94 | } 95 | 96 | bool is_first_block(uint8_t bTagType, uint32_t uiBlock) 97 | { 98 | if (!is_valid_block(bTagType, uiBlock)) { 99 | return false; 100 | } 101 | 102 | // Test if we are in the small or big sectors 103 | if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) { 104 | // For Mifare Classic 1K, it will enter always here 105 | return ((uiBlock) % (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) == 0); 106 | } else { 107 | // This branch will enter only for Mifare Classic 4K big sectors 108 | return ((uiBlock) % (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) == 0); 109 | } 110 | 111 | // Should not reach here, but... never know 112 | return false; 113 | } 114 | 115 | bool is_trailer_block(uint8_t bTagType, uint32_t uiBlock) 116 | { 117 | if (!is_valid_block(bTagType, uiBlock)) { 118 | return false; 119 | } 120 | 121 | // Test if we are in the small or big sectors 122 | if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) { 123 | // For Mifare Classic 1K, it will enter always here 124 | return ((uiBlock + 1) % (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) == 0); 125 | } else { 126 | // This branch will enter only for Mifare Classic 4K big sectors 127 | return ((uiBlock + 1) % (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) == 0); 128 | } 129 | 130 | // Should not reach here, but... never know 131 | return false; 132 | } 133 | 134 | uint32_t get_first_block(uint8_t bTagType, uint32_t uiBlock) 135 | { 136 | if (!is_valid_block(bTagType, uiBlock)) { 137 | return MIFARE_CLASSIC_INVALID_BLOCK; 138 | } 139 | 140 | // Test if we are in the small or big sectors 141 | if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) { 142 | // Integer divide, then integer multiply 143 | return (uiBlock / MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1; 144 | } else { 145 | uint32_t tmp = uiBlock - MIFARE_CLASSIC_4K_MAX_BLOCKS1; 146 | return MIFARE_CLASSIC_4K_MAX_BLOCKS1 + (tmp / MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2; 147 | } 148 | 149 | // Should not reach here, but... never know 150 | return MIFARE_CLASSIC_INVALID_BLOCK; 151 | } 152 | 153 | uint32_t get_trailer_block(uint8_t bTagType, uint32_t uiBlock) 154 | { 155 | if (!is_valid_block(bTagType, uiBlock)) { 156 | return MIFARE_CLASSIC_INVALID_BLOCK; 157 | } 158 | 159 | // Test if we are in the small or big sectors 160 | if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) { 161 | // Integer divide, then integer multiply 162 | return (uiBlock / MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1 + (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1 - 1); 163 | } else { 164 | uint32_t tmp = uiBlock - MIFARE_CLASSIC_4K_MAX_BLOCKS1; 165 | return MIFARE_CLASSIC_4K_MAX_BLOCKS1 + (tmp / MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2 + (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2 - 1); 166 | } 167 | 168 | // Should not reach here, but... never know 169 | return MIFARE_CLASSIC_INVALID_BLOCK; 170 | } 171 | 172 | bool is_big_sector(uint8_t bTagType, uint32_t uiSector) 173 | { 174 | if (!is_valid_sector(bTagType, uiSector)) { 175 | return false; 176 | } 177 | 178 | if (uiSector >= MIFARE_CLASSIC_4K_MAX_SECTORS1) { 179 | return true; 180 | } 181 | 182 | return false; 183 | } 184 | 185 | uint32_t get_first_block_for_sector(uint8_t bTagType, uint32_t uiSector) 186 | { 187 | if (!is_valid_sector(bTagType, uiSector)) { 188 | return MIFARE_CLASSIC_INVALID_BLOCK; 189 | } 190 | 191 | if (uiSector < MIFARE_CLASSIC_4K_MAX_SECTORS1) { 192 | // For Mifare Classic 1K, it will enter always here 193 | return (uiSector * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1); 194 | } else { 195 | // For Mifare Classic 4K big sectors it will enter always here 196 | uint32_t tmp = uiSector - MIFARE_CLASSIC_4K_MAX_SECTORS1; 197 | return MIFARE_CLASSIC_4K_MAX_BLOCKS1 + (tmp * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2); 198 | } 199 | 200 | // Should not reach here, but... never know 201 | return MIFARE_CLASSIC_INVALID_BLOCK; 202 | } 203 | 204 | uint32_t get_trailer_block_for_sector(uint8_t bTagType, uint32_t uiSector) 205 | { 206 | if (!is_valid_sector(bTagType, uiSector)) { 207 | return MIFARE_CLASSIC_INVALID_BLOCK; 208 | } 209 | 210 | if (uiSector < MIFARE_CLASSIC_4K_MAX_SECTORS1) { 211 | // For Mifare Classic 1K, it will enter always here 212 | return (uiSector * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) + (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1 - 1); 213 | } else { 214 | // For Mifare Classic 4K big sectors it will enter always here 215 | uint32_t tmp = uiSector - MIFARE_CLASSIC_4K_MAX_SECTORS1; 216 | return MIFARE_CLASSIC_4K_MAX_BLOCKS1 + (tmp * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) + (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2 - 1); 217 | } 218 | 219 | // Should not reach here, but... never know 220 | return MIFARE_CLASSIC_INVALID_BLOCK; 221 | } 222 | 223 | uint32_t get_sector_for_block(uint8_t bTagType, uint32_t uiBlock) 224 | { 225 | if (!is_valid_block(bTagType, uiBlock)) { 226 | return MIFARE_CLASSIC_INVALID_BLOCK; 227 | } 228 | 229 | // Test if we are in the small or big sectors 230 | if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) { 231 | // For Mifare Classic 1K, it will enter always here 232 | return (uiBlock / MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1); 233 | } else { 234 | uint32_t tmp = uiBlock - MIFARE_CLASSIC_4K_MAX_BLOCKS1; 235 | return MIFARE_CLASSIC_4K_MAX_SECTORS1 + (tmp / MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2); 236 | } 237 | 238 | // Should not reach here, but... never know 239 | return MIFARE_CLASSIC_INVALID_BLOCK; 240 | } 241 | 242 | // Test case function for checking correct functionality of the block/sector is_ ang get_ functions 243 | void test_mifare_classic_blocks_sectors_functions(uint8_t bTagType) 244 | { 245 | uint32_t i; 246 | uint32_t max_blocks, max_sectors; 247 | 248 | if (IS_MIFARE_CLASSIC_1K(bTagType)) { 249 | printf("\nMIFARE CLASSIC 1K\n"); 250 | max_blocks = MIFARE_CLASSIC_1K_MAX_BLOCKS; 251 | max_sectors = MIFARE_CLASSIC_1K_MAX_SECTORS; 252 | } else if (IS_MIFARE_CLASSIC_4K(bTagType)) { 253 | printf("\nMIFARE CLASSIC 4K\n"); 254 | max_blocks = MIFARE_CLASSIC_4K_MAX_BLOCKS; 255 | max_sectors = MIFARE_CLASSIC_4K_MAX_SECTORS; 256 | } else { 257 | return; 258 | } 259 | 260 | // Include one invalid block, that is why we add +1 261 | for (i = 0; i < max_blocks + 1; i++) { 262 | printf("BLOCK %d\n", i); 263 | printf("\t is_valid_block: %c\n", (is_valid_block(bTagType, i) ? 'Y' : 'N')); 264 | printf("\t is_first_block: %c\n", (is_first_block(bTagType, i) ? 'Y' : 'N')); 265 | printf("\t is_trailer_block: %c\n", (is_trailer_block(bTagType, i) ? 'Y' : 'N')); 266 | printf("\t get_first_block: %d\n", get_first_block(bTagType, i)); 267 | printf("\t get_trailer_block: %d\n", get_trailer_block(bTagType, i)); 268 | printf("\t get_sector_for_block: %d\n", get_sector_for_block(bTagType, i)); 269 | } 270 | 271 | // Include one invalid sector, that is why we add +1 272 | for (i = 0; i < max_sectors + 1; i++) { 273 | printf("SECTOR %d\n", i); 274 | printf("\t is_valid_sector: %c\n", (is_valid_sector(bTagType, i) ? 'Y' : 'N')); 275 | printf("\t is_big_sector: %c\n", (is_big_sector(bTagType, i) ? 'Y' : 'N')); 276 | printf("\t get_first_block_for_sector: %d\n", get_first_block_for_sector(bTagType, i)); 277 | printf("\t get_trailer_block_for_sector: %d\n", get_trailer_block_for_sector(bTagType, i)); 278 | } 279 | 280 | } 281 | 282 | bool mfcuk_save_tag_dump(const char *filename, mifare_classic_tag *tag) 283 | { 284 | FILE *fp; 285 | size_t result; 286 | 287 | fp = fopen(filename, "wb"); 288 | if (!fp) { 289 | return false; 290 | } 291 | 292 | // Expect to write 1 record 293 | result = fwrite((void *) tag, sizeof(*tag), 1, fp); 294 | 295 | // If not written exactly 1 record, something is wrong 296 | if (result != 1) { 297 | fclose(fp); 298 | return false; 299 | } 300 | 301 | fclose(fp); 302 | return true; 303 | } 304 | 305 | bool mfcuk_save_tag_dump_ext(const char *filename, mifare_classic_tag_ext *tag_ext) 306 | { 307 | FILE *fp; 308 | size_t result; 309 | 310 | fp = fopen(filename, "wb"); 311 | if (!fp) { 312 | return false; 313 | } 314 | 315 | // Expect to write 1 record 316 | result = fwrite((void *) tag_ext, sizeof(*tag_ext), 1, fp); 317 | 318 | // If not written exactly 1 record, something is wrong 319 | if (result != 1) { 320 | fclose(fp); 321 | return false; 322 | } 323 | 324 | fclose(fp); 325 | return true; 326 | } 327 | 328 | bool mfcuk_load_tag_dump(const char *filename, mifare_classic_tag *tag) 329 | { 330 | FILE *fp; 331 | size_t result; 332 | 333 | fp = fopen(filename, "rb"); 334 | if (!fp) { 335 | return false; 336 | } 337 | 338 | // Expect to read 1 record 339 | result = fread((void *) tag, sizeof(*tag), 1, fp); 340 | 341 | // If not read exactly 1 record, something is wrong 342 | if (result != 1) { 343 | fclose(fp); 344 | return false; 345 | } 346 | 347 | fclose(fp); 348 | return true; 349 | } 350 | 351 | bool mfcuk_load_tag_dump_ext(const char *filename, mifare_classic_tag_ext *tag_ext) 352 | { 353 | FILE *fp; 354 | size_t result; 355 | 356 | fp = fopen(filename, "rb"); 357 | if (!fp) { 358 | return false; 359 | } 360 | 361 | // Expect to read 1 record 362 | result = fread((void *) tag_ext, sizeof(*tag_ext), 1, fp); 363 | 364 | // If not read exactly 1 record, something is wrong 365 | if (result != sizeof(*tag_ext)) { 366 | fclose(fp); 367 | return false; 368 | } 369 | 370 | fclose(fp); 371 | return true; 372 | } 373 | 374 | void print_mifare_classic_tag_keys(const char *title, mifare_classic_tag *tag) 375 | { 376 | uint32_t i, max_blocks, trailer_block; 377 | uint8_t bTagType; 378 | mifare_classic_block_trailer *ptr_trailer = NULL; 379 | 380 | if (!tag) { 381 | return; 382 | } 383 | 384 | bTagType = tag->amb->mbm.btUnknown; 385 | 386 | if (!IS_MIFARE_CLASSIC_1K(bTagType) && !IS_MIFARE_CLASSIC_4K(bTagType)) { 387 | return; 388 | } 389 | 390 | printf("%s - UID %02x %02x %02x %02x - TYPE 0x%02x (%s)\n", 391 | title, tag->amb->mbm.abtUID[0], tag->amb->mbm.abtUID[1], tag->amb->mbm.abtUID[2], tag->amb->mbm.abtUID[3], bTagType, 392 | (IS_MIFARE_CLASSIC_1K(bTagType) ? (MIFARE_CLASSIC_1K_NAME) : (IS_MIFARE_CLASSIC_4K(bTagType) ? (MIFARE_CLASSIC_4K_NAME) : (MIFARE_CLASSIC_UNKN_NAME))) 393 | ); 394 | printf("-------------------------------------------------------\n"); 395 | printf("Sector\t| Key A\t| AC bits\t| Key B\n"); 396 | printf("-------------------------------------------------------\n"); 397 | 398 | if (IS_MIFARE_CLASSIC_1K(tag->amb->mbm.btUnknown)) { 399 | max_blocks = MIFARE_CLASSIC_1K_MAX_BLOCKS; 400 | } else { 401 | max_blocks = MIFARE_CLASSIC_4K_MAX_BLOCKS; 402 | } 403 | 404 | for (i = 0; i < max_blocks; i++) { 405 | trailer_block = get_trailer_block(bTagType, i); 406 | 407 | if (!is_valid_block(bTagType, trailer_block)) { 408 | break; 409 | } 410 | 411 | ptr_trailer = (mifare_classic_block_trailer *)((char *)tag + (trailer_block * MIFARE_CLASSIC_BYTES_PER_BLOCK)); 412 | 413 | printf("%d\t| %02x%02x%02x%02x%02x%02x\t| %02x%02x%02x%02x\t| %02x%02x%02x%02x%02x%02x\n", 414 | get_sector_for_block(bTagType, trailer_block), 415 | ptr_trailer->abtKeyA[0], ptr_trailer->abtKeyA[1], ptr_trailer->abtKeyA[2], 416 | ptr_trailer->abtKeyA[3], ptr_trailer->abtKeyA[4], ptr_trailer->abtKeyA[5], 417 | ptr_trailer->abtAccessBits[0], ptr_trailer->abtAccessBits[1], ptr_trailer->abtAccessBits[2], ptr_trailer->abtAccessBits[3], 418 | ptr_trailer->abtKeyB[0], ptr_trailer->abtKeyB[1], ptr_trailer->abtKeyB[2], 419 | ptr_trailer->abtKeyB[3], ptr_trailer->abtKeyB[4], ptr_trailer->abtKeyB[5] 420 | ); 421 | 422 | // Go beyond current trailer block, i.e. go to next sector 423 | i = trailer_block; 424 | } 425 | 426 | printf("\n"); 427 | 428 | return; 429 | } 430 | 431 | bool mfcuk_key_uint64_to_arr(const uint64_t *ui64Key, uint8_t *arr6Key) 432 | { 433 | int i; 434 | 435 | if (!ui64Key || !arr6Key) { 436 | return false; 437 | } 438 | 439 | for (i = 0; i < MIFARE_CLASSIC_KEY_BYTELENGTH; i++) { 440 | arr6Key[i] = (uint8_t)(((*ui64Key) >> 8 * (MIFARE_CLASSIC_KEY_BYTELENGTH - i - 1)) & 0xFF); 441 | } 442 | 443 | return true; 444 | } 445 | 446 | bool mfcuk_key_arr_to_uint64(const uint8_t *arr6Key, uint64_t *ui64Key) 447 | { 448 | uint64_t key = 0; 449 | int i; 450 | 451 | if (!ui64Key || !arr6Key) { 452 | return false; 453 | } 454 | 455 | for (i = 0; i < MIFARE_CLASSIC_KEY_BYTELENGTH; i++, key <<= 8) { 456 | key |= arr6Key[i]; 457 | } 458 | key >>= 8; 459 | 460 | *ui64Key = key; 461 | 462 | return true; 463 | } 464 | -------------------------------------------------------------------------------- /src/mfcuk_mifare.h: -------------------------------------------------------------------------------- 1 | /* 2 | Package: 3 | MiFare Classic Universal toolKit (MFCUK) 4 | 5 | Package version: 6 | 0.1 7 | 8 | Filename: 9 | mfcuk_mifare.h 10 | 11 | Description: 12 | MFCUK defines and function prototypes header file extending 13 | mainly libnfc's "mifare.h" interface/functionality. 14 | 15 | Contact, bug-reports: 16 | http://andreicostin.com/ 17 | mailto:zveriu@gmail.com 18 | 19 | License: 20 | GPL2 (see below), Copyright (C) 2009, Andrei Costin 21 | 22 | * @file mfcuk_mifare.h 23 | * @brief 24 | */ 25 | 26 | /* 27 | VERSION HISTORY 28 | -------------------------------------------------------------------------------- 29 | | Number : 0.1 30 | | dd/mm/yyyy : 23/11/2009 31 | | Author : zveriu@gmail.com, http://andreicostin.com 32 | | Description: Moved bulk of defines and functions from "mfcuk_keyrecovery_darkside.c" 33 | -------------------------------------------------------------------------------- 34 | */ 35 | 36 | /* 37 | LICENSE 38 | 39 | This program is free software: you can redistribute it and/or modify 40 | it under the terms of the GNU General Public License as published by 41 | the Free Software Foundation, either version 2 of the License, or 42 | (at your option) any later version. 43 | 44 | This program is distributed in the hope that it will be useful, 45 | but WITHOUT ANY WARRANTY; without even the implied warranty of 46 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 47 | GNU General Public License for more details. 48 | 49 | You should have received a copy of the GNU General Public License 50 | along with this program. If not, see . 51 | */ 52 | 53 | #ifndef _MFCUK_MIFARE_H_ 54 | #define _MFCUK_MIFARE_H_ 55 | 56 | #include 57 | #include 58 | 59 | #include 60 | #include "mifare.h" 61 | 62 | #define MIFARE_CLASSIC_UID_BYTELENGTH 4 // Length of a Mifare Classic UID in bytes 63 | #define MIFARE_CLASSIC_KEY_BYTELENGTH 6 // Length of a Mifare Classic key in bytes 64 | #define MIFARE_CLASSIC_1K_NAME "MC1K" 65 | #define MIFARE_CLASSIC_4K_NAME "MC4K" 66 | #define MIFARE_CLASSIC_UNKN_NAME "UNKN" 67 | #define MIFARE_CLASSIC_1K 0x08 // MF1ICS50 Functional Specifications - 0x08 68 | #define MIFARE_CLASSIC_4K 0x18 // MF1ICS70 Functional Specifications - 0x18 69 | #define MIFARE_DESFIRE 0x20 // XXXXXXXX Functional Specifications - 0x20 70 | #define MIFARE_CLASSIC_1K_RATB 0x88 // Infineon Licensed Mifare 1K = 0x88 (thanks JPS) 71 | #define MIFARE_CLASSIC_4K_SKGT 0x98 // Infineon Licensed Mifare 4K = 0x98??? 72 | 73 | #define IS_MIFARE_CLASSIC_1K(ats_sak) ( ((ats_sak) == MIFARE_CLASSIC_1K) || ((ats_sak) == MIFARE_CLASSIC_1K_RATB) ) 74 | #define IS_MIFARE_CLASSIC_4K(ats_sak) ( ((ats_sak) == MIFARE_CLASSIC_4K) || ((ats_sak) == MIFARE_CLASSIC_4K_SKGT) ) 75 | #define IS_MIFARE_DESFIRE(ats_sak) ( ((ats_sak) == MIFARE_DESFIRE) ) 76 | 77 | #define IS_MIFARE_CLASSIC_1K_TAG(tag) IS_MIFARE_CLASSIC_1K(tag->amb[0].mbm.btUnknown) 78 | #define IS_MIFARE_CLASSIC_4K_TAG(tag) IS_MIFARE_CLASSIC_4K(tag->amb[0].mbm.btUnknown) 79 | #define IS_MIFARE_DESFIRE_TAG(tag) IS_MIFARE_DESFIRE(tag->amb[0].mbm.btUnknown) 80 | 81 | #define MIFARE_CLASSIC_BYTES_PER_BLOCK 16 // Common for Mifare Classic 1K and Mifare Classic 4K 82 | #define MIFARE_CLASSIC_INVALID_BLOCK 0xFFFFFFFF 83 | 84 | #define MIFARE_CLASSIC_1K_MAX_SECTORS 16 85 | #define MIFARE_CLASSIC_1K_BLOCKS_PER_SECTOR 4 86 | #define MIFARE_CLASSIC_1K_MAX_BLOCKS ( (MIFARE_CLASSIC_1K_MAX_SECTORS) * (MIFARE_CLASSIC_1K_BLOCKS_PER_SECTOR) ) 87 | 88 | #define MIFARE_CLASSIC_4K_MAX_SECTORS1 32 89 | #define MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1 MIFARE_CLASSIC_1K_BLOCKS_PER_SECTOR // Possibly NXP made it for Mifare 1K backward compatibility 90 | #define MIFARE_CLASSIC_4K_MAX_BLOCKS1 ( (MIFARE_CLASSIC_4K_MAX_SECTORS1) * (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) ) 91 | 92 | #define MIFARE_CLASSIC_4K_MAX_SECTORS2 8 93 | #define MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2 16 94 | #define MIFARE_CLASSIC_4K_MAX_BLOCKS2 ( (MIFARE_CLASSIC_4K_MAX_SECTORS2) * (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) ) 95 | 96 | #define MIFARE_CLASSIC_4K_MAX_SECTORS ( (MIFARE_CLASSIC_4K_MAX_SECTORS1) + (MIFARE_CLASSIC_4K_MAX_SECTORS2) ) 97 | #define MIFARE_CLASSIC_4K_MAX_BLOCKS ( (MIFARE_CLASSIC_4K_MAX_BLOCKS1) + (MIFARE_CLASSIC_4K_MAX_BLOCKS2) ) 98 | 99 | #define MFCUK_EXTENDED_DESCRIPTION_LENGTH 128 100 | 101 | // Define an extended type of dump, basically a wrapper dump around basic tag dump 102 | typedef struct { 103 | uint32_t uid; // looks redundant, but it is easier to use dmp.uid instead of dmp.amb.mbm.abtUID[0]...[3] 104 | uint8_t type; // ATS/SAK from ti.tia.btSak, example 0x08h for Mifare 1K, 0x18h for Mifare 4K 105 | char datetime[14]; // non-zero-terminated date-time of dump in format YYYYMMDDH24MISS, example 20091114231541 - 14 Nov 2009, 11:15:41 PM 106 | char description[MFCUK_EXTENDED_DESCRIPTION_LENGTH]; // a description of the tag dump, example "RATB_DUMP_BEFORE_PAY" 107 | mifare_classic_tag tag_basic; 108 | } mifare_classic_tag_ext; 109 | 110 | // Define type of keys (A or B) in NXP notation 111 | typedef enum { 112 | keyA = 0x60, 113 | keyB = 0x61, 114 | } mifare_key_type; 115 | 116 | // Default keys used as a *BIG* mistake in many applications - especially System Integrators should pay attention! 117 | extern uint8_t mfcuk_default_keys[][MIFARE_CLASSIC_KEY_BYTELENGTH]; 118 | extern int mfcuk_default_keys_num; 119 | 120 | bool is_valid_block(uint8_t bTagType, uint32_t uiBlock); 121 | bool is_valid_sector(uint8_t bTagType, uint32_t uiSector); 122 | bool is_first_block(uint8_t bTagType, uint32_t uiBlock); 123 | bool is_trailer_block(uint8_t bTagType, uint32_t uiBlock); 124 | uint32_t get_first_block(uint8_t bTagType, uint32_t uiBlock); 125 | uint32_t get_trailer_block(uint8_t bTagType, uint32_t uiBlock); 126 | bool is_big_sector(uint8_t bTagType, uint32_t uiSector); 127 | uint32_t get_first_block_for_sector(uint8_t bTagType, uint32_t uiSector); 128 | uint32_t get_trailer_block_for_sector(uint8_t bTagType, uint32_t uiSector); 129 | uint32_t get_sector_for_block(uint8_t bTagType, uint32_t uiBlock); 130 | bool is_first_sector(uint8_t bTagType, uint32_t uiSector); 131 | bool is_first_big_sector(uint8_t bTagType, uint32_t uiSector); 132 | bool is_first_small_sector(uint8_t bTagType, uint32_t uiSector); 133 | bool is_last_sector(uint8_t bTagType, uint32_t uiSector); 134 | bool is_last_big_sector(uint8_t bTagType, uint32_t uiSector); 135 | bool is_last_small_sector(uint8_t bTagType, uint32_t uiSector); 136 | void test_mifare_classic_blocks_sectors_functions(uint8_t bTagType); 137 | bool mfcuk_save_tag_dump(const char *filename, mifare_classic_tag *tag); 138 | bool mfcuk_save_tag_dump_ext(const char *filename, mifare_classic_tag_ext *tag_ext); 139 | bool mfcuk_load_tag_dump(const char *filename, mifare_classic_tag *tag); 140 | bool mfcuk_load_tag_dump_ext(const char *filename, mifare_classic_tag_ext *tag_ext); 141 | void print_mifare_classic_tag_keys(const char *title, mifare_classic_tag *tag); 142 | bool mfcuk_key_uint64_to_arr(const uint64_t *ui64Key, uint8_t *arr6Key); 143 | bool mfcuk_key_arr_to_uint64(const uint8_t *arr6Key, uint64_t *ui64Key); 144 | 145 | #endif // _MFCUK_MIFARE_H_ 146 | -------------------------------------------------------------------------------- /src/mfcuk_utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | Package: 3 | MiFare Classic Universal toolKit (MFCUK) 4 | 5 | Package version: 6 | 0.1 7 | 8 | Filename: 9 | mfcuk_utils.c 10 | 11 | Description: 12 | MFCUK common utility functions implementation. 13 | 14 | License: 15 | GPL2 (see below), Copyright (C) 2009, Andrei Costin 16 | 17 | * @file mfcuk_utils.c 18 | * @brief 19 | */ 20 | 21 | /* 22 | VERSION HISTORY 23 | -------------------------------------------------------------------------------- 24 | | Number : 0.1 25 | | dd/mm/yyyy : 23/11/2009 26 | | Author : zveriu@gmail.com, http://andreicostin.com 27 | | Description: Moved bulk of defines and prototypes from "mfcuk_keyrecovery_darkside.c" 28 | -------------------------------------------------------------------------------- 29 | */ 30 | 31 | /* 32 | LICENSE 33 | 34 | This program is free software: you can redistribute it and/or modify 35 | it under the terms of the GNU General Public License as published by 36 | the Free Software Foundation, either version 2 of the License, or 37 | (at your option) any later version. 38 | 39 | This program is distributed in the hope that it will be useful, 40 | but WITHOUT ANY WARRANTY; without even the implied warranty of 41 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 42 | GNU General Public License for more details. 43 | 44 | You should have received a copy of the GNU General Public License 45 | along with this program. If not, see . 46 | */ 47 | 48 | #include "config.h" 49 | 50 | #if defined(WIN32) 51 | #include 52 | #elif defined(HAVE_UNISTD_H) 53 | #include 54 | #else 55 | #error "Unsupported system" 56 | #endif 57 | 58 | #include "mfcuk_utils.h" 59 | #include 60 | 61 | /* 62 | http://www.velocityreviews.com/forums/t451319-advice-required-on-my-ascii-to-hex-conversion-c.html 63 | Basically, converting a hex digit into a hex nibble (4 binary digits) algorithm looks like; 64 | char xdigit; // hex digit to convert [0-9A-Fa-f] 65 | xdigit = tolower(xdigit); // make it lowercase [0-9a-f] 66 | xdigit -= '0'; // if it was a [0-9] digit, it's the value now 67 | if(xdigit > 9) // if it was a [a-f] digit, compensate for that 68 | xdigit = xdigit + '0' - 'a'; 69 | The below code is just an optimization of the algorithm. Maxim Yegorushkin 70 | */ 71 | 72 | /*inline*/ 73 | int is_hex(char c) 74 | { 75 | return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); 76 | } 77 | 78 | /*inline*/ 79 | unsigned char hex2bin(unsigned char h, unsigned char l) 80 | { 81 | h |= 0x20; // to lower 82 | h -= 0x30; 83 | h -= -(h > 9) & 0x27; 84 | l |= 0x20; 85 | l -= 0x30; 86 | l -= -(l > 9) & 0x27; 87 | return h << 4 | l; 88 | } 89 | 90 | void sleepmillis(unsigned int millis) 91 | { 92 | #ifdef WIN32 // If system is Windows, use system's own function if possible to reduce overhead, even if a standard C library is available 93 | Sleep(millis); 94 | #else 95 | usleep(millis * 1000); 96 | #endif 97 | } 98 | 99 | void clear_screen() 100 | { 101 | #ifdef WIN32 // On Windows, use "cls" command 102 | system("cls"); 103 | #else // Otherwise fall back to TTY control characters 104 | printf("\033[1;1H\033[J"); 105 | #endif 106 | } 107 | 108 | -------------------------------------------------------------------------------- /src/mfcuk_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | Package: 3 | MiFare Classic Universal toolKit (MFCUK) 4 | 5 | Package version: 6 | 0.1 7 | 8 | Filename: 9 | mfcuk_utils.h 10 | 11 | Description: 12 | MFCUK common utility functions prototypes. 13 | 14 | License: 15 | GPL2 (see below), Copyright (C) 2009, Andrei Costin 16 | 17 | * @file mfcuk_utils.h/ 18 | * @brief 19 | */ 20 | 21 | /* 22 | VERSION HISTORY 23 | -------------------------------------------------------------------------------- 24 | | Number : 0.1 25 | | dd/mm/yyyy : 23/11/2009 26 | | Author : zveriu@gmail.com, http://andreicostin.com 27 | | Description: Moved bulk of defines and prototypes from "mfcuk_keyrecovery_darkside.c" 28 | -------------------------------------------------------------------------------- 29 | */ 30 | 31 | /* 32 | LICENSE 33 | 34 | This program is free software: you can redistribute it and/or modify 35 | it under the terms of the GNU General Public License as published by 36 | the Free Software Foundation, either version 2 of the License, or 37 | (at your option) any later version. 38 | 39 | This program is distributed in the hope that it will be useful, 40 | but WITHOUT ANY WARRANTY; without even the implied warranty of 41 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 42 | GNU General Public License for more details. 43 | 44 | You should have received a copy of the GNU General Public License 45 | along with this program. If not, see . 46 | */ 47 | 48 | #ifndef _MFCUK_UTILS_H_ 49 | #define _MFCUK_UTILS_H_ 50 | 51 | /** 52 | * @fn int is_hex(char c) 53 | * @brief Checks if an ASCII character is a valid hexadecimal base digit 54 | * @param c The ASCII character to be checked 55 | * @return Returns true (non-zero) or false (zero) 56 | * 57 | * Checks if an ASCII character is a valid hexadecimal base digit. 58 | * Used for hex2bin() functionality. 59 | */ 60 | int is_hex(char c); 61 | 62 | /** 63 | * @fn unsigned char hex2bin(unsigned char h, unsigned char l) 64 | * @brief Converts from two nibbles (4 bits) into the corresponding byte 65 | * @param h The HIGH (left-most in human reading) nibble of two-char hex representation of a byte 66 | * @param l The LOW (right-most in human reading) nibble of two-char hex representation of a byte 67 | * @return Returns the byte which is formed from the two-char hex representation of it 68 | * 69 | * Converts from two nibbles (4 bits) into the corresponding byte. 70 | * Uses the algorithm and implementation from here: 71 | * http://www.velocityreviews.com/forums/t451319-advice-required-on-my-ascii-to-hex-conversion-c.html 72 | */ 73 | unsigned char hex2bin(unsigned char h, unsigned char l); 74 | 75 | /** 76 | * @fn void sleepmillis(unsigned int millis) 77 | * @brief Pauses execution for a certain amount of milliseconds 78 | * @param millis Number of milliseconds to sleep 79 | * 80 | * Wrapper for system-dependant sleep function. It pauses execution for a certain amount of milliseconds. 81 | */ 82 | void sleepmillis(unsigned int millis); 83 | 84 | /** 85 | * @fn void clear_screen(void); 86 | * @brief Clears output console 87 | * 88 | * Wrapper for system-dependant clear screen function. 89 | * Resets output console, clearing text and resetting character pointer. 90 | */ 91 | void clear_screen(void); 92 | 93 | #endif // _MFCUK_UTILS_H_ 94 | 95 | -------------------------------------------------------------------------------- /src/mifare.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Public platform independent Near Field Communication (NFC) library examples 3 | * 4 | * Copyright (C) 2009 Roel Verdult 5 | * Copyright (C) 2010 Romain Tartière 6 | * Copyright (C) 2010, 2011 Romuald Conty 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 1) Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2 )Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Note that this license only applies on the examples, NFC library itself is under LGPL 29 | * 30 | */ 31 | /** 32 | * @file mifare.c 33 | * @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc 34 | */ 35 | #include "mifare.h" 36 | 37 | #include 38 | 39 | #include 40 | 41 | /** 42 | * @brief Execute a MIFARE Classic Command 43 | * @return Returns true if action was successfully performed; otherwise returns false. 44 | * @param pmp Some commands need additional information. This information should be supplied in the mifare_param union. 45 | * 46 | * The specified MIFARE command will be executed on the tag. There are different commands possible, they all require the destination block number. 47 | * @note There are three different types of information (Authenticate, Data and Value). 48 | * 49 | * First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID. 50 | * They are both used to initialize the internal cipher-state of the PN53X chip (http://libnfc.org/hardware/pn53x-chip). 51 | * After a successful authentication it will be possible to execute other commands (e.g. Read/Write). 52 | * The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process. 53 | */ 54 | bool 55 | nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp) 56 | { 57 | uint8_t abtRx[265]; 58 | size_t szParamLen; 59 | uint8_t abtCmd[265]; 60 | //bool bEasyFraming; 61 | 62 | abtCmd[0] = mc; // The MIFARE Classic command 63 | abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff) 64 | 65 | switch (mc) { 66 | // Read and store command have no parameter 67 | case MC_READ: 68 | case MC_STORE: 69 | szParamLen = 0; 70 | break; 71 | 72 | // Authenticate command 73 | case MC_AUTH_A: 74 | case MC_AUTH_B: 75 | szParamLen = sizeof(struct mifare_param_auth); 76 | break; 77 | 78 | // Data command 79 | case MC_WRITE: 80 | szParamLen = sizeof(struct mifare_param_data); 81 | break; 82 | 83 | // Value command 84 | case MC_DECREMENT: 85 | case MC_INCREMENT: 86 | case MC_TRANSFER: 87 | szParamLen = sizeof(struct mifare_param_value); 88 | break; 89 | 90 | // Please fix your code, you never should reach this statement 91 | default: 92 | return false; 93 | break; 94 | } 95 | 96 | // When available, copy the parameter bytes 97 | if (szParamLen) 98 | memcpy(abtCmd + 2, (uint8_t *) pmp, szParamLen); 99 | 100 | // FIXME: Save and restore bEasyFraming 101 | // bEasyFraming = nfc_device_get_property_bool (pnd, NP_EASY_FRAMING, &bEasyFraming); 102 | if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true) < 0) { 103 | nfc_perror(pnd, "nfc_device_set_property_bool"); 104 | return false; 105 | } 106 | // Fire the mifare command 107 | int res; 108 | if ((res = nfc_initiator_transceive_bytes(pnd, abtCmd, 2 + szParamLen, abtRx, sizeof(abtRx), -1)) < 0) { 109 | if (res == NFC_ERFTRANS) { 110 | // "Invalid received frame", usual means we are 111 | // authenticated on a sector but the requested MIFARE cmd (read, write) 112 | // is not permitted by current acces bytes; 113 | // So there is nothing to do here. 114 | } else { 115 | nfc_perror(pnd, "nfc_initiator_transceive_bytes"); 116 | } 117 | // XXX nfc_device_set_property_bool (pnd, NP_EASY_FRAMING, bEasyFraming); 118 | return false; 119 | } 120 | /* XXX 121 | if (nfc_device_set_property_bool (pnd, NP_EASY_FRAMING, bEasyFraming) < 0) { 122 | nfc_perror (pnd, "nfc_device_set_property_bool"); 123 | return false; 124 | } 125 | */ 126 | 127 | // When we have executed a read command, copy the received bytes into the param 128 | if (mc == MC_READ) { 129 | if (res == 16) { 130 | memcpy(pmp->mpd.abtData, abtRx, 16); 131 | } else { 132 | return false; 133 | } 134 | } 135 | // Command succesfully executed 136 | return true; 137 | } 138 | -------------------------------------------------------------------------------- /src/mifare.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Public platform independent Near Field Communication (NFC) library examples 3 | * 4 | * Copyright (C) 2009 Roel Verdult 5 | * Copyright (C) 2010 Romain Tartière 6 | * Copyright (C) 2010, 2011 Romuald Conty 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions are met: 10 | * 1) Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 2 )Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | * 28 | * Note that this license only applies on the examples, NFC library itself is under LGPL 29 | * 30 | */ 31 | 32 | /** 33 | * @file mifare.h 34 | * @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc 35 | */ 36 | 37 | #ifndef _LIBNFC_MIFARE_H_ 38 | # define _LIBNFC_MIFARE_H_ 39 | 40 | # include 41 | 42 | // Compiler directive, set struct alignment to 1 uint8_t for compatibility 43 | # pragma pack(1) 44 | 45 | typedef enum { 46 | MC_AUTH_A = 0x60, 47 | MC_AUTH_B = 0x61, 48 | MC_READ = 0x30, 49 | MC_WRITE = 0xA0, 50 | MC_TRANSFER = 0xB0, 51 | MC_DECREMENT = 0xC0, 52 | MC_INCREMENT = 0xC1, 53 | MC_STORE = 0xC2 54 | } mifare_cmd; 55 | 56 | // MIFARE command params 57 | struct mifare_param_auth { 58 | uint8_t abtKey[6]; 59 | uint8_t abtAuthUid[4]; 60 | }; 61 | 62 | struct mifare_param_data { 63 | uint8_t abtData[16]; 64 | }; 65 | 66 | struct mifare_param_value { 67 | uint8_t abtValue[4]; 68 | }; 69 | 70 | typedef union { 71 | struct mifare_param_auth mpa; 72 | struct mifare_param_data mpd; 73 | struct mifare_param_value mpv; 74 | } mifare_param; 75 | 76 | // Reset struct alignment to default 77 | # pragma pack() 78 | 79 | bool nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp); 80 | 81 | // Compiler directive, set struct alignment to 1 uint8_t for compatibility 82 | # pragma pack(1) 83 | 84 | // MIFARE Classic 85 | typedef struct { 86 | uint8_t abtUID[4]; 87 | uint8_t btBCC; 88 | uint8_t btUnknown; 89 | uint8_t abtATQA[2]; 90 | uint8_t abtUnknown[8]; 91 | } mifare_classic_block_manufacturer; 92 | 93 | typedef struct { 94 | uint8_t abtData[16]; 95 | } mifare_classic_block_data; 96 | 97 | typedef struct { 98 | uint8_t abtKeyA[6]; 99 | uint8_t abtAccessBits[4]; 100 | uint8_t abtKeyB[6]; 101 | } mifare_classic_block_trailer; 102 | 103 | typedef union { 104 | mifare_classic_block_manufacturer mbm; 105 | mifare_classic_block_data mbd; 106 | mifare_classic_block_trailer mbt; 107 | } mifare_classic_block; 108 | 109 | typedef struct { 110 | mifare_classic_block amb[256]; 111 | } mifare_classic_tag; 112 | 113 | // MIFARE Ultralight 114 | typedef struct { 115 | uint8_t sn0[3]; 116 | uint8_t btBCC0; 117 | uint8_t sn1[4]; 118 | uint8_t btBCC1; 119 | uint8_t internal; 120 | uint8_t lock[2]; 121 | uint8_t otp[4]; 122 | } mifareul_block_manufacturer; 123 | 124 | typedef struct { 125 | uint8_t abtData[16]; 126 | } mifareul_block_data; 127 | 128 | typedef union { 129 | mifareul_block_manufacturer mbm; 130 | mifareul_block_data mbd; 131 | } mifareul_block; 132 | 133 | typedef struct { 134 | mifareul_block amb[4]; 135 | } mifareul_tag; 136 | 137 | // Reset struct alignment to default 138 | # pragma pack() 139 | 140 | #endif // _LIBNFC_MIFARE_H_ 141 | -------------------------------------------------------------------------------- /src/nfc-utils.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Free/Libre Near Field Communication (NFC) library 3 | * 4 | * Libnfc historical contributors: 5 | * Copyright (C) 2009 Roel Verdult 6 | * Copyright (C) 2009-2013 Romuald Conty 7 | * Copyright (C) 2010-2012 Romain Tartière 8 | * Copyright (C) 2010-2013 Philippe Teuwen 9 | * Copyright (C) 2012-2013 Ludovic Rousseau 10 | * Additional contributors of this file: 11 | * 12 | * Redistribution and use in source and binary forms, with or without 13 | * modification, are permitted provided that the following conditions are met: 14 | * 1) Redistributions of source code must retain the above copyright notice, 15 | * this list of conditions and the following disclaimer. 16 | * 2 )Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | * Note that this license only applies on the examples, NFC library itself is under LGPL 33 | * 34 | */ 35 | /** 36 | * @file nfc-utils.c 37 | * @brief Provide some examples shared functions like print, parity calculation, options parsing. 38 | */ 39 | #include 40 | #include 41 | 42 | #include "nfc-utils.h" 43 | 44 | uint8_t 45 | oddparity(const uint8_t bt) 46 | { 47 | // cf http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel 48 | return (0x9669 >> ((bt ^(bt >> 4)) & 0xF)) & 1; 49 | } 50 | 51 | void 52 | oddparity_bytes_ts(const uint8_t *pbtData, const size_t szLen, uint8_t *pbtPar) 53 | { 54 | size_t szByteNr; 55 | // Calculate the parity bits for the command 56 | for (szByteNr = 0; szByteNr < szLen; szByteNr++) { 57 | pbtPar[szByteNr] = oddparity(pbtData[szByteNr]); 58 | } 59 | } 60 | 61 | void 62 | print_hex(const uint8_t *pbtData, const size_t szBytes) 63 | { 64 | size_t szPos; 65 | 66 | for (szPos = 0; szPos < szBytes; szPos++) { 67 | printf("%02x ", pbtData[szPos]); 68 | } 69 | printf("\n"); 70 | } 71 | 72 | void 73 | print_hex_bits(const uint8_t *pbtData, const size_t szBits) 74 | { 75 | uint8_t uRemainder; 76 | size_t szPos; 77 | size_t szBytes = szBits / 8; 78 | 79 | for (szPos = 0; szPos < szBytes; szPos++) { 80 | printf("%02x ", pbtData[szPos]); 81 | } 82 | 83 | uRemainder = szBits % 8; 84 | // Print the rest bits 85 | if (uRemainder != 0) { 86 | if (uRemainder < 5) 87 | printf("%01x (%d bits)", pbtData[szBytes], uRemainder); 88 | else 89 | printf("%02x (%d bits)", pbtData[szBytes], uRemainder); 90 | } 91 | printf("\n"); 92 | } 93 | 94 | void 95 | print_hex_par(const uint8_t *pbtData, const size_t szBits, const uint8_t *pbtDataPar) 96 | { 97 | uint8_t uRemainder; 98 | size_t szPos; 99 | size_t szBytes = szBits / 8; 100 | 101 | for (szPos = 0; szPos < szBytes; szPos++) { 102 | printf("%02x", pbtData[szPos]); 103 | if (oddparity(pbtData[szPos]) != pbtDataPar[szPos]) { 104 | printf("! "); 105 | } else { 106 | printf(" "); 107 | } 108 | } 109 | 110 | uRemainder = szBits % 8; 111 | // Print the rest bits, these cannot have parity bit 112 | if (uRemainder != 0) { 113 | if (uRemainder < 5) 114 | printf("%01x (%d bits)", pbtData[szBytes], uRemainder); 115 | else 116 | printf("%02x (%d bits)", pbtData[szBytes], uRemainder); 117 | } 118 | printf("\n"); 119 | } 120 | 121 | void 122 | print_nfc_target(const nfc_target *pnt, bool verbose) 123 | { 124 | char *s; 125 | str_nfc_target(&s, pnt, verbose); 126 | printf("%s", s); 127 | nfc_free(s); 128 | } 129 | -------------------------------------------------------------------------------- /src/nfc-utils.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Free/Libre Near Field Communication (NFC) library 3 | * 4 | * Libnfc historical contributors: 5 | * Copyright (C) 2009 Roel Verdult 6 | * Copyright (C) 2009-2013 Romuald Conty 7 | * Copyright (C) 2010-2012 Romain Tartière 8 | * Copyright (C) 2010-2013 Philippe Teuwen 9 | * Copyright (C) 2012-2013 Ludovic Rousseau 10 | * Additional contributors of this file: 11 | * 12 | * Redistribution and use in source and binary forms, with or without 13 | * modification, are permitted provided that the following conditions are met: 14 | * 1) Redistributions of source code must retain the above copyright notice, 15 | * this list of conditions and the following disclaimer. 16 | * 2 )Redistributions in binary form must reproduce the above copyright 17 | * notice, this list of conditions and the following disclaimer in the 18 | * documentation and/or other materials provided with the distribution. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | * POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | * Note that this license only applies on the examples, NFC library itself is under LGPL 33 | * 34 | */ 35 | 36 | /** 37 | * @file nfc-utils.h 38 | * @brief Provide some examples shared functions like print, parity calculation, options parsing. 39 | */ 40 | 41 | #ifndef _EXAMPLES_NFC_UTILS_H_ 42 | # define _EXAMPLES_NFC_UTILS_H_ 43 | 44 | # include 45 | # include 46 | # include 47 | 48 | /** 49 | * @macro DBG 50 | * @brief Print a message of standard output only in DEBUG mode 51 | */ 52 | #ifdef DEBUG 53 | # define DBG(...) do { \ 54 | warnx ("DBG %s:%d", __FILE__, __LINE__); \ 55 | warnx (" " __VA_ARGS__ ); \ 56 | } while (0) 57 | #else 58 | # define DBG(...) {} 59 | #endif 60 | 61 | /** 62 | * @macro WARN 63 | * @brief Print a warn message 64 | */ 65 | #ifdef DEBUG 66 | # define WARN(...) do { \ 67 | warnx ("WARNING %s:%d", __FILE__, __LINE__); \ 68 | warnx (" " __VA_ARGS__ ); \ 69 | } while (0) 70 | #else 71 | # define WARN(...) warnx ("WARNING: " __VA_ARGS__ ) 72 | #endif 73 | 74 | /** 75 | * @macro ERR 76 | * @brief Print a error message 77 | */ 78 | #ifdef DEBUG 79 | # define ERR(...) do { \ 80 | warnx ("ERROR %s:%d", __FILE__, __LINE__); \ 81 | warnx (" " __VA_ARGS__ ); \ 82 | } while (0) 83 | #else 84 | # define ERR(...) warnx ("ERROR: " __VA_ARGS__ ) 85 | #endif 86 | 87 | #ifndef MIN 88 | #define MIN(a,b) (((a) < (b)) ? (a) : (b)) 89 | #endif 90 | #ifndef MAX 91 | #define MAX(a,b) (((a) > (b)) ? (a) : (b)) 92 | #endif 93 | 94 | uint8_t oddparity(const uint8_t bt); 95 | void oddparity_bytes_ts(const uint8_t *pbtData, const size_t szLen, uint8_t *pbtPar); 96 | 97 | void print_hex(const uint8_t *pbtData, const size_t szLen); 98 | void print_hex_bits(const uint8_t *pbtData, const size_t szBits); 99 | void print_hex_par(const uint8_t *pbtData, const size_t szBits, const uint8_t *pbtDataPar); 100 | 101 | void print_nfc_target(const nfc_target *pnt, bool verbose); 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /src/pm3_mfc_parser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Original source: proxmark3.org community forum 4 | 5 | import sys 6 | import os 7 | import string 8 | import commands 9 | 10 | def line_tag(line): 11 | if string.find(line, 'TAG') > 0: 12 | return True 13 | 14 | return False 15 | 16 | def line_rdr(line): 17 | if string.find(line, 'TAG') < 1: 18 | return True 19 | 20 | return False 21 | 22 | def line_bytes(line): 23 | bytes = line[20:len(line)-1] 24 | bytes = bytes.replace('crc', '') 25 | bytes = bytes.replace('!', '') 26 | bytes = bytes.replace(' ', '') 27 | 28 | return len(bytes)/2 29 | 30 | try: 31 | file= open(sys.argv[1]) 32 | except: 33 | print 34 | print '\tusage:', sys.argv[0], '' 35 | print 36 | sys.exit(True) 37 | 38 | lines = file.readlines() 39 | uid = '' 40 | find_multi_sector = False 41 | 42 | for i in range(len(lines)): 43 | if string.find(lines[i],': 93 20') > 0 and line_tag(lines[i + 1]) and line_bytes(lines[i + 1]) == 5: 44 | find_multi_sector = False 45 | key = '' 46 | 47 | uid = lines[i + 1][20:34] 48 | uid = uid.replace(' ', '') 49 | print 'Found TAG UID:', uid 50 | 51 | if uid and (string.find(lines[i],': 60') > 0 or string.find(lines[i],': 61') > 0) and line_tag(lines[i + 1]) and line_bytes(lines[i + 1]) == 4 and line_rdr(lines[i + 2]) and line_bytes(lines[i + 2]) == 8 and line_tag(lines[i + 3]) and line_bytes(lines[i + 3]) == 4: 52 | tag_challenge = lines[i+1][20:34] 53 | tag_challenge = tag_challenge.replace(' ', '') 54 | tag_challenge = tag_challenge.replace('!', '') 55 | print 'Nt:', tag_challenge 56 | 57 | reader_challenge_response = lines[i+2][20:50] 58 | reader_challenge_response = reader_challenge_response.replace(' ', '') 59 | reader_challenge_response = reader_challenge_response.replace('!', '') 60 | print 'Nt\':', reader_challenge_response 61 | 62 | tag_response = lines[i+3][20:34] 63 | tag_response = tag_response.replace(' ', '') 64 | tag_response = tag_response.replace('!', '') 65 | print 'Nr:', tag_response 66 | 67 | find_multi_sector = True 68 | 69 | # Usually, a multi-sector authentication if a sequence of R->T 4 bytes (encrypted 60 xx p1 p2 or 61 xx p1 p2) and T->R 4 bytes 70 | if find_multi_sector and line_rdr(lines[i]) and line_bytes(lines[i]) == 4 and string.find(lines[i],': 60') < 1 and string.find(lines[i],': 61') < 1 and line_tag(lines[i + 1]) and line_bytes(lines[i + 1]) == 4: 71 | encr_multi_sect_auth = lines[i][20:34] 72 | encr_multi_sect_auth = encr_multi_sect_auth.replace(' ', '') 73 | encr_multi_sect_auth = encr_multi_sect_auth.replace('!', '') 74 | #print 'Multi-sector AUTH (candidates):', encr_multi_sect_auth 75 | 76 | encr_multi_sect_Nt = lines[i + 1][20:34] 77 | encr_multi_sect_Nt = encr_multi_sect_Nt.replace(' ', '') 78 | encr_multi_sect_Nt = encr_multi_sect_Nt.replace('!', '') 79 | #print 'Multi-sector encrypted Nt (candidates):', encr_multi_sect_Nt 80 | 81 | mfcuk_P_params = './mfcuk -P ' + '0x' + uid + ':' + '0x' + tag_challenge + ':' + '0x' + reader_challenge_response[0:8] + ':' + '0x' + reader_challenge_response[8:16] + ':' + '0x' + tag_response + ':' + '0x' + encr_multi_sect_auth 82 | 83 | print 'Executing ', mfcuk_P_params 84 | #os.execv('./mfcuk',string.split(mfcuk_P_params)) 85 | -------------------------------------------------------------------------------- /src/trace1.txt: -------------------------------------------------------------------------------- 1 | + 561882: 1 : 26 2 | + 64: 2 : TAG 04 00 3 | + 10217: 2 : 93 20 4 | + 64: 5 : TAG 9c 59 9b 32 6c 5 | + 12313: 9 : 93 70 9c 59 9b 32 6c 6b 30 6 | + 64: 3 : TAG 08 b6 dd 7 | + 923318: 4 : 60 00 f5 7b 8 | + 112: 4 : TAG 82 a4 16 6c 9 | + 6985: 8 : a1 e4! 58 ce! 6e ea! 41 e0! !crc 10 | + 64: 4 : TAG 5c! ad f4 39! 11 | + 811513: 4 : 8e 0e! 5d! b9 !crc 12 | + 112: 4 : TAG 5a! 92 0d! 85! 13 | + 6946: 8 : 98! d7 6b! 77 d6 c6 e8 70 !crc 14 | + 64: 4 : TAG ca 7e! 0b! 63! 15 | + 670868: 4 : 3e! 70 9c! 8a !crc 16 | + 112: 4 : TAG 36! 41 24! 79 17 | + 9505: 8 : 1b! 8c 3a! 48! 83 5a 4a! 27 !crc 18 | + 64: 4 : TAG 40! 6a! 99! 4b 19 | + 905612: 4 : c9 7c 64! 13! !crc 20 | + 112: 4 : TAG b5! ab! 1d! 2b 21 | + 6936: 8 : 7e! d2 5c! ca! 4b! 50! 88! c4 !crc 22 | + 64: 4 : TAG bf dd 01 be! 23 | + 987853: 4 : 56 98 49 d6! !crc 24 | + 72: 18 : TAG 09 bf! f5! f6! fc! b9! 5e! 51! 07 ac f6 72 f8 73 3b! 1b 73! ad! !crc 25 | + 94864: 4 : 5c! 7b 24! 02 !crc 26 | + 72: 18 : TAG a0 1f! 0b! b7 0d! ba c9 e7! fa! 36! 47 d2 a0! 01! 40! 87 ff 95! !crc 27 | + 94827: 4 : c9 90 dc! a3 !crc 28 | + 72: 18 : TAG df b8! 7a bc! 17! 99 82! 5c 55 d5! 98! 68 8b f8 e7 89 dc 42! !crc 29 | + 99081: 4 : 9f! d5 0f! d8! !crc 30 | + 72: 18 : TAG ca! 40 fa! 34 82 cc 3e de 1f! 7f f7! f0 62! 18! 77! 34 30 07 !crc 31 | + 93995: 4 : ad 7f! 3e 0c! !crc 32 | + 72: 18 : TAG f4! 2b 17! 4c a2! 5a 0c! a0! d8 03! 05 cc cc 4c 1f 12! 0c! 78! !crc 33 | + 94857: 4 : f1! b4 f0 3b! !crc 34 | + 72: 18 : TAG 8f da ca 17! 42 8e 24 c9! 8e fb! 38! aa! 39 e2! dd dd! a8 a6 !crc 35 | + 94850: 4 : c4 03! 7b! 9a !crc 36 | + 72: 18 : TAG 9f! 42! 42 49! cd d1! 3d! fd 8e 8f d3 8d! d5! ca! ef! 15 84 c9! !crc 37 | + 93961: 4 : 33! 3b! ae 0a! !crc 38 | + 72: 18 : TAG 74 ed! 58 46! e7 cc 48 d1! 5a 4b b0! 3a! c1 79! 8a! bf! e7! 42 !crc 39 | + 93193: 4 : f6 ec! 36 91! !crc 40 | + 72: 18 : TAG 79! 63 89! 21! 24 1e 3e! 03! a8! c3! 9b 95! a1 ad! 6c! 34 52 94 !crc 41 | + 94866: 4 : ad! 5c! 47 c5! !crc 42 | + 72: 18 : TAG 68 d4 9d c2! 2b 18 46! f7 e8! 28 ea 03 a4 df d5! 9f 23 00! !crc 43 | + 93994: 4 : 41 4c! 40! 11 !crc 44 | + 72: 18 : TAG b1 95 17! 84! ac fc! 31 b8! 02 40 97! ec! 4c 19 6f e9 f0! 8c! !crc 45 | + 94818: 4 : b8! b5! 5c! 74! !crc 46 | + 72: 18 : TAG c6 03 b9 92! 7d! eb! 13 8a 56 b7 9c 7c 07 3d! 6a 95! 7e! 44 !crc 47 | 48 | # http://www.proxmark.org/forum/post/550/#p550 49 | # UID = 0x9c599b32 50 | # KEY = 0xffffffffffff 51 | # 0x9c599b32 0x82a4166c 0xa1e458ce 0x6eea41e0 0x5cadf439 52 | -------------------------------------------------------------------------------- /src/xgetopt.c: -------------------------------------------------------------------------------- 1 | // XGetopt.cpp Version 1.2 2 | // 3 | // Author: Hans Dietrich 4 | // hdietrich2@hotmail.com 5 | // 6 | // Description: 7 | // XGetopt.cpp implements getopt(), a function to parse command lines. 8 | // 9 | // History 10 | // Version 1.2 - 2003 May 17 11 | // - Added Unicode support 12 | // 13 | // Version 1.1 - 2002 March 10 14 | // - Added example to XGetopt.cpp module header 15 | // 16 | // This software is released into the public domain. 17 | // You are free to use it in any way you like. 18 | // 19 | // This software is provided "as is" with no expressed 20 | // or implied warranty. I accept no liability for any 21 | // damage or loss of business that this software may cause. 22 | // 23 | /////////////////////////////////////////////////////////////////////////////// 24 | 25 | 26 | /////////////////////////////////////////////////////////////////////////////// 27 | // if you are using precompiled headers then include this line: 28 | //#include "stdafx.h" 29 | /////////////////////////////////////////////////////////////////////////////// 30 | 31 | 32 | /////////////////////////////////////////////////////////////////////////////// 33 | // if you are not using precompiled headers then include these lines: 34 | //#include 35 | //#include 36 | //#include 37 | /////////////////////////////////////////////////////////////////////////////// 38 | 39 | #include 40 | #include 41 | #include "xgetopt.h" 42 | 43 | 44 | /////////////////////////////////////////////////////////////////////////////// 45 | // 46 | // X G e t o p t . c p p 47 | // 48 | // 49 | // NAME 50 | // getopt -- parse command line options 51 | // 52 | // SYNOPSIS 53 | // int getopt(int argc, char *argv[], char *optstring) 54 | // 55 | // extern char *optarg; 56 | // extern int optind; 57 | // 58 | // DESCRIPTION 59 | // The getopt() function parses the command line arguments. Its 60 | // arguments argc and argv are the argument count and array as 61 | // passed into the application on program invocation. In the case 62 | // of Visual C++ programs, argc and argv are available via the 63 | // variables __argc and __argv (double underscores), respectively. 64 | // getopt returns the next option letter in argv that matches a 65 | // letter in optstring. (Note: Unicode programs should use 66 | // __targv instead of __argv. Also, all character and string 67 | // literals should be enclosed in _T( ) ). 68 | // 69 | // optstring is a string of recognized option letters; if a letter 70 | // is followed by a colon, the option is expected to have an argument 71 | // that may or may not be separated from it by white space. optarg 72 | // is set to point to the start of the option argument on return from 73 | // getopt. 74 | // 75 | // Option letters may be combined, e.g., "-ab" is equivalent to 76 | // "-a -b". Option letters are case sensitive. 77 | // 78 | // getopt places in the external variable optind the argv index 79 | // of the next argument to be processed. optind is initialized 80 | // to 0 before the first call to getopt. 81 | // 82 | // When all options have been processed (i.e., up to the first 83 | // non-option argument), getopt returns EOF, optarg will point 84 | // to the argument, and optind will be set to the argv index of 85 | // the argument. If there are no non-option arguments, optarg 86 | // will be set to NULL. 87 | // 88 | // The special option "--" may be used to delimit the end of the 89 | // options; EOF will be returned, and "--" (and everything after it) 90 | // will be skipped. 91 | // 92 | // RETURN VALUE 93 | // For option letters contained in the string optstring, getopt 94 | // will return the option letter. getopt returns a question mark (?) 95 | // when it encounters an option letter not included in optstring. 96 | // EOF is returned when processing is finished. 97 | // 98 | // BUGS 99 | // 1) Long options are not supported. 100 | // 2) The GNU double-colon extension is not supported. 101 | // 3) The environment variable POSIXLY_CORRECT is not supported. 102 | // 4) The + syntax is not supported. 103 | // 5) The automatic permutation of arguments is not supported. 104 | // 6) This implementation of getopt() returns EOF if an error is 105 | // encountered, instead of -1 as the latest standard requires. 106 | // 107 | // EXAMPLE 108 | // BOOL CMyApp::ProcessCommandLine(int argc, char *argv[]) 109 | // { 110 | // int c; 111 | // 112 | // while ((c = getopt(argc, argv, _T("aBn:"))) != EOF) 113 | // { 114 | // switch (c) 115 | // { 116 | // case _T('a'): 117 | // TRACE(_T("option a\n")); 118 | // // 119 | // // set some flag here 120 | // // 121 | // break; 122 | // 123 | // case _T('B'): 124 | // TRACE( _T("option B\n")); 125 | // // 126 | // // set some other flag here 127 | // // 128 | // break; 129 | // 130 | // case _T('n'): 131 | // TRACE(_T("option n: value=%d\n"), atoi(optarg)); 132 | // // 133 | // // do something with value here 134 | // // 135 | // break; 136 | // 137 | // case _T('?'): 138 | // TRACE(_T("ERROR: illegal option %s\n"), argv[optind-1]); 139 | // return FALSE; 140 | // break; 141 | // 142 | // default: 143 | // TRACE(_T("WARNING: no handler for option %c\n"), c); 144 | // return FALSE; 145 | // break; 146 | // } 147 | // } 148 | // // 149 | // // check for non-option args here 150 | // // 151 | // return TRUE; 152 | // } 153 | // 154 | /////////////////////////////////////////////////////////////////////////////// 155 | 156 | char *optarg; // global argument pointer 157 | int optind = 0; // global argv index 158 | 159 | int getopt(int argc, char *argv[], char *optstring) 160 | { 161 | char c = 0; 162 | char *cp = NULL; 163 | 164 | static char *next = NULL; 165 | if (optind == 0) 166 | next = NULL; 167 | 168 | optarg = NULL; 169 | 170 | if (next == NULL || *next == '\0') { 171 | if (optind == 0) 172 | optind++; 173 | 174 | if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') { 175 | optarg = NULL; 176 | if (optind < argc) 177 | optarg = argv[optind]; 178 | return EOF; 179 | } 180 | 181 | if (strcmp(argv[optind], "--") == 0) { 182 | optind++; 183 | optarg = NULL; 184 | if (optind < argc) 185 | optarg = argv[optind]; 186 | return EOF; 187 | } 188 | 189 | next = argv[optind]; 190 | next++; // skip past - 191 | optind++; 192 | } 193 | 194 | c = *next++; 195 | cp = strchr(optstring, c); 196 | 197 | if (cp == NULL || c == ':') 198 | return '?'; 199 | 200 | cp++; 201 | if (*cp == ':') { 202 | if (*next != '\0') { 203 | optarg = next; 204 | next = NULL; 205 | } else if (optind < argc) { 206 | optarg = argv[optind]; 207 | optind++; 208 | } else { 209 | return '?'; 210 | } 211 | } 212 | 213 | return c; 214 | } 215 | -------------------------------------------------------------------------------- /src/xgetopt.h: -------------------------------------------------------------------------------- 1 | // XGetopt.h Version 1.2 2 | // 3 | // Author: Hans Dietrich 4 | // hdietrich2@hotmail.com 5 | // 6 | // This software is released into the public domain. 7 | // You are free to use it in any way you like. 8 | // 9 | // This software is provided "as is" with no expressed 10 | // or implied warranty. I accept no liability for any 11 | // damage or loss of business that this software may cause. 12 | // 13 | /////////////////////////////////////////////////////////////////////////////// 14 | 15 | #ifndef XGETOPT_H 16 | #define XGETOPT_H 17 | 18 | #if HAVE_UNISTD_H 19 | #include 20 | #else 21 | 22 | extern int optind, opterr; 23 | extern char *optarg; 24 | 25 | int getopt(int argc, char *argv[], char *optstring); 26 | 27 | #endif 28 | 29 | #endif //XGETOPT_H 30 | -------------------------------------------------------------------------------- /tools/proxmark3_parser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Original source: proxmark3.org community forum 4 | 5 | import sys 6 | import os 7 | import string 8 | 9 | try: 10 | file= open(sys.argv[1]) 11 | except: 12 | print 13 | print '\tusage: mifarecrack.py ' 14 | print 15 | sys.exit(True) 16 | 17 | lines= file.readlines() 18 | uid= '' 19 | 20 | gotone= False 21 | for i in range(len(lines)): 22 | if not uid and string.find(lines[i],': 93 20') > 0: 23 | uid= lines[i + 1][20:34] 24 | print 25 | print 'Found TAG UID:', uid 26 | if string.find(lines[i],': 60') > 0 or string.find(lines[i],': 61') > 0: 27 | gotone= True 28 | tag_challenge= lines[i+1] 29 | reader_challenge_response= lines[i+2] 30 | tag_response= lines[i+3] 31 | break 32 | if not gotone: 33 | print 'No crypto exchange found!' 34 | sys.exit(True) 35 | 36 | crackstring= './mifarecrack '+ uid 37 | 38 | # now process challenge/response 39 | crackstring += ' ' + tag_challenge[20:34] 40 | crackstring += ' ' + reader_challenge_response[20:50] 41 | crackstring += ' ' + tag_response[20:34] 42 | print 'Executing ', crackstring 43 | os.execv('./mifarecrack',string.split(crackstring)) 44 | --------------------------------------------------------------------------------