Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Tue, 10 Sep 2019 20:59:32 +1000
From: Marcin Gębarowski <>
Subject: Re: SHA256(XOR(salt+pass, key))

On 9/09/2019 16:09, magnum wrote:
> On 2019-09-07 15:05, Marcin Gębarowski wrote:
>> Looking for help with using john to crack the hashes I got, the 
>> application creates them as follows:
>> SHA256(XOR(salt + pass, key))
>> Salt and key are both 32 bytes long. I have the key. Hashes are stored 
>> in format:
>> base64(salt + hash)
>> but I can easily change that to anything else.
>> The main problem I'm having is the XOR function, which I was unable to 
>> find in dynamic scripts library. Having something like:
>> sha256(xor($s.$p, $key))
>> as dynamic script would definitely solve this...
> So is key like a 2nd (fixed) salt (pepper)? What application is that? 
> I'm sure Jim could add XOR to dynamic compiler format with ease. Can you 
> post a sample or two with known pass and key that we can use as test 
> vectors?
> There's a minor optimization possible - we could save state of SHA256 
> after the first 8 rounds with a given salt, and reuse that for as many 
> password candidates we like.
> magnum

Hi Magnum,
Unfortunately I cannot disclose the name of the application and any 
specifics about it. It's a thick client connecting to a database.
The key, whatever we call it, is used to XOR salt and the password 
(pepper kinda makes sense). I'll go through whole process below.


Hash (providing both in Base64 and HEX form, the database contains 
Base64 form):

or in hex form:

If above is translated into admin:salt:hash it turns into (salt is the 
first half of whole hash):

Hardcoded XOR key:

To check the hash the application does the following:

1. Salt value is extracted:

0000h: 24 07 4B 87 48 DE AD 0B 61 9B 6B 52 AD F1 58 8D  $.K‡HÞ­.a›kR­ñX
0010h: EE 3F EC 01 AF 73 C3 48 84 34 4D 71 46 65 76 59  î?ì.¯sÃH„4MqFevY

2. Provided password is appended to it:

0000h: 24 07 4B 87 48 DE AD 0B 61 9B 6B 52 AD F1 58 8D  $.K‡HÞ­.a›kR­ñX
0010h: EE 3F EC 01 AF 73 C3 48 84 34 4D 71 46 65 76 59  î?ì.¯sÃH„4MqFevY
0020h: 53 65 63 72 65 74 50 40 73 73 77 30 72 64        SecretP@...0rd

3. Resulting data is XORed with hardcoded key:

0000h: A5 4F AD A4 33 CA BF F1 B4 30 4A 91 FD 73 6E B6  ¥O­¤3Ê¿ñ´0J‘ýsn¶
0010h: 93 60 9C 02 01 42 94 56 92 80 9B 1D A1 A9 95 C1  “`œ..B”V’€›.¡©•Á
0020h: D2 2D 85 51 1E 60 42 BA A6 D8 56 F3 22 E6        Ò-…Q.`Bº¦ØVó"æ

4. This goes through SHA256 giving:


As can be seen the resulting hashes are the same.

Other credentials and their hashes (same XOR key used):



I imagine the dynamic format for cracking these would look something like:


Please treat above as pseudocode, I'm new to the dynamic formats and not 
aware how HEX data is passed to them. Of course above could be changed into:

sha256(xor($s, $c1).xor($p, 

which most likely would do better performance-wise.

Let me know if you have any further questions.


Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.