AxCrypt v2
#6
I have a nice update for you.

I just took some free time to have a quick glance on the JTR (John The Ripper) implementation of AxCrypt 2 and it seems the algorithm of AxCrypt 2 is pretty straight forward.

I've now coded a perl POC (proof of concept) axcrypt2.pl to demonstrate how the "cracking" would look like (please don't blame me for that bad code, it's just a quick test):
Code:
#!/usr/bin/env perl

# Author: philsmd
# Date: August 2020
# License: public domain, credits go to philsmd and hashcat

# AxCrypt 2 with AES-256 encryption

use warnings;
use strict;

use Crypt::PBKDF2;
use Crypt::Mode::ECB;

#
# Constants:
#

my $AXCRYPT_MAGIC = pack ("H*", "a6a6a6a6a6a6a6a6");

#
# Example:
#

# Example 1:

# $axcrypt$*2*28200*96fca6b5aff19cb540125e6452f1ab6e1cbf7097ad75326e7aa1726f687ed18e66a63295d735f458a138901be41d95d29ff760c7c4b4178320251f2ab0ecabd8*d1d90c425fd8e2d20b2aa7ef6f3ab9dcefad84917f9e07f65f8da61e7e84f490ba8007179718ce0033cbc887177c2b51ed00e88155741960ab667a5328f305969518bc436ee1ba28126a5be79b0b90f8a9c8a438cba9d0e59c0b6573cde124a8300a6fb01ff857485d302285f1eacd7f08d9cc70ec9fdf412b60bc5a728b5108ef8bda24caee5ab7cc4376951c080c6d*1000*fead8792ea352979ab19e7b287bf709f39df0706a7e460b5271d1ebc71014b3b:openwall

my $pass      = "openwall";
my $iter_wrap = 28200;
my $salt_wrap = pack ("H*", "96fca6b5aff19cb540125e6452f1ab6e1cbf7097ad75326e7aa1726f687ed18e66a63295d735f458a138901be41d95d29ff760c7c4b4178320251f2ab0ecabd8");
my $data      = pack ("H*", "d1d90c425fd8e2d20b2aa7ef6f3ab9dcefad84917f9e07f65f8da61e7e84f490ba8007179718ce0033cbc887177c2b51ed00e88155741960ab667a5328f305969518bc436ee1ba28126a5be79b0b90f8a9c8a438cba9d0e59c0b6573cde124a8300a6fb01ff857485d302285f1eacd7f08d9cc70ec9fdf412b60bc5a728b5108ef8bda24caee5ab7cc4376951c080c6d");
my $iter_kdf = 1000;
my $salt_kdf = pack ("H*", "fead8792ea352979ab19e7b287bf709f39df0706a7e460b5271d1ebc71014b3b");


# Example 2:

# $axcrypt$*2*23652*8817291e0611409390c50a8bdc99a98bf56d393174d7c177082391f7919ed392a701783790ad2eed49139ede2b1546dc4a9aaa142e2b2530b4c82cff03df18b1*2561a0c3f5e166c7273ea6fb59592a58b8d8235a379c82de39fc6d674291b6a25a268732c34eab1b092166ca4f9ef9e383325b90633896890f7dca4d29876ec5bb232ff89c8130aad917f93d9228a091a9996e1f14d4b130b5aad7516c11aa9143730d7b0ec8168b4d83bdd0ca1a9a36784572b9db992bd13289ecd577a421ded0576801e88c7275b2d5fa8eb7e540cb*1000*3dc38e68204a7060c3cd616ffcf6df17dbbb3c199e67ea85c7e29751b9ea2fc2:openwall123

# my $pass      = "openwall123";
# my $iter_wrap = 23652;
# my $salt_wrap = pack ("H*", "8817291e0611409390c50a8bdc99a98bf56d393174d7c177082391f7919ed392a701783790ad2eed49139ede2b1546dc4a9aaa142e2b2530b4c82cff03df18b1");
# my $data      = pack ("H*", "2561a0c3f5e166c7273ea6fb59592a58b8d8235a379c82de39fc6d674291b6a25a268732c34eab1b092166ca4f9ef9e383325b90633896890f7dca4d29876ec5bb232ff89c8130aad917f93d9228a091a9996e1f14d4b130b5aad7516c11aa9143730d7b0ec8168b4d83bdd0ca1a9a36784572b9db992bd13289ecd577a421ded0576801e88c7275b2d5fa8eb7e540cb");
# my $iter_kdf = 1000;
# my $salt_kdf = pack ("H*", "3dc38e68204a7060c3cd616ffcf6df17dbbb3c199e67ea85c7e29751b9ea2fc2");


#
# Start:
#

my $pbkdf2 = Crypt::PBKDF2->new
(
  hasher     => Crypt::PBKDF2->hasher_from_algorithm ('HMACSHA2', 512),
  iterations => $iter_kdf,
  output_len => 64
);

# most heavy part (PBKDF2-HMAC-SHA512):

my $KEK = $pbkdf2->PBKDF2 ($salt_kdf, $pass);

# reduce 64 bytes of key to 32 bytes (why not just use 32 byte output length o.O ?)

$KEK = substr ($KEK,  0, 32) ^ substr ($KEK, 32, 32);

$KEK = $KEK ^ substr ($salt_wrap, 0, 32);

my $aes = Crypt::Mode::ECB->new ('AES', 0);


# unwrap:

for (my $j = $iter_wrap - 1; $j >= 0; $j--)
{
  for (my $k = 6; $k >= 1; $k--)
  {
    my $idx = 6 * $j + $k;

    my $block =  substr ($data,      0, 4) .
                (substr ($data,      4, 4) ^ pack ("L>", $idx)) .
                 substr ($data, $k * 8, 8);

    $block = $aes->decrypt ($block, $KEK);

    substr ($data,      0, 8) = substr ($block, 0, 8);
    substr ($data, $k * 8, 8) = substr ($block, 8, 8);
  }
}

#
# Verify:
#

if (index ($data, $AXCRYPT_MAGIC) == 0)
{
  print "Password found: '$pass'\n";

  exit (0);
}

exit (1);

so it's just PBKDF2-HMAC-SHA512 with a 64 byte output and a custom AES unwrapping code.


Some things are still unknown to me... axcrypt2john.py has a comment about AES-256 and that other ciphers could be used too (https://github.com/magnumripper/JohnTheR...ohn.py#L20).

We should really make sure that your target hash uses that AES-256 option and maybe also investigate which other ciphers would be allowed by AxCrypt (except from AES-256).

Could you also mention these new discoveries over https://github.com/hashcat/hashcat/issues/2510 (about the algorithm details ) ?

The github issue that was created by you is https://github.com/hashcat/hashcat/issues/2510 (just as a reference also here for the forum).
Reply


Messages In This Thread
AxCrypt v2 - by lapolis - 08-11-2020, 08:46 AM
RE: AxCrypt v2 - by philsmd - 08-11-2020, 09:43 AM
RE: AxCrypt v2 - by lapolis - 08-11-2020, 10:13 AM
RE: AxCrypt v2 - by philsmd - 08-11-2020, 10:51 AM
RE: AxCrypt v2 - by lapolis - 08-11-2020, 10:56 AM
RE: AxCrypt v2 - by philsmd - 08-11-2020, 02:45 PM
RE: AxCrypt v2 - by philsmd - 08-12-2020, 12:17 AM
RE: AxCrypt v2 - by lapolis - 08-12-2020, 08:32 AM
RE: AxCrypt v2 - by philsmd - 08-12-2020, 09:04 AM
RE: AxCrypt v2 - by lapolis - 08-12-2020, 09:37 AM
RE: AxCrypt v2 - by philsmd - 08-12-2020, 11:51 AM
RE: AxCrypt v2 - by lapolis - 08-12-2020, 12:56 PM
RE: AxCrypt v2 - by TomM - 08-12-2020, 03:57 PM
RE: AxCrypt v2 - by philsmd - 08-12-2020, 05:04 PM
RE: AxCrypt v2 - by lapolis - 08-12-2020, 06:32 PM
RE: AxCrypt v2 - by philsmd - 08-14-2020, 11:06 AM
RE: AxCrypt v2 - by lapolis - 08-15-2020, 05:39 AM
RE: AxCrypt v2 - by philsmd - 08-18-2020, 10:55 AM