.NET SHA256Cng (SHA256 Bcrypt?)
#1
Hi All, I'm looking to run hashes from an application I manage - decompiling the crypto dlls shows me that it uses the SHA256CNG Class from Microsoft .NET.


https://learn.microsoft.com/en-us/dotnet...work-4.8.1

Reading the article it says:
Quote:Provides a Cryptography Next Generation (CNG) implementation of the Secure Hash Algorithm (SHA) for 256-bit hash values.
...
It uses the BCrypt (BestCrypt) layer CNG.

I'm assuming this is similar to m28400 bcrypt(sha512) but with sha256?
Also the salt seems quite long, when converted from Base64 the salt is 96 bits and hash is 256 bits.

Any idea if hashcat modes can cater for this?
Reply
#2
Here's an example hash generated in the application -  password is 'hashcat'

Code:
3tKJrhwSwvp1TG0w:s+ILzfJ6MOymVTnmeQAa2iDEoEeRdlu0MmWnzyADlvU=

From the decompilation:

Code:
using (HashAlgorithm hA = (HashAlgorithm) new SHA256Cng())

        return Convert.ToBase64String(hA.ComputeHash(Encoding.Unicode.GetBytes(salt + ":" + pw)));

Salt is generated from 12 random bytes (96b).

Running base64 -> hex on each part gives:

Code:
ded289ae1c12c2fa754c6d30

b3e20bcdf27a30eca65539e679001ada20c4a04791765bb43265a7cf200396f5
Reply
#3
The SHA256Cng is just the OS 'fast' way of creating a sha256 hash. Nothing weird is happening in regards to BCrypt.

I think some parts of the code are missing that perhaps alter or change the salt or password. Using this basic .Net code I do not get the same result:

Code:
using System;
using System.Security.Cryptography;
using System.Text;

public class Program
{
public static void Main()
{
byte[] salt = Convert.FromBase64String("3tKJrhwSwvp1TG0w");
byte[] pw = Convert.FromBase64String("aGFzaGNhdA=="); // string pw = "hashcat";
using (HashAlgorithm hA = (HashAlgorithm) new SHA256Cng())
        Console.WriteLine( Convert.ToBase64String(hA.ComputeHash(Encoding.Unicode.GetBytes(salt + ":" + pw))) );
}
}

result: 3MSU+bx67fropKer+3n6xBNdtL5MMgVqtE0diKiyWc8= and not s+ILzfJ6MOymVTnmeQAa2iDEoEeRdlu0MmWnzyADlvU=

You can run it at https://dotnetfiddle.net/V9crKz

Perhaps somewhere in the code the pw is modified or represented in a different way. Without the rest of the code it is hard to know how to crack this sha256 hash.
Reply
#4
(03-25-2024, 10:11 AM)DanielG Wrote: You can run it at https://dotnetfiddle.net/V9crKz

Perhaps somewhere in the code the pw is modified or represented in a different way. Without the rest of the code it is hard to know how to crack this sha256 hash.

Thanks DanielG - dotnetfiddle is a great way to play. I've extracted the full structure of the hashing and implemented it here:
https://dotnetfiddle.net/5kZo1a

It looks like it is hashing 'salt;pw' - and this now correctly represents the hash made from the application.
Code:
HashPassword with pw:hashcat salt:3tKJrhwSwvp1TG0w
1;3tKJrhwSwvp1TG0w;s+ILzfJ6MOymVTnmeQAa2iDEoEeRdlu0MmWnzyADlvU=
Reply
#5
Of course I attempted the crack with m1420 and candidate ';hashcat' but it appears to be not that simple Big Grin
Reply
#6
Ah yes, it seems that they don't first decode the salt from base64.

The annoying thing is that 'Encoding.Unicode.GetBytes' returns what looks like a UTF-16 representation of the data. As a byte array the code 'Encoding.Unicode.GetBytes(salt + ";" + pw)' returns:

Code:
51, 0, 116, 0, 75, 0, 74, 0, 114, 0, 104, 0, 119, 0, 83, 0, 119, 0, 118, 0, 112, 0, 49, 0, 84, 0, 71, 0, 48, 0, 119, 0, 59, 0, 104, 0, 97, 0, 115, 0, 104, 0, 99, 0, 97, 0, 116, 0

So a null byte after each character, if you would to hash that in something else such as hashcat you will need to compensate for that. I don't know if hashcat has an easy way to transform password candidates to utf-16 beforehand.

As you can see on https://gchq.github.io/CyberChef/#recipe...IDExNiwgMA taking a sha256 hash from that array of bytes creates the correct value (b3e20bcdf27a30eca65539e679001ada20c4a04791765bb43265a7cf200396f5)
Reply
#7
Turns out hashcat does have a mode using utf16le. Mode 1440 = sha256($salt.utf16le($pass)). It does not however encode the salt for you, this must be done manually (https://gchq.github.io/CyberChef/#recipe...nAxVEcwdzs)

Code:
hashcat --hex-salt -a 3 -m 1440 "b3e20bcdf27a30eca65539e679001ada20c4a04791765bb43265a7cf200396f5:330074004b004a007200680077005300770076007000310054004700300077003b00" "hashca?l"

cracks the password
Reply
#8
(03-25-2024, 02:37 PM)DanielG Wrote: Turns out hashcat does have a mode using utf16le. Mode 1440 = sha256($salt.utf16le($pass)). It does not however encode the salt for you, this must be done manually (https://gchq.github.io/CyberChef/#recipe...nAxVEcwdzs)

Code:
hashcat --hex-salt -a 3 -m 1440 "b3e20bcdf27a30eca65539e679001ada20c4a04791765bb43265a7cf200396f5:330074004b004a007200680077005300770076007000310054004700300077003b00" "hashca?l"

cracks the password

Thanks so much for looking at this Daniel - that's incredible and I can script the rest - I can now remove wordlist/simple passwords from my systems.

PS: CyberChef is a pretty amazing tool too, thanks!
Reply