first commit
This commit is contained in:
commit
716e1154fa
8 changed files with 1326 additions and 0 deletions
111
README.md
Executable file
111
README.md
Executable file
|
@ -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 <keepassx-file.kdbx> [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 <databasename>.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):
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
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!
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
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__`
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
* Copyright (c) 2016, mod0keecrack
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch>
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of mod0keecrack.
|
||||||
|
*
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch> 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.
|
||||||
|
</pre>
|
||||||
|
|
348
crypto-ms.c
Executable file
348
crypto-ms.c
Executable file
|
@ -0,0 +1,348 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016, mod0keecrack
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch>
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of mod0keecrack.
|
||||||
|
*
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch> 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 <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <bcrypt.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
46
crypto.h
Executable file
46
crypto.h
Executable file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016, mod0keecrack
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch>
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of mod0keecrack.
|
||||||
|
*
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch> 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
|
61
genwords.py
Executable file
61
genwords.py
Executable file
|
@ -0,0 +1,61 @@
|
||||||
|
#!python
|
||||||
|
# *
|
||||||
|
# * Copyright (c) 2016, mod0keecrack
|
||||||
|
# * Thorsten Schroeder <ths at modzero dot ch>
|
||||||
|
# *
|
||||||
|
# * All rights reserved.
|
||||||
|
# *
|
||||||
|
# * This file is part of mod0keecrack.
|
||||||
|
# *
|
||||||
|
# * "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
# * Thorsten Schroeder <ths at modzero dot ch> 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 <fmt>" % sys.argv[0])
|
||||||
|
print("[-] e.g. %s 'Secrets%%04d!'" % sys.argv[0])
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
|
155
helper.c
Executable file
155
helper.c
Executable file
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016, mod0keecrack
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch>
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of mod0keecrack.
|
||||||
|
*
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch> 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 <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
82
helper.h
Executable file
82
helper.h
Executable file
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016, mod0keecrack
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch>
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of mod0keecrack.
|
||||||
|
*
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch> 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 <stdint.h>
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* 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
|
410
mod0keecrack.c
Executable file
410
mod0keecrack.c
Executable file
|
@ -0,0 +1,410 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016, mod0keecrack
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch>
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of mod0keecrack.
|
||||||
|
*
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch> 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 <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;i++) {
|
||||||
|
|
||||||
|
if(e[i].data != NULL) {
|
||||||
|
free(e[i].data);
|
||||||
|
memset(&e[i], 0, sizeof(m0_kdbx_header_entry_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t kdbx_headerentries_read(FILE *kdbx_fd, m0_kdbx_header_entry_t *entries)
|
||||||
|
{
|
||||||
|
size_t ret = 0;
|
||||||
|
size_t result = 0;
|
||||||
|
|
||||||
|
uint8_t id = 0;
|
||||||
|
|
||||||
|
if (entries == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
// headers have variable lengths.
|
||||||
|
// we need to read: [1 byte hdr-id] [1 word data-len] [data-len bytes of value]
|
||||||
|
// if hdr-id == 0x00: header ends, encrypted payload starts.
|
||||||
|
|
||||||
|
ret = fread(&id, sizeof(uint8_t), 1, kdbx_fd);
|
||||||
|
|
||||||
|
if ( ret != 1)
|
||||||
|
printf("[!] fread(id) failed.");
|
||||||
|
|
||||||
|
if(id > 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 <databasename>.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 <keepassx-file.kdbx> ...\n", prog);
|
||||||
|
exit(1);
|
||||||
|
}
|
113
mod0keecrack.h
Executable file
113
mod0keecrack.h
Executable file
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016, mod0keecrack
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch>
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This file is part of mod0keecrack.
|
||||||
|
*
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* Thorsten Schroeder <ths at modzero dot ch> 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
|
Loading…
Reference in a new issue