123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466 |
- #!/usr/bin/python
- # -*- coding: iso-8859-15 -*-
- """
- This file is part of the cintruder project, http://cintruder.03c8.net
- Copyright (c) 2012/2016 psy <epsylon@riseup.net>
- cintruder is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation version 3 of the License.
- cintruder is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- details.
- You should have received a copy of the GNU General Public License along
- with cintruder; if not, write to the Free Software Foundation, Inc., 51
- Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- """
- import os, traceback, hashlib, sys, time, socket, urlparse
- import platform, subprocess, re, webbrowser
- from core.options import CIntruderOptions
- from core.crack import CIntruderCrack
- from core.ocr import CIntruderOCR
- from core.curl import CIntruderCurl
- from core.xml_export import CIntruderXML
- from core.update import Updater
- from urlparse import urlparse
- # set to emit debug messages about errors (0 = off).
- DEBUG = 0
- class cintruder():
- """
- CIntruder application class
- """
- def __init__(self):
- self.captcha = ""
- self.optionOCR = []
- self.optionCrack = []
- self.optionParser = None
- self.optionCurl = None
- self.options = None
- self.word_sug = None
- self.train == 0
- self.crack == 0
- self.ignoreproxy = 1
- self.isurl = 0
- self.os_sys = platform.system()
- self._webbrowser = webbrowser
- def set_options(self, options):
- """
- Set cintruder options
- """
- self.options = options
- def create_options(self, args=None):
- """
- Create the program options for OptionParser.
- """
- self.optionParser = CIntruderOptions()
- self.options = self.optionParser.get_options(args)
- if not self.options:
- return False
- return self.options
- def set_webbrowser(self, browser):
- self._webbrowser = browser
- def banner(self):
- print '='*75
- print ""
- print " o8%8888, "
- print " o88%8888888. "
- print " 8'- -:8888b "
- print " 8' 8888 "
- print " d8.-=. ,==-.:888b "
- print " >8 `~` :`~' d8888 "
- print " 88 ,88888 "
- print " 88b. `-~ ':88888 "
- print " 888b \033[1;31m~==~\033[1;m .:88888 "
- print " 88888o--:':::8888 "
- print " `88888| :::' 8888b "
- print " 8888^^' 8888b "
- print " d888 ,%888b. "
- print " d88% %%%8--'-. "
- print " /88:.__ , _%-' --- - "
- print " '''::===..-' = --. `\n"
- print self.optionParser.description, "\n"
- print '='*75
- @classmethod
- def try_running(cls, func, error, args=None):
- """
- Try running a function and print some error if it fails and exists with
- a fatal error.
- """
- args = args or []
- try:
- return func(*args)
- except Exception:
- print(error, "error")
- if DEBUG:
- traceback.print_exc()
- def get_attack_captchas(self):
- """
- Get captchas to brute force
- """
- captchas = []
- options = self.options
- p = self.optionParser
- if options.train:
- print('='*75)
- print(str(p.version))
- print('='*75)
- print("Starting to 'train'...")
- print('='*75)
- captchas = [options.train]
- if options.crack:
- print('='*75)
- print(str(p.version))
- print('='*75)
- print("Starting to 'crack'")
- print('='*75)
- captchas = [options.crack]
- if options.track:
- print('='*75)
- print(str(p.version))
- print('='*75)
- print("Tracking captchas from url...")
- print('='*75+"\n")
- captchas = [options.track]
- return captchas
- def train(self, captchas):
- """
- Learn mode:
- + Add words to the brute forcing dictionary
- """
- self.train_captcha(captchas)
- def train_captcha(self, captcha):
- """
- Learn mode:
- 1- Apply OCR to captcha/image and split into unities
- 2- Human-Recognize that unities like alphanumeric words (gui supported)
- 3- Move that words into dictionary (gui supported)
- """
- options = self.options
- # step 1: applying OCR techniques
- if options.name: # with a specific OCR module
- print "[Info] Using module: [", options.name, "]"
- try:
- sys.path.append('mods/%s/'%(options.name))
- exec("from " + options.name + "_ocr" + " import CIntruderOCR") # import module
- except Exception:
- print "\n[Error] '"+ options.name+ "' module not found!\n"
- return #sys.exit(2)
- if options.setids: # with a specific colour ID
- setids = int(options.setids)
- if setids >= 0 and setids <= 255:
- self.optionOCR = CIntruderOCR(captcha, options)
- else:
- print "\n[Error] You must enter a valid RGB colour ID number (between 0 and 255)\n"
- return #sys.exit(2)
- else:
- self.optionOCR = CIntruderOCR(captcha, options)
- else: # using general OCR algorithm
- if options.setids: # with a specific colour ID
- setids = int(options.setids)
- if setids >= 0 and setids <= 255:
- self.optionOCR = CIntruderOCR(captcha, options)
- else:
- print "\n[Error] You must enter a valid RGB colour ID number (between 0 and 255)\n"
- return #sys.exit(2)
- else:
- self.optionOCR = CIntruderOCR(captcha, options)
- def crack(self, captchas):
- """
- Crack mode:
- + Brute force target's captcha against a dictionary
- """
- self.crack_captcha(captchas)
- def crack_captcha(self, captcha):
- """
- Crack mode: bruteforcing...
- """
- options = self.options
- if options.name:
- print "Loading module:", options.name
- print "==============="
- try:
- sys.path.append('mods/%s/'%(options.name))
- exec("from " + options.name + "_crack" + " import CIntruderCrack")
- except Exception:
- print "\n[Error] '"+ options.name+ "' module not found!\n"
- return #sys.exit(2)
- self.optionCrack = CIntruderCrack(captcha)
- w = self.optionCrack.crack(options)
- self.word_sug = w
- else:
- self.optionCrack = CIntruderCrack(captcha)
- w = self.optionCrack.crack(options)
- self.word_sug = w
- def remote(self, captchas, proxy):
- """
- Get remote captchas
- """
- l = []
- if not os.path.exists("inputs/"):
- os.mkdir("inputs/")
- for captcha in captchas:
- c = self.remote_captcha(captcha, proxy)
- l.append(c)
- return l
- def remote_captcha(self, captcha, proxy):
- """
- Get remote captcha
- """
- if proxy:
- self.ignoreproxy=0
- self.optionCurl = CIntruderCurl(captcha, self.ignoreproxy, proxy)
- buf = self.optionCurl.request()
- if buf != "exit":
- m = hashlib.md5()
- m.update(captcha)
- c = "%s.gif"%(m.hexdigest())
- h = "inputs/" + c
- f = open(h, 'wb')
- f.write(buf.getvalue())
- f.close
- buf.close
- return h
- else:
- return #sys.exit(2)
- def export(self, captchas):
- """
- Export results
- """
- if self.options.xml and not (self.options.train):
- self.optionXML = CIntruderXML(captchas)
- if self.word_sug == None:
- print "[Info] XML NOT created!. There are not words to suggest..."
- else:
- self.optionXML.print_xml_results(captchas, self.options.xml, self.word_sug)
- print "[Info] XML created:", self.options.xml, "\n"
- def track(self, captchas, proxy, num_tracks):
- """
- Download captchas from url
- """
- for captcha in captchas:
- self.track_captcha(captcha, proxy, num_tracks)
- def track_captcha(self, captcha, proxy, num_tracks):
- """
- This technique is useful to create a dictionary of 'session based' captchas
- """
- options = self.options
- urlp = urlparse(captcha)
- self.domain = urlp.hostname
- if not os.path.exists("inputs/%s"%(self.domain)):
- os.mkdir("inputs/%s"%(self.domain))
- if proxy:
- self.ignoreproxy = 0
- buf = ""
- i=0
- while i < int(num_tracks) and buf != "exit":
- self.optionCurl = CIntruderCurl(captcha, self.ignoreproxy, proxy)
- buf = self.optionCurl.request()
- if options.verbose:
- print "\n[-]Connection data:"
- out = self.optionCurl.print_options()
- print '-'*45
- if buf != "exit":
- m = hashlib.md5()
- m.update("%s%s"%(time.time(), captcha))
- h = "inputs/%s/%s.gif"%(self.domain, m.hexdigest())
- f = open(h, 'wb')
- f.write(buf.getvalue())
- f.close
- buf.close
- print "[Info] Saved:", h
- print "------------"
- i=i+1
- if buf != "exit":
- print "\n================="
- print "Tracking Results:"
- print "================="
- print "\nNumber of tracked captchas: [", num_tracks, "] \n"
- def run(self, opts=None):
- """
- Run cintruder
- """
- if opts:
- options = self.create_options(opts)
- self.set_options(options)
- options = self.options
- #step -1: run GUI/Web interface
- if options.web:
- self.create_web_interface()
- return
- #step -1: check/update for latest stable version
- if options.update:
- self.banner()
- try:
- print("\nTrying to update automatically to the latest stable version\n")
- Updater()
- except:
- print("\nSomething was wrong!. To have working this feature, you should clone CIntruder with:\n")
- print("$ git clone https://github.com/epsylon/cintruder\n")
- #step 0: list output results and get captcha targets
- if options.listmods:
- print "====================================="
- print "Listing specific OCR exploit modules:"
- print "=====================================\n"
- top = 'mods/'
- for root, dirs, files in os.walk(top, topdown=False):
- for name in files:
- if name == 'DESCRIPTION':
- if self.os_sys == "Windows": #check for win32 sys
- subprocess.call("type %s/%s"%(root, name), shell=True)
- else:
- subprocess.call("cat %s/%s"%(root, name), shell=True)
- print "\n[Info] List end...\n"
- return #sys.exit(2)
- captchas = self.try_running(self.get_attack_captchas, "\nInternal error getting -captchas-. look at the end of this Traceback.")
- captchas = self.sanitize_captchas(captchas)
- captchas2track = captchas
- if self.isurl == 1 and (options.train or options.crack):
- if options.proxy:
- captchas = self.remote(captchas, options.proxy)
- else:
- captchas = self.remote(captchas, "")
- if options.verbose:
- print "[-] Connection data:"
- out = self.optionCurl.print_options()
- print '-'*45
- #step 0: track
- if options.track:
- if options.s_num:
- num_tracks = int(options.s_num) # tracking number defined by user
- else:
- num_tracks = int(5) # default track connections
- if options.proxy:
- self.try_running(self.track, "\nInternal problems tracking: ", (captchas2track, options.proxy, num_tracks))
- else:
- self.try_running(self.track, "\nInternal problems tracking: ", (captchas2track, "", num_tracks))
- #step 1: train
- if options.train:
- try:
- if len(captchas) == 1:
- for captcha in captchas:
- if captcha is None:
- print "\n[Error] Applying OCR algorithm... Is that captcha supported?\n"
- else:
- print "Target:", options.train
- print "=======\n"
- self.try_running(self.train, "\nInternal problems training: ", (captchas))
- else:
- for captcha in captchas:
- if len(captchas) > 1 and captcha is None:
- pass
- else:
- print "Target: ", options.train
- self.try_running(self.train, "\nInternal problems training: ", (captchas))
- except:
- print "\n[Error] Something wrong getting captcha. Aborting...\n"
- if options.xml:
- print "[Info] You don't need export to XML on this mode... File not generated!\n"
- #step 2: crack
- if options.crack:
- if len(captchas) == 1:
- for captcha in captchas:
- if captcha is None:
- print "\n[Error] Trying to bruteforce... Is that captcha supported?\n"
- else:
- print "Target: ", options.crack
- print "======="
- self.try_running(self.crack, "\nInternal problems cracking: ", (captchas))
- else:
- for captcha in captchas:
- if len(captchas) > 1 and captcha is None:
- pass
- else:
- print "Target: ", options.crack
- print "======="
- self.try_running(self.crack, "\nInternal problems cracking: ", (captchas))
- if options.command:
- print "[Info] Executing tool connector... \n"
- if self.word_sug is not None:
- print "[Info] This is the word suggested by CIntruder: [", self.word_sug, "] \n"
- else:
- print "[Error] CIntruder hasn't any word to suggest... Handlering tool process aborted! ;(\n"
- sys.exit(2)
- if "CINT" in options.command: # check parameter CINT on command (*)
- # change cintruder suggested word for the users captchas input form parameter
- # and execute handlered tool with it.
- if self.word_sug is not None:
- cmd = options.command.replace("CINT", self.word_sug)
- subprocess.call(cmd, shell=True)
- else:
- cmd = options.command
- subprocess.call(cmd, shell=True)
- else:
- print "[Error] Captcha's parameter flag: 'CINT' is not present on:", options.command, "\n"
- #step 3: export
- if options.xml:
- self.try_running(self.export, "\nInternal problems exporting: ", (captchas))
- def sanitize_captchas(self, captchas):
- """
- Sanitize correct input of source target(s)
- """
- options = self.options
- all_captchas = set()
- for captcha in captchas:
- # captcha from url
- if "http://" in captcha or "https://" in captcha:
- all_captchas.add(captcha)
- self.isurl = 1
- elif self.isurl == 0: # captcha from file
- (root, ext) = os.path.splitext(captcha)
- if ext != '.gif' and ext != '.jpg' and ext != '.jpeg' and ext != '.png': #by the moment
- captcha = None
- all_captchas.add(captcha)
- else:
- all_captchas.add(captcha)
- self.isurl = 0
- return all_captchas
- def create_web_interface(self):
- from webgui import ClientThread
- host = '0.0.0.0'
- port = 9999
- try:
- webbrowser.open('http://127.0.0.1:9999', new=1)
- tcpsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- tcpsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- tcpsock.bind((host,port))
- while True:
- tcpsock.listen(4)
- (clientsock, (ip, port)) = tcpsock.accept()
- newthread = ClientThread(ip, port, clientsock)
- newthread.start()
- except (KeyboardInterrupt, SystemExit):
- sys.exit()
- if __name__ == "__main__":
- app = cintruder()
- options = app.create_options()
- if options:
- app.set_options(options)
- app.run()
|