Created
December 7, 2016 22:36
-
-
Save korc/81358735de3b2fa8cf14f109453bb957 to your computer and use it in GitHub Desktop.
~/.ssh/known_hosts bruteforcer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import Crypto.Hash.SHA, Crypto.Hash.HMAC | |
import sys, re, os | |
import getopt | |
import time | |
kh_re=re.compile(r'^\|1\|(?P<salt>[a-zA-Z0-9/+]+=*)\|(?P<hash>[a-zA-Z0-9/+]+=*) (?P<keytype>\S+) (?P<hostkey>[a-zA-Z0-9/+]+=*)$') | |
def read_kh(fname): | |
ret=[] | |
with open(fname) as kh: | |
for idx,line in enumerate(kh): | |
match=kh_re.match(line) | |
if not match: continue | |
item=match.groupdict() | |
item["index"]=idx | |
item['hmac']=Crypto.Hash.HMAC.new(item["salt"].decode("base64"), digestmod=Crypto.Hash.SHA) | |
item["hmac_target"]=item["hash"].decode("base64") | |
ret.append(item) | |
return ret | |
def find_key(test_key, known_hosts): | |
for row in known_hosts: | |
hmac=row["hmac"].copy() | |
hmac.update(test_key) | |
if hmac.digest()==row["hmac_target"]: | |
return row | |
def charrange(start,end): | |
return ''.join(map(chr,range(ord(start),ord(end)+1))) | |
class CharGen(object): | |
__slots__=['alphabet','index','maxlen','maxindex','result_converter'] | |
def __init__(self,alphabet=charrange('a','z'), maxlen=None, maxindex=None): | |
self.alphabet=alphabet | |
self.index=1 | |
self.maxlen=maxlen | |
self.maxindex=maxindex | |
self.result_converter=self.join_str | |
def __iter__(self): | |
while True: | |
y=self.get_value_by_index(self.index) | |
if self.maxlen is not None and len(y)>self.maxlen: break | |
if self.maxindex is not None and self.index>self.maxindex: break | |
yield y | |
self.index+=1 | |
def reset(self): self.index=0 | |
def get_value(self): return self.get_value_by_index(self.index) | |
def set_value(self, v): self.index=int(v) | |
value=property(get_value, set_value) | |
@staticmethod | |
def join_str(val): return ''.join(val) | |
def get_value_by_index(self,i): | |
if i<1: raise ValueError,"Index must be a positive integer" | |
div=i | |
ret=[] | |
while True: | |
div=div-1 | |
div,mod=divmod(div,len(self.alphabet)) | |
ret.insert(0,self.alphabet[mod]) | |
if div==0: break | |
return self.result_converter(ret) | |
class IPGen(object): | |
max_value=(1<<32)-1 | |
def get_value(self): | |
return self.__value | |
def set_value(self, val): | |
if isinstance(val, basestring): | |
val=reduce(lambda a,b: (a<<8) + int(b), val.split("."), 0) | |
self.__value=val | |
value=property(get_value, set_value) | |
def __init__(self, init_value="1.0.0.0"): | |
self.value=init_value | |
def __str__(self): | |
return ".".join(map(lambda z: str(0xff&(self.value>>z)), [24, 16, 8, 0])) | |
def __iter__(self): | |
while True: | |
yield str(self) | |
self.value+=1 | |
if self.value>self.max_value: | |
break | |
if __name__=='__main__': | |
opts,args=getopt.getopt(sys.argv[1:], "is:f:h?") | |
gen_cls=CharGen | |
gen_start=None | |
kh_fname=os.path.expanduser("~/.ssh/known_hosts") | |
for opt,arg in opts: | |
if opt=="-i": gen_cls=IPGen | |
elif opt=="-s": gen_start=arg | |
elif opt=="-f": kh_fname=arg | |
elif opt in ("-h", "-?"): | |
print """Usage: %s [-f <known_hosts>] [-i] [-s <start_ip>] [test_names..] | |
-i makes bruteforcer use IP addresses | |
"""%(os.path.basename(sys.argv[0],)) | |
raise SystemExit(0) | |
kh=read_kh(kh_fname) | |
tests=args | |
if not tests: | |
tests=gen_cls() | |
if gen_start is not None: | |
tests.value=gen_start | |
tm_start=time.time() | |
for k in tests: | |
tm_diff=time.time()-tm_start | |
if tm_diff>1: print "\x1b[Ktesting: %r .."%(k), | |
m=find_key(k, kh) | |
if m: | |
print "found", repr(k), "at line", m["index"]+1, "hash:", m["hash"] | |
kh=filter(lambda x: not x["hash"]==m["hash"], kh) | |
if not kh: | |
print "End of known_hosts" | |
break | |
else: | |
if tm_diff>1: | |
print "not found\r", | |
sys.stdout.flush() | |
if tm_diff>1: | |
tm_start=time.time() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment