Im interested in brute-forcing known_hosts files for SSH, these look like this:
|[int]|[base64 SALT]|[base64 TARGET] ssh-rsa [base64]
These are SHA1_HMACs of the IP address or hostname where the Text (not the salt or key) is the password. (The Int at the beginning of the string defines the type of SHA hash e.g. 1, 256, 512).
e.g. if hmac.new(SALT, GUESS, sha1).digest() == TARGET then you have a match.
Hashcat has the modes 150 and 160 but nothing for unknown Text. Would it be hard to add support for this? I think it has some valuable uses when identifying hosts to move laterally within networks.
What do you mean by "unknown text"? What is the technical difference to a password?
For the example below:
#|1|cISUEz2xxa7ZeaVeGBzNjHRF5tU=|Td1EXemzcxAGovyEkvHYUx+UorQ= rsa-key blahblah
If we convert to hex we have:
17513529ea04fde116862d745a91afe0e7623ba6:dfdf3c415d1513cc2664beecb8dad840b2132c28
In this case the output of the hmac is known dfdf3c415d1513cc2664beecb8dad840b2132c28 and the key used is known 17513529ea04fde116862d745a91afe0e7623ba6 but I dont know the text that was hmac'd (in this case 192.168.1.61)
isn't that just the same as hmac-sha1(key = $pass)?
edit: according to the argument order of hmac it should probably be hmac-sha1(key = $salt)
I dont think so but I could be completely mis-reading this. I have the key (17513529ea04fde116862d745a91afe0e7623ba6) but I dont know the plain text that was hmac'd (192.168.1.61) - its the plain text I want to brute-force
If it helps this is what I used to brute-force it in python (where tkey.txt) contains:
|1|F1E1KeoE/eEWhi10WpGv4OdiO6Y=|3988QV0VE8wmZL7suNrYQLITLCg= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgwCZx9lGaY+Zhz98TdWqZ01mTzOwRnQO0EIBM8Hx8olxMbrQ1Xa+x/7LBoGyJqeYFunZbFCVpAu+2SBkvf75qV8nTlq3WXnLnprsH5Sq/c9f29ZCcMHevI
Python:
import base64
import hmac
from hashlib import sha1
if __name__ == '__main__':
for kh in open("tkey.txt"):
print (kh.strip())
parts = kh.strip().split("|")
if len(parts) < 2:
continue
saltb64 = parts[2]
targetb64 = parts[3].split(" ")[0]
salt = base64.b64decode(saltb64)
target = base64.b64decode(targetb64)
for a in ["192"]:
for b in range(160, 256):
print(b) # For debugging
for c in range(0, 256):
for d in range(0, 256):
message = bytes("%s.%s.%s.%s" % (a,b,c,d), "ascii")
hashed = hmac.new(salt, message, sha1).digest()
if target == hashed:
print("%s|%s -> %s" % (salt.hex(), target.hex(), message))
print("%s|%s -> %s" % (saltb64, targetb64, message))
quit()
you should be able to crack this by using
dfdf3c415d1513cc2664beecb8dad840b2132c28:17513529ea04fde116862d745a91afe0e7623ba6 --hex-salt -m 160
Ah, thanks
I was missing --hex-salt
dfdf3c415d1513cc2664beecb8dad840b2132c28:17513529ea04fde116862d745a91afe0e7623ba6:192.168.1.61
Heres a IPv4 hcmask if anyone is in the same situation.
python3 parse_knownhosts.py.txt .ssh/known_hosts > unknown
dfdf3c415d1513cc2664beecb8dad840b2132c28:17513529ea04fde116862d745a91afe0e7623ba6
hashcat -m 160 --hex-salt -m 160 unknown -a 3 ipv4.hcmask.txt
Ah nice, I found it slower to process all of those rules for a single hash - I guess it'd be faster for longer lists tho?