From 716e1154fadfe5f9d1ebb743ad75a4e2c011149a Mon Sep 17 00:00:00 2001 From: Thorsten Schroeder Date: Mon, 28 Mar 2016 04:04:53 +0200 Subject: [PATCH] first commit --- README.md | 111 +++++++++++++ crypto-ms.c | 348 +++++++++++++++++++++++++++++++++++++++++ crypto.h | 46 ++++++ genwords.py | 61 ++++++++ helper.c | 155 +++++++++++++++++++ helper.h | 82 ++++++++++ mod0keecrack.c | 410 +++++++++++++++++++++++++++++++++++++++++++++++++ mod0keecrack.h | 113 ++++++++++++++ 8 files changed, 1326 insertions(+) create mode 100755 README.md create mode 100755 crypto-ms.c create mode 100755 crypto.h create mode 100755 genwords.py create mode 100755 helper.c create mode 100755 helper.h create mode 100755 mod0keecrack.c create mode 100755 mod0keecrack.h diff --git a/README.md b/README.md new file mode 100755 index 0000000..4bc8bc5 --- /dev/null +++ b/README.md @@ -0,0 +1,111 @@ +# mod0keecrack + +## Introduction + +> *KeePass is a free open source password manager, which helps you to manage your passwords in a secure way. You can put all your passwords in one database, which is locked with one master key or a key file.* +(Source: http://keepass.info/) + +**mod0keecrack** is a simple tool to crack/bruteforce passwords of KeePass 2 databases. It implements a KeePass 2 Database file parser for .kdbx files, as well as decryption routines to verify if a supplied password is correct. mod0keecrack only handles the encrypted file format and is not able to parse the resulting plaintext database. The only purpose of mod0keecrack is the brute-forcing of a KeePass 2 database password. + +mod0keecrack handles KeePass 2 databases that are encrypted with password-only, or with password and key-file. + +Currently, there is no incremental or template-based bruteforce algorithm for passphrase generation implemented yet. To use mod0keecrack, you need to generate own wordlists or supply a wordlist via pipe/stdin. For example, you could use the john password cracker to generate wordlists and feed them directly into mod0keecrack via stdin. You can also use text-files with a wordlist on the command-line. + +Using wordlists is recommended, as dumb incremental brute-force may take a too long time due to the crypto-algorithms that are used by KeePass databases (SHA256 and many AES key-transformation rounds). + +mod0keecrack is plain C and has no 3rd party library dependencies on Windows, as it's using the Microsoft Cryptographic (CNG) Framework. A platform independent implementation could be done by simply porting crypto-ms.c to e.g. crypto-openssl.c. + +## Usage + +To encrypt password databases, KeePass supports passwords, keyfiles or a password-keyfile combo. To crack a password-only database, use mod0keecrack like this: + +`mod0keecrack [wordlist.txt]` + +To crack a database that also uses a key-file, use the command line as shown above, and copy the keyfile to the same directory as the database and rename it to .key. For example, if your KeePass database filename is `lala.kdbx` you must copy the keyfile to `lala.key` within the same directory. **If there is a corresponding .key file within the same directory, mod0keecrack always consider it as key-file input.** + +wordlist.txt is optional. If no wordlist is provided via command line argument, mod0keecrack reads a wordlist from stdin. If you want to generate a wordlist on the fly, you can use genwords.py as an example and use it like this: + +`genwords.py Secrets%04d! | mod0keecrack lala.kdbx` + +Example output of the last command line (lala.kdbx uses password AND keyfile lala.key): + +
+mod0keecrack>genwords.py Secrets%04d! | mod0keecrack.exe lala.kdbx
+[*] using  db: lala.kdbx
+[*] using key: lala.key
+[*] kdbx header:
+[-]    file magic:          9aa2d903
+[-]    file identifier:     b54bfb67
+[-]    file minor version:  0001
+[-]    file major version:  0003
+[*] kdbx headerentries:
+[-]    END:                 0D0A0D0A
+[-]    COMMENT:
+[-]    CIPHERID:            31C1F2E6BF714350BE5805216AFC5AFF
+[-]    COMPRESSIONFLAGS:    00000001
+[-]    MASTERSEED:          BD5A62AC01FD27B040D98894A7FA306D0F9AED7A23E870DC1E36ECE31DA2526B
+[-]    TRANSFORMSEED:       FFA6509325D87EDD8FAFA2A44C814F8846109FC1F7BCF2775F278C1C0CDF52A7
+[-]    TRANSFORMROUNDS:     00000000000186a0
+[-]    ENCRYPTIONIV:        40F71E30D138591E5F8AF4EDF1DB9EE0
+[-]    PROTECTEDSTREAMKEY:  27CA955DF72F13301E1A038404ADCA4D59E8DC26B30F8776E393F0F22568E13E
+[-]    STREAMSTARTBYTES:    76B99E10BE00334DDE830361A07FBA86845F39DD0DCBCEEE5102D6F41204B746
+[-]    INNERRANDOMSTREAMID: 00000002
+[*] kdbx payload:
+[-]    payload offset:      de
+[-]    payload len:         470
+[*] Using keyfile lala.key
+[+] key hash:               A884B77F5E1ED180BDF95B988BD032247CE6A87893BB4CC5C0532407BC86FE3B
+[*] kdbx crack:
+[*] decryption successful with password Secrets2015!
+
+ +mod0keecrack does not process decrypted kdbx-database payload. It simply tells you, if a database-passphrase was right or wrong. + +## Platforms + +mod0keecrack is implemented in plain C and should be able to compile and run on any platform, if the crypto-framework is ported to the target platform. Currently, the only platform dependend code is implemented in three functions in crypto-ms.c. The first version is using the Microsoft CNG (bcrypt) framework for SHA256 and AES. It should be no issue to implement a platform independent openssl-based version of crypto-ms.c. + +## Building + +To build mod0keecrack on Windows, open your Dev-command prompt and enter: + +`cl.exe /Femod0keecrack.exe helper.c mod0keecrack.c crypto-ms.c bcrypt.lib` + +## Author and Legal Stuff + +mod0keecrack was written by Thorsten (THS) Schroeder of modzero. You can get in touch with me e.g. via twitter: `@__ths__` + +
+ * Copyright (c) 2016, mod0keecrack
+ *    Thorsten Schroeder 
+ *
+ * All rights reserved.
+ *
+ * This file is part of mod0keecrack.
+ *
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * Thorsten Schroeder  wrote this file. As long as you 
+ * retain this notice you can do whatever you want with this stuff. If we meet 
+ * some day, and you think this stuff is worth it, you can buy me a beer in 
+ * return. Thorsten Schroeder.
+ *
+ * NON-MILITARY-USAGE CLAUSE
+ * Redistribution and use in source and binary form for military use and 
+ * military research is not permitted. Infringement of these clauses may
+ * result in publishing the source code of the utilizing applications and 
+ * libraries to the public. As this software is developed, tested and
+ * reviewed by *international* volunteers, this clause shall not be refused 
+ * due to the matter of *national* security concerns.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE DDK PROJECT BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ diff --git a/crypto-ms.c b/crypto-ms.c new file mode 100755 index 0000000..979e5c4 --- /dev/null +++ b/crypto-ms.c @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2016, mod0keecrack + * Thorsten Schroeder + * + * All rights reserved. + * + * This file is part of mod0keecrack. + * + * "THE BEER-WARE LICENSE" (Revision 42): + * Thorsten Schroeder wrote this file. As long as you + * retain this notice you can do whatever you want with this stuff. If we meet + * some day, and you think this stuff is worth it, you can buy me a beer in + * return. Thorsten Schroeder. + * + * NON-MILITARY-USAGE CLAUSE + * Redistribution and use in source and binary form for military use and + * military research is not permitted. Infringement of these clauses may + * result in publishing the source code of the utilizing applications and + * libraries to the public. As this software is developed, tested and + * reviewed by *international* volunteers, this clause shall not be refused + * due to the matter of *national* security concerns. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE DDK PROJECT BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * File: crypto-ms.c + * Description: Platform specific implementation of keepassx crypto functions + * on Microsoft Windows. + */ + +#include +#include +#include +#include + +#include "helper.h" +#include "mod0keecrack.h" + +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) + +int aes_transformkey(m0_kdbx_header_entry_t *hdr, uint8_t *tkey, size_t tkeylen) +{ + BCRYPT_ALG_HANDLE aes = NULL; + BCRYPT_KEY_HANDLE key = NULL; + NTSTATUS status = 0; + DWORD len_ciphertext = 0, + tmp_len = 0, + key_objectlen = 0; + + PBYTE key_object = NULL; + uint64_t rounds = 0; + + // Open an algorithm handle. + status = BCryptOpenAlgorithmProvider( + &aes, + BCRYPT_AES_ALGORITHM, + NULL, + 0); + + if(!NT_SUCCESS(status)) { + printf("[!] Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + goto cleanup; + } + + // Calculate the size of the buffer to hold the KeyObject. + status = BCryptGetProperty( + aes, + BCRYPT_OBJECT_LENGTH, + (PBYTE)&key_objectlen, + sizeof(DWORD), + &tmp_len, + 0); + + if(!NT_SUCCESS(status)) { + printf("[!] Error 0x%x returned by BCryptGetProperty\n", status); + goto cleanup; + } + + // Allocate the key object on the heap. + key_object = (PBYTE)HeapAlloc(GetProcessHeap(), 0, key_objectlen); + + if(NULL == key_object) { + printf("[!] memory allocation failed\n"); + goto cleanup; + } + + status = BCryptSetProperty( + aes, + BCRYPT_CHAINING_MODE, + (PBYTE)BCRYPT_CHAIN_MODE_ECB, + sizeof(BCRYPT_CHAIN_MODE_ECB), + 0); + + if(!NT_SUCCESS(status)) { + printf("[!] Error 0x%x returned by BCryptSetProperty\n", status); + goto cleanup; + } + + // Generate the key from supplied input key bytes. + status = BCryptGenerateSymmetricKey( + aes, + &key, + key_object, + key_objectlen, + hdr[TRANSFORMSEED].data, + hdr[TRANSFORMSEED].len, + 0); + + if(!NT_SUCCESS(status)) { + printf("[!] Error 0x%x returned by BCryptGenerateSymmetricKey\n", status); + goto cleanup; + } + + status = BCryptEncrypt( + key, + tkey, + tkeylen, + NULL, + NULL, + 0, + NULL, + 0, + &len_ciphertext, + 0); + + if(!NT_SUCCESS(status)) { + printf("[!] Error 0x%x returned by BCryptEncrypt (calculate)\n", status); + goto cleanup; + } + + for(rounds = 0; rounds < hdr[TRANSFORMROUNDS].qw; rounds++) { + + status = BCryptEncrypt( + key, + tkey, + tkeylen, + NULL, + NULL, + 0, + tkey, + tkeylen, + &tmp_len, + 0); + + if(!NT_SUCCESS(status)) { + printf("[!] Error 0x%x returned by BCryptEncrypt (encrypt)\n", status); + goto cleanup; + } + } + +cleanup: + + if(aes) { + BCryptCloseAlgorithmProvider(aes,0); + } + + if (key) { + BCryptDestroyKey(key); + } + + if(key_object) { + HeapFree(GetProcessHeap(), 0, key_object); + } + + return status; +} + +bool aes_decrypt_check(m0_kdbx_header_entry_t *hdr, uint8_t *masterkey, m0_kdbx_payload_t *payload) +{ + bool res = false; + + BCRYPT_ALG_HANDLE aes = NULL; + BCRYPT_KEY_HANDLE ctx = NULL; + NTSTATUS status = 0; + DWORD len_ciphertext = 0, + tmp_len = 0, + key_objectlen = 0; + + PBYTE key_object = NULL; + + uint8_t plaintext[32] = {0}; + uint8_t iv[256] = {0}; + uint8_t ivlen = hdr[ENCRYPTIONIV].len & 0xFF; + + // we need to create a local copy of IV, as it is modified during decryption. + memcpy(&iv, hdr[ENCRYPTIONIV].data, ivlen); + + // Open an algorithm handle. + status = BCryptOpenAlgorithmProvider( + &aes, + BCRYPT_AES_ALGORITHM, + NULL, + 0); + + if(!NT_SUCCESS(status)) { + printf("[!] Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); + goto cleanup; + } + + // Calculate the size of the buffer to hold the Key Object. + status = BCryptGetProperty( + aes, + BCRYPT_OBJECT_LENGTH, + (PBYTE)&key_objectlen, + sizeof(DWORD), + &tmp_len, + 0); + + if(!NT_SUCCESS(status)) { + printf("[!] Error 0x%x returned by BCryptGetProperty\n", status); + goto cleanup; + } + + // We should use preallocated memory for better performance... + key_object = (PBYTE)HeapAlloc(GetProcessHeap(), 0, key_objectlen); + + if(NULL == key_object) { + printf("[!] memory allocation failed\n"); + goto cleanup; + } + + status = BCryptSetProperty( + aes, + BCRYPT_CHAINING_MODE, + (PBYTE)BCRYPT_CHAIN_MODE_CBC, + sizeof(BCRYPT_CHAIN_MODE_CBC), + 0); + + if(!NT_SUCCESS(status)) { + printf("[!] Error 0x%x returned by BCryptSetProperty\n", status); + goto cleanup; + } + + // Generate the key from supplied input key bytes. + status = BCryptGenerateSymmetricKey( + aes, + &ctx, + key_object, + key_objectlen, + masterkey, + 32, + 0); + + if(!NT_SUCCESS(status)) { + printf("[!] Error 0x%x returned by BCryptGenerateSymmetricKey\n", status); + goto cleanup; + } + + status = BCryptDecrypt( + ctx, + payload->encrypted, + hdr[STREAMSTARTBYTES].len, + NULL, + iv, + ivlen, + plaintext, + sizeof(plaintext), + &tmp_len, + 0); + + if(!NT_SUCCESS(status)) { + printf("[!] Error 0x%x returned by BCryptDecrypt\n", status); + goto cleanup; + } + + // success! + if (0 == memcmp(plaintext, hdr[STREAMSTARTBYTES].data, hdr[STREAMSTARTBYTES].len)) { + res = true; + payload->decrypted = malloc(hdr[STREAMSTARTBYTES].len); + memcpy(payload->decrypted, plaintext, hdr[STREAMSTARTBYTES].len); + } + +cleanup: + + if(aes) { + BCryptCloseAlgorithmProvider(aes,0); + } + + if (ctx) { + BCryptDestroyKey(ctx); + } + + if(key_object) { + HeapFree(GetProcessHeap(), 0, key_object); + } + + return res; +} + + +int sha256_hash(uint8_t *hash, uint8_t *data, size_t len) +{ + int res = 0; + NTSTATUS status; + BCRYPT_ALG_HANDLE sha = NULL; + BCRYPT_HASH_HANDLE ctx = NULL; + + status = BCryptOpenAlgorithmProvider( + &sha, + BCRYPT_SHA256_ALGORITHM, + NULL, + BCRYPT_HASH_REUSABLE_FLAG); + + status = BCryptCreateHash( + sha, + &ctx, + NULL, + 0, + NULL, + 0, + 0); + + status = BCryptHashData( + ctx, + (PBYTE)data, + len, + 0); + + status = BCryptFinishHash( + ctx, + hash, + 32, + 0); + +cleanup: + + if (NULL != ctx) { + BCryptDestroyHash(ctx); + } + + if( NULL != sha ) { + BCryptCloseAlgorithmProvider( + sha, + 0); + } + + return res; + +} + diff --git a/crypto.h b/crypto.h new file mode 100755 index 0000000..2278111 --- /dev/null +++ b/crypto.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, mod0keecrack + * Thorsten Schroeder + * + * All rights reserved. + * + * This file is part of mod0keecrack. + * + * "THE BEER-WARE LICENSE" (Revision 42): + * Thorsten Schroeder wrote this file. As long as you + * retain this notice you can do whatever you want with this stuff. If we meet + * some day, and you think this stuff is worth it, you can buy me a beer in + * return. Thorsten Schroeder. + * + * NON-MILITARY-USAGE CLAUSE + * Redistribution and use in source and binary form for military use and + * military research is not permitted. Infringement of these clauses may + * result in publishing the source code of the utilizing applications and + * libraries to the public. As this software is developed, tested and + * reviewed by *international* volunteers, this clause shall not be refused + * due to the matter of *national* security concerns. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE DDK PROJECT BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * File: mod0keecrack.h + * Description: Project header files. + */ + +#ifndef _CRYPTO_H +#define _CRYPTO_H + +// implementation in platform specific files: crypto-XX.c +int aes_transformkey(m0_kdbx_header_entry_t *hdr, uint8_t *tkey, size_t tkeylen); +int aes_decrypt_check(m0_kdbx_header_entry_t *hdr, uint8_t *masterkey, m0_kdbx_payload_t *p); +int sha256_hash(uint8_t *hash, uint8_t *data, size_t len); + +#endif diff --git a/genwords.py b/genwords.py new file mode 100755 index 0000000..476b523 --- /dev/null +++ b/genwords.py @@ -0,0 +1,61 @@ +#!python +# * +# * Copyright (c) 2016, mod0keecrack +# * Thorsten Schroeder +# * +# * All rights reserved. +# * +# * This file is part of mod0keecrack. +# * +# * "THE BEER-WARE LICENSE" (Revision 42): +# * Thorsten Schroeder wrote this file. As long as you +# * retain this notice you can do whatever you want with this stuff. If we meet +# * some day, and you think this stuff is worth it, you can buy me a beer in +# * return. Thorsten Schroeder. +# * +# * NON-MILITARY-USAGE CLAUSE +# * Redistribution and use in source and binary form for military use and +# * military research is not permitted. Infringement of these clauses may +# * result in publishing the source code of the utilizing applications and +# * libraries to the public. As this software is developed, tested and +# * reviewed by *international* volunteers, this clause shall not be refused +# * due to the matter of *national* security concerns. +# * +# * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# * ARE DISCLAIMED. IN NO EVENT SHALL THE DDK PROJECT BE LIABLE FOR ANY DIRECT, +# * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# * +# * File: genwords.py +# * Description: wordlist generation demo +# * + +import sys + +def main(): + check_args(sys.argv) + fmt = sys.argv[1] + + try: + for i in xrange(9999): + print(fmt % i) + except Exception, e: + sys.exit(0) # stdout was closed + +def check_args(argv): + if len(argv) < 2: + print("[!] usage: %s " % sys.argv[0]) + print("[-] e.g. %s 'Secrets%%04d!'" % sys.argv[0]) + sys.exit(1) + +if __name__ == "__main__": + main() + + + diff --git a/helper.c b/helper.c new file mode 100755 index 0000000..8745ef9 --- /dev/null +++ b/helper.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2016, mod0keecrack + * Thorsten Schroeder + * + * All rights reserved. + * + * This file is part of mod0keecrack. + * + * "THE BEER-WARE LICENSE" (Revision 42): + * Thorsten Schroeder wrote this file. As long as you + * retain this notice you can do whatever you want with this stuff. If we meet + * some day, and you think this stuff is worth it, you can buy me a beer in + * return. Thorsten Schroeder. + * + * NON-MILITARY-USAGE CLAUSE + * Redistribution and use in source and binary form for military use and + * military research is not permitted. Infringement of these clauses may + * result in publishing the source code of the utilizing applications and + * libraries to the public. As this software is developed, tested and + * reviewed by *international* volunteers, this clause shall not be refused + * due to the matter of *national* security concerns. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE DDK PROJECT BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * File: helper.c + * Description: Implementation of helper functions. + */ + +#include +#include + +#include + +#include "helper.h" + +// bin to hexascii nibble +static const unsigned char _tab[] = "0123456789ABCDEF"; + +void print_hex_byte(char b) +{ + putchar( _tab[ (b >> 4) & 0xF ] ); + putchar( _tab[ (b >> 0) & 0xF ] ); +} + +void print_hex_word(int16_t w) +{ + putchar( _tab[ (w >> 12) & 0xF ] ); + putchar( _tab[ (w >> 8) & 0xF ] ); + putchar( _tab[ (w >> 4) & 0xF ] ); + putchar( _tab[ (w >> 0) & 0xF ] ); +} + + +void print_hex_dword(int32_t d) +{ + putchar( _tab[ (d >> 28) & 0xF ] ); + putchar( _tab[ (d >> 24) & 0xF ] ); + putchar( _tab[ (d >> 20) & 0xF ] ); + putchar( _tab[ (d >> 16) & 0xF ] ); + putchar( _tab[ (d >> 12) & 0xF ] ); + putchar( _tab[ (d >> 8) & 0xF ] ); + putchar( _tab[ (d >> 4) & 0xF ] ); + putchar( _tab[ (d >> 0) & 0xF ] ); +} + +void print_hex_buf(char *s, uint32_t l) +{ + + while(l--) { + putchar( _tab[ (*s >> 4) & 0xF ] ); + putchar( _tab[ (*s >> 0) & 0xF ] ); + s++; + } +} + + +/* + * print data in rows of 16 bytes: offset hex ascii + * + * 00000 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d 0a GET / HTTP/1.1.. + */ +void print_hex_ascii_line(const unsigned char *payload, int slen, int offset) +{ + + int i; + int gap, len; + const unsigned char *ch, *ch2; + + len = 16; + ch2 = ch = payload; + + do { + + /* offset */ + //printf("%05x ", offset); + print_hex_word(offset & 0xffff); + putchar(' '); + + /* hex */ + if(slen < len) + len=slen; + + for(i = 0; i < len; i++) { + + //printf("%02x ", *ch); + + print_hex_byte(*ch); + putchar(' '); + + ch++; + /* print extra space after 8th byte for visual aid */ + if (i == 7) + putchar(' '); + } + /* print space to handle line less than 8 bytes */ + if (len < 8) + putchar(' '); + + /* fill hex gap with spaces if not full line */ + if (len < 16) { + gap = 16 - len; + for (i = 0; i < gap; i++) { + printf(" "); + } + } + printf(" "); + + /* ascii (if printable) */ + for(i = 0; i < len; i++) { + if (isprint(*ch2)){ + printf("%c", *ch2); + } else + putchar(' '); + ch2++; + } + + puts(""); + slen -= 16; + offset += len; + } while( slen > 0 ) ; + + + return; +} + + diff --git a/helper.h b/helper.h new file mode 100755 index 0000000..a3b0eab --- /dev/null +++ b/helper.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2016, mod0keecrack + * Thorsten Schroeder + * + * All rights reserved. + * + * This file is part of mod0keecrack. + * + * "THE BEER-WARE LICENSE" (Revision 42): + * Thorsten Schroeder wrote this file. As long as you + * retain this notice you can do whatever you want with this stuff. If we meet + * some day, and you think this stuff is worth it, you can buy me a beer in + * return. Thorsten Schroeder. + * + * NON-MILITARY-USAGE CLAUSE + * Redistribution and use in source and binary form for military use and + * military research is not permitted. Infringement of these clauses may + * result in publishing the source code of the utilizing applications and + * libraries to the public. As this software is developed, tested and + * reviewed by *international* volunteers, this clause shall not be refused + * due to the matter of *national* security concerns. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE DDK PROJECT BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * File: helper.h + * Description: Declaration & Documentation of helper functions. + */ + +#ifndef _HELPER_H +#define _HELPER_H + +#include + +/*! + * print buffer as hex-dump. The input buffer is printed as hex-dump, with + * an offset column first. The second column is the hexadecimal dump of the binary data. + * Third column is the ascii representation of the input data. + * Example: + * 00000 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d 0a GET / HTTP/1.1.. + * + * @param[in] s source buffer + * @param[in] l source buffer length + * @param[in] o offset +*/ +void print_hex_ascii_line(const unsigned char *s, int l, int o); + +/*! + * print byte as hex. Prints input byte b as hex string. + * @param[in] b byte +*/ +void print_hex_byte(char b); + +/*! + * print 16bit word as hex. Prints input word w as hex string. + * @param[in] w word +*/ +void print_hex_word(int16_t w); + +/*! + * print 32bit dword as hex. Prints input dword d as hex string. + * @param[in] d dword +*/ +void print_hex_dword(int32_t d); + +/*! + * print buffer as hex. Prints input byte buffer s as hex string. + * @param[in] s source buffer + * @param[in] l source buffer length +*/ +void print_hex_buf(char *s, uint32_t l); + + +#endif \ No newline at end of file diff --git a/mod0keecrack.c b/mod0keecrack.c new file mode 100755 index 0000000..fe541ec --- /dev/null +++ b/mod0keecrack.c @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2016, mod0keecrack + * Thorsten Schroeder + * + * All rights reserved. + * + * This file is part of mod0keecrack. + * + * "THE BEER-WARE LICENSE" (Revision 42): + * Thorsten Schroeder wrote this file. As long as you + * retain this notice you can do whatever you want with this stuff. If we meet + * some day, and you think this stuff is worth it, you can buy me a beer in + * return. Thorsten Schroeder. + * + * NON-MILITARY-USAGE CLAUSE + * Redistribution and use in source and binary form for military use and + * military research is not permitted. Infringement of these clauses may + * result in publishing the source code of the utilizing applications and + * libraries to the public. As this software is developed, tested and + * reviewed by *international* volunteers, this clause shall not be refused + * due to the matter of *national* security concerns. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE DDK PROJECT BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * File: mod0keecrack.c + * Description: Implementation of a KeepassX 2 database password cracker. + */ + + + +#include +#include +#include +#include +#include "helper.h" +#include "mod0keecrack.h" +#include "crypto.h" + +static void usage(char *prog); +static char *kdbx_filename; + +size_t kdbx_headerentries_free(m0_kdbx_header_entry_t *e) +{ + size_t i = 0; + + for(i=0; i HEADERIDCOUNT) { + id = END; + continue; + } + + entries[id].id = id; + + ret = fread(&entries[id].len, sizeof(uint16_t), 1, kdbx_fd); + + if ( ret != 1) + printf("[!] fread(hdrlen) failed."); + + entries[id].data = (uint8_t *)malloc(entries[id].len); + + if(entries[id].data == NULL) { + printf("[!] malloc(entries[id].len) failed."); + break; + } + + ret = fread(entries[id].data, entries[id].len, 1, kdbx_fd); + + if ( ret != 1) + printf("[!] fread(entries[%d].data) failed.", id); + + if( (id == 3) || (id==10) ) { + memcpy(&entries[id].dw, entries[id].data, 4); + memcpy(&entries[id].qw, entries[id].data, 4); + } else if( id == 6 ) { + memcpy(&entries[id].qw, entries[id].data, 8); + } + result++; + + } while (id != END); + + return result; +} + +void kdbx_headerentries_dump(m0_kdbx_header_entry_t *h) +{ + printf("[*] kdbx headerentries:\n"); + printf("[-] END: "); print_hex_buf(h[0].data, h[0].len); puts(""); + printf("[-] COMMENT: "); print_hex_buf(h[1].data, h[1].len); puts(""); + printf("[-] CIPHERID: "); print_hex_buf(h[2].data, h[2].len); puts(""); + printf("[-] COMPRESSIONFLAGS: %08x\n", h[3].dw ); + printf("[-] MASTERSEED: "); print_hex_buf(h[4].data, h[4].len); puts(""); + printf("[-] TRANSFORMSEED: "); print_hex_buf(h[5].data, h[5].len); puts(""); + printf("[-] TRANSFORMROUNDS: %016llx\n", h[6].qw ); + printf("[-] ENCRYPTIONIV: "); print_hex_buf(h[7].data, h[7].len); puts(""); + printf("[-] PROTECTEDSTREAMKEY: "); print_hex_buf(h[8].data, h[8].len); puts(""); + printf("[-] STREAMSTARTBYTES: "); print_hex_buf(h[9].data, h[9].len); puts(""); + printf("[-] INNERRANDOMSTREAMID: %08x\n", h[10].dw ); + return; +} + +size_t kdbx_header_read(FILE *kdbx_fd, m0_kdbx_header_t *header) +{ + size_t ret = 0; + + if (header == NULL) + return 0; + + ret = fread(header, sizeof(m0_kdbx_header_t), 1, kdbx_fd); + if ( ret != 1) + printf("[!] fread(m0_kdbx_header) failed."); + + return ret; +} + +void kdbx_header_dump(m0_kdbx_header_t h) +{ + printf("[*] kdbx header:\n"); + printf("[-] file magic: %08x\n", h.magic); + printf("[-] file identifier: %08x\n", h.identifier); + printf("[-] file minor version: %04x\n", (h.minor_version)); + printf("[-] file major version: %04x\n", (h.major_version)); + return; +} + +size_t kdbx_payload_read(FILE *kdbx_fd, m0_kdbx_payload_t *p) +{ + size_t ret = 0; + size_t payload_len = 0; + off_t off_start = 0; + off_t off_end = 0; + + if (p == NULL) + return 0; + + off_start = ftell(kdbx_fd); + + fseek(kdbx_fd, 0, SEEK_END); + off_end = ftell(kdbx_fd); + fseek(kdbx_fd, off_start, SEEK_SET); + + p->offset_start = off_start; + p->len = (off_end-off_start); + p->encrypted = (uint8_t *)malloc(p->len); + + if(p->encrypted == NULL) { + printf("[!] malloc(payload->encrypted) failed."); + return 0; + } + + memset(p->encrypted, 0, p->len); + + ret = fread(p->encrypted, p->len, 1, kdbx_fd); + if ( ret != 1) + printf("[!] fread(payload) failed."); + + return ret; +} + +void kdbx_payload_dump(m0_kdbx_payload_t p) +{ + printf("[*] kdbx payload:\n"); + printf("[-] payload offset: %llx\n", p.offset_start); + printf("[-] payload len: %x\n", p.len); + + return; +} + +bool kdbx_payload_crack(m0_kdbx_database_t *db, FILE *wordlist_fd) +{ + bool res = false; + char pass[1024] = {0}; + FILE *keyfd = NULL; + uint8_t *key_hash = NULL; + uint8_t *key_data = NULL; + size_t key_len = 0; + int ret = 0; + + // if there is a file named .key, we use this key in addition to the password. + // otherwise, only the password is used to unlock the database. + keyfd = fopen(kdbx_filename, "rb"); + + if (!keyfd) { + printf("[*] Not using keyfile\n"); + key_hash = NULL; + } else { + printf("[*] Using keyfile %s\n", kdbx_filename); + key_hash = (uint8_t *)malloc(32); + if(!key_hash) { + printf("[!] key_hash = malloc(32) failed."); + return false; + } + + fseek(keyfd, 0, SEEK_END); + key_len = ftell(keyfd); + fseek(keyfd, 0, SEEK_SET); + key_data = (uint8_t *)malloc(key_len); + + if(!key_data) { + printf("[!] key_data = malloc(%d) failed.", key_len); + return false; + } + + ret = fread(key_data, key_len, 1, keyfd); + + if ( ret != 1) + printf("[!] fread(key_data) failed."); + + sha256_hash(key_hash, key_data, key_len); + printf("[+] key hash: "); print_hex_buf(key_hash, 32); puts(""); + } + + printf("[*] kdbx crack:\n"); + + if( wordlist_fd == NULL ) + return false; + + while( fgets(pass, sizeof(pass), wordlist_fd) ) { + int len = strlen(pass); + if(len > 0) + pass[len-1] = 0x00; + + res = kdbx_decrypt_payload(db, pass, key_hash); + if(res) { + printf("[*] decryption successful with password %s\n", pass); + break; + } + } + + return res; +} + +bool kdbx_decrypt_payload(m0_kdbx_database_t *db, char *pass, uint8_t *key_hash) +{ + bool res = false; + uint8_t hash[32] = {0}; + uint8_t composite_key[32] = {0}; + uint8_t composite_data[64] = {0}; + uint8_t transform_key[32] = {0}; + uint8_t master_key[32] = {0}; + uint8_t *masterkey_input = NULL; + size_t masterkey_input_len = 0; + + m0_kdbx_header_entry_t *hdr = &db->kdbxheader; + + memset(composite_data, 0, 64); + memset(transform_key, 0, 32); + memset(master_key, 0, 32); + + printf("[+] trying: %s\r", pass); + + sha256_hash(hash, pass, strlen(pass)); + + if(key_hash == NULL) { + sha256_hash(composite_key, hash, sizeof(hash)); + } else { + memcpy(composite_data, hash, sizeof(hash)); + memcpy(composite_data+sizeof(hash), key_hash, sizeof(composite_data)-sizeof(hash)); + sha256_hash(composite_key, composite_data, sizeof(composite_data)); + } + + memcpy(transform_key, composite_key, sizeof(transform_key)); + + // aes_transformkey() is platform specific. + // For Windows, CNG is used and implemented in crypto-ms.c + aes_transformkey(&db->kdbxheader, transform_key, sizeof(transform_key)); + + sha256_hash(transform_key, transform_key, sizeof(transform_key)); + + masterkey_input_len = sizeof(transform_key) + hdr[MASTERSEED].len; + masterkey_input = (uint8_t *)malloc(masterkey_input_len); + + if(masterkey_input_len < hdr[MASTERSEED].len) { + // should never happen, as masterkey len is (currently) 16 bit + puts("[!] masterkey_input len integer overflow."); + return 0; + } + memcpy(masterkey_input, hdr[MASTERSEED].data, hdr[MASTERSEED].len); + memcpy(masterkey_input+hdr[MASTERSEED].len, transform_key, sizeof(transform_key)); + + sha256_hash(master_key, masterkey_input, masterkey_input_len); + + // aes_decrypt_check() is platform specific. + // For Windows, CNG is used and implemented in crypto-ms.c + res = aes_decrypt_check(hdr, master_key, &db->payload); + + return res; +} + +int main(int ac, char** av) +{ + FILE *kdbx_fd = NULL; + FILE *wordlist_fd = NULL; + + char *kdbx_path = NULL; + char *tmp = NULL; + char *wordlist_path = NULL; + size_t filename_len = 0; + + m0_kdbx_database_t kdbx_db = {0}; + + if(ac < 2) + usage(av[0]); + else if(ac > 2) { + // wordlist from file + wordlist_path = av[2]; + } else { + // wordlist == stdin + } + + memset(&kdbx_db, 0, sizeof(kdbx_db)); + + kdbx_path = av[1]; + filename_len = strlen(kdbx_path); + kdbx_filename = (char *) malloc(filename_len + 5); + memset(kdbx_filename, 0, filename_len+5); + + if(filename_len > filename_len+5) + exit(1); + + memcpy(kdbx_filename, kdbx_path, filename_len); + tmp = strrchr(kdbx_filename, '.'); + + if(tmp) + memcpy(tmp, ".key\x00", 5); + else + strcat(kdbx_filename, ".key"); + + printf("[*] using db: %s\n[*] using key: %s\n", kdbx_path, kdbx_filename); + + kdbx_fd = fopen(kdbx_path, "rb"); + + if (!kdbx_fd) { + printf("[!] Can't open kdbx %s\n", kdbx_path); + exit(2); + } + + if(wordlist_path) { + wordlist_fd = fopen(wordlist_path, "r"); + if (!wordlist_fd) { + printf("[!] Can't open wordlist %s\n", wordlist_path); + exit(2); + } + } else { + wordlist_fd = stdin; //fdopen(stdin, "r"); + if (!wordlist_fd) { + printf("[!] Can't open wordlist from stdin\n"); + exit(2); + } + } + + kdbx_header_read(kdbx_fd, &kdbx_db.fileheader); + kdbx_header_dump(kdbx_db.fileheader); + + kdbx_headerentries_read(kdbx_fd, &kdbx_db.kdbxheader); + kdbx_headerentries_dump(&kdbx_db.kdbxheader); + + kdbx_payload_read(kdbx_fd, &kdbx_db.payload); + kdbx_payload_dump(kdbx_db.payload); + + kdbx_payload_crack(&kdbx_db, wordlist_fd); + + kdbx_headerentries_free(&kdbx_db.kdbxheader); + fclose(kdbx_fd); + exit(0); +} + +static void usage(char *prog) +{ + printf("[+] usage: %s ...\n", prog); + exit(1); +} \ No newline at end of file diff --git a/mod0keecrack.h b/mod0keecrack.h new file mode 100755 index 0000000..1b8aa0a --- /dev/null +++ b/mod0keecrack.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2016, mod0keecrack + * Thorsten Schroeder + * + * All rights reserved. + * + * This file is part of mod0keecrack. + * + * "THE BEER-WARE LICENSE" (Revision 42): + * Thorsten Schroeder wrote this file. As long as you + * retain this notice you can do whatever you want with this stuff. If we meet + * some day, and you think this stuff is worth it, you can buy me a beer in + * return. Thorsten Schroeder. + * + * NON-MILITARY-USAGE CLAUSE + * Redistribution and use in source and binary form for military use and + * military research is not permitted. Infringement of these clauses may + * result in publishing the source code of the utilizing applications and + * libraries to the public. As this software is developed, tested and + * reviewed by *international* volunteers, this clause shall not be refused + * due to the matter of *national* security concerns. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE DDK PROJECT BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * File: mod0keecrack.h + * Description: Project header file. Datatypes und function prototypes. + */ + +#ifndef _MOD0KEECRACK_H +#define _MOD0KEECRACK_H + +typedef uintmax_t off_t; + + +enum _m0_kdbx_headerid { + END, + COMMENT, + CIPHERID, + COMPRESSIONFLAGS, + MASTERSEED, + TRANSFORMSEED, // 5 + TRANSFORMROUNDS, + ENCRYPTIONIV, + PROTECTEDSTREAMKEY, + STREAMSTARTBYTES, + INNERRANDOMSTREAMID, // 10 + HEADERIDCOUNT +}; + +typedef enum _m0_kdbx_headerid m0_kdbx_headerid_t; + +typedef struct _m0_kdbx_header_entry { + uint8_t id; + uint16_t len; + uint8_t *data; + uint32_t dw; + uint64_t qw; +} m0_kdbx_header_entry_t; + + +typedef struct _m0_kdbx_header { + uint32_t magic; + uint32_t identifier; + uint16_t minor_version; + uint16_t major_version; +} m0_kdbx_header_t; + +typedef struct _m0_kdbx_payload { + off_t offset_start; + off_t pos; + size_t len; + uint8_t *encrypted; + uint8_t *decrypted; + +} m0_kdbx_payload_t; + +typedef struct _m0kdbx_data { + m0_kdbx_header_t header; + size_t data_len; + uint8_t *data; +} m0_kbdx_data_t; + +typedef struct _m0_kdbx_database { + m0_kdbx_header_t fileheader; + m0_kdbx_header_entry_t kdbxheader; + m0_kdbx_payload_t payload; +} m0_kdbx_database_t; + +// Function prototypes + +size_t kdbx_headerentries_free(m0_kdbx_header_entry_t *); +size_t kdbx_headerentries_read(FILE *, m0_kdbx_header_entry_t *); +void kdbx_headerentries_dump(m0_kdbx_header_entry_t *); + +size_t kdbx_header_read(FILE *, m0_kdbx_header_t *); +void kdbx_header_dump(m0_kdbx_header_t); + +size_t kdbx_payload_read(FILE *, m0_kdbx_payload_t *); +void kdbx_payload_dump(m0_kdbx_payload_t); +bool kdbx_payload_crack(m0_kdbx_database_t *, FILE *); + +bool kdbx_decrypt_payload(m0_kdbx_database_t *, char *, uint8_t *); + +#endif