I have some test data:

  1. Test 1
Text: pass1234
Salt: 33b9d87b83c097ce3ea6e6f84a298f839aafc6d7aa23d909a43ac94bdee35ddf
Hash: 61477724c136fb285918114792685a4d
  1. Test 2
Text: test1234
Salt: 33b9d87b83c097ce3ea6e6f84a298f839aafc6d7aa23d909a43ac94bdee35ddf
Hash: 00281231e8928af48c34ca03e09eebe5
  1. Test 3
Text: simple123
Salt: b68053c65b06b1b322b6cbc53fce1f614eee9366384a12aa01188bdaa8f14ac3
Hash: 0c9e564acfe36f51b54b5050741f351c
  1. Test 4
Test: pass1234
Salt: b68053c65b06b1b322b6cbc53fce1f614eee9366384a12aa01188bdaa8f14ac3
Hash: 0fc692cc78a51a9650c896c735a1b577

They look like MD5 hashes but I could not reproduce them. Does anyone have any idea how to get the algorithm to reproduce these hashes?

  • 1
    Have you access to the asm that produce it ? If not, this is almost impossible to guess what is the hash function. – perror Jul 4 at 7:18
  • you can try sha-256, sha-1, blake, etc...you can do a python script that do that easly – camp0 Jul 4 at 8:04
  • as 0xC0000022L's post below indicates, with the details currently provided, this is less reverse engineering and more an exercise in brute-forcing. Please explain where you got this data from. There isn't anything here that has to do with reverse engineering per-se. Hash cracking and cryptanalysis with insufficient data are not on topic. – julian Jul 4 at 17:09
  • @perror [link] (stackoverflow.com/questions/56880235/…) is what I'm trying to do. I do have access to the binary but I'm not so convenient with asm nor OllyDbg (or IDA Pro) – user11703733 Jul 4 at 23:22
  • Thanks @0xC0000022L for the the answer with a nice script. It really helps me brute force these hashes – user11703733 Jul 4 at 23:29

Lots of possibilities, for all we know there's a chance that some "other" salt is used or that either the password or the salt or both are preprocessed in some way. Additionally there could be multiple rounds of hashing one of the combinations ...

So this question literally requires looking at the code and therefore reverse code engineering to give you more than some wild guess.

I tried the most obvious cases and there was no match (tested with DSA, DSA-SHA, MD4, MD5, RIPEMD160, SHA, SHA1, SHA224, SHA256, SHA384, SHA512, dsaEncryption, dsaWithSHA, ecdsa-with-SHA1, md4, md5, ripemd160, sha, sha1, sha224, sha256, sha384, sha512, whirlpool):

#!/usr/bin/env python3
from hashlib import new as hashnew, algorithms_available

# Several possibilities
# - assuming the password is ASCII and the calculated hash is the hex
#   representation of the digest (or parts thereof)
#   1. the salt could be used as ASCII string
#   2. as array of bytes of 32 bytes size
#   3. some other nondescript way
# - Salt could be appended or prepended
# - Output could be part of the hex digest of some hash algo that yields
#   larger digests than MD5
DATA = [
    ("pass1234", "33b9d87b83c097ce3ea6e6f84a298f839aafc6d7aa23d909a43ac94bdee35ddf", "61477724c136fb285918114792685a4d"),
    ("test1234", "33b9d87b83c097ce3ea6e6f84a298f839aafc6d7aa23d909a43ac94bdee35ddf", "00281231e8928af48c34ca03e09eebe5"),
    ("simple123", "b68053c65b06b1b322b6cbc53fce1f614eee9366384a12aa01188bdaa8f14ac3", "0c9e564acfe36f51b54b5050741f351c"),
    ("pass1234", "b68053c65b06b1b322b6cbc53fce1f614eee9366384a12aa01188bdaa8f14ac3", "0fc692cc78a51a9650c896c735a1b577"),

results = {}
print("Testing", ", ".join(sorted(algorithms_available)))
# Go through supported hash algos
for algo in sorted(algorithms_available):
    for password, salt, expected in DATA:
        cases = []
        # password + salt
        cases.append(password.encode('ascii') + salt.encode('ascii'))
        # salt + password
        cases.append(salt.encode('ascii') + password.encode('ascii'))
        # password + bytes(salt)
        cases.append(password.encode('ascii') + bytes.fromhex(salt))
        # bytes(salt) + password
        cases.append(bytes.fromhex(salt) + password.encode('ascii'))
        reslist = []
        for case in cases:
            h = hashnew(algo, case)
            hexd = h.hexdigest()
            if expected.lower() in hexd.lower():
                highlight = hexd.lower().replace(expected.lower(), "[%s]" % (expected.lower()))
                print("Match for algorithm %s: %s" % (algo, highlight))

Admittedly a naïve approach, but as you can see just from this, there's a multitude of possibilities in which the password and salt can be represented and combined and there are a multitude of hash algorithms to test.

Given the above did not include BLAKE2, I'd strongly recommend testing that one as well.

Additionally I'd like to draw your attention to key derivation algorithms like those supported in hashlib: pbkdf2_hmac and scrypt.

Anyway, short of brute-forcing (my above attempt and variations on that) you won't get around looking at the actual code. For starters you may be able to figure out the algorithm used by certain signatures. But moreover you may find out ways by which the password, the salt or both are mutated prior to the hashing.

And considering key derivation algorithms the fact that you can run them an arbitrary number of iterations provides for another "dimension" in the permutations possible ...

Not the answer you're looking for? Browse other questions tagged or ask your own question.