#!/usr/bin/python3 # -*- coding: iso-8859-15 -*- """ This file is part of the cintruder project, https://cintruder.03c8.net Copyright (c) 2012/2020 psy 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 socket, threading, re, base64, os, time import webbrowser, subprocess, json, sys try: from urlparse import urlparse except: import urllib.request, urllib.parse, urllib.error from .options import CIntruderOptions from pprint import pprint from shutil import copyfile host = "0.0.0.0" port = 9999 class ClientThread(threading.Thread): def __init__(self, ip, port, socket): threading.Thread.__init__(self) self.ip = ip self.port = port self.socket = socket self.pages = Pages() def run(self): req = self.socket.recv(2048) res = self.pages.get(req) if res is None: self.socket.close() return out = "HTTP/1.0 %s\r\n" % res["code"] out += "Pragma: no-cache\n" out += "Expires: Fri, 30 Oct 1998 00:00:01 GMT\n" out += "Cache-Control: no-cache, must-revalidate\n" out += "Content-Type: %s\r\n\r\n" % res["ctype"] out += "%s" % res["html"] try: self.socket.send(out.encode('utf-8')) except: self.socket.send(out) self.socket.close() if "run" in res and len(res["run"]): subprocess.Popen(res["run"], shell=True) class Pages(): def __init__(self): self.options = CIntruderOptions() self.pages = {} cintruder_img = open("core/images/cintruder.txt").read() #base64 logo if not os.path.exists("outputs/words/"): os.mkdir("outputs/words/") self.pages["/header"] = """ CINTRUDER: OCR Bruteforcing Toolkit """ self.pages["/footer"] = """ """ self.pages["/"] = self.pages["/header"] + """

CINTRUDER is an automatic pentesting tool to bypass captchas

Contact: psy (epsylon@riseup.net) - [03c8.net]

License: GPLv3 | Donate: BTC


Track: Train: Crack:


""" + self.pages["/footer"] self.pages["/directory-words"] ="""

View Dictionary Info
"""+str("".join(self.list_words()))+"""

""" self.pages["/lib.js"] = """function loadXMLDoc() { var xmlhttp; if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp = new XMLHttpRequest(); } else { // code for IE6, IE5 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 ) { if(xmlhttp.status == 200){ document.getElementById("cmdOut").innerHTML = xmlhttp.responseText; setTimeout("loadXMLDoc()", 3000); } } } xmlhttp.send(); } function runCommandX(cmd,params) { var xmlhttp; if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp = new XMLHttpRequest(); } else { // code for IE6, IE5 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 ) { if(xmlhttp.status == 200){ if(cmd.indexOf("?")!=-1){ s=cmd.split("?") cmd=s[0] params=s[1] } document.getElementById("cmdOut").innerHTML = xmlhttp.responseText; //document.getElementById("cmdOut").scrollIntoView(); newcmd=cmd if(newcmd=="cmd_remove_ocr" || newcmd=="cmd_move_ocr" || newcmd=="cmd_dict"){ //do not refresh return; } else { if(newcmd=="cmd_list" || newcmd=="cmd_track" || newcmd == "cmd_tracklist" || newcmd=="cmd_crack" || newcmd=="cmd_train") newcmd=newcmd+"_update" //do not refresh if certain text on response is found if(newcmd.match(/update/) && ( xmlhttp.responseText.match(/Number of tracked captchas/) || xmlhttp.responseText.match(/to the correct folder/) || xmlhttp.responseText.match(/by the moment/) || xmlhttp.responseText.match(/Is that captcha supported?/) || xmlhttp.responseText.match(/module not found/) || xmlhttp.responseText.match(/No idea/) || xmlhttp.responseText.match(/Possible Solution/) || xmlhttp.responseText.match(/Internal problems/) || xmlhttp.responseText.match(/List end/) ) ) return; setTimeout(function(){runCommandX(newcmd,params)}, 3000); return;} } } } if(typeof params != "undefined") cmd=cmd+"?"+params xmlhttp.open("GET", cmd, true); xmlhttp.send(); } """ def list_words(self): m = [] t = os.listdir("outputs/words") for f in t: try: with open("core/images/previews/ocr/"+f,'rb') as img_f: img = "data:image/gif;base64,"+base64.b64encode(img_f.read()).decode('utf-8') except: img = "" ocr_preview = "
"+f+"
" m.append(ocr_preview) return m def convert_size(self, size): import math if (size == 0): return '0B' size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB") i = int(math.floor(math.log(size,1024))) p = math.pow(1024,i) s = round(size/p,2) return '%s %s' % (s,size_name[i]) def buildGetParams(self, request): params = {} try: path = re.findall("^GET ([^\s]+)", request) except: path = re.findall("^GET ([^\s]+)", request.decode('utf-8')) if path: path = path[0] start = path.find("?") if start != -1: for param in path[start+1:].split("&"): f = param.split("=") if len(f) == 2: var = f[0] value = f[1] value = value.replace("+", " ") value = urllib.parse.unquote(value) params[var] = value return params def get(self, request): cmd_options = "" runcmd = "" try: res = re.findall("^GET ([^\s]+)", request) except: res = re.findall("^GET ([^\s]+)", request.decode('utf-8')) if res is None: return pGet = {} try: page = res[0] except: return paramStart = page.find("?") if paramStart != -1: page = page[:paramStart] pGet = self.buildGetParams(request) if page.startswith("/images/") or page.startswith("/js/") or page.startswith("/inputs/"): if os.path.exists("core/"+page[1:]): try: f=open("core/"+page[1:],'r',encoding="utf-8") data = f.read() except: try: with open("core/"+page[1:],'rb') as img_f: data = base64.b64encode(img_f.read()).decode('utf-8') except: data = "" self.pages[page]=data if page == "/cmd_dict": # view dictionary info path, dirs, files = next(os.walk("dictionary/")) total_dirs = len(dirs) total_files = len(files) size = 0 for d in dirs: path, dirs, files = next(os.walk("dictionary/"+d)) total_files = total_files + len(files) for f in files: size += os.path.getsize("dictionary/"+d+"/"+f) size = self.convert_size(size) last_update = time.ctime(os.path.getctime("dictionary/")) self.pages["/cmd_dict"] = "
Creation Date:Size:Total Words:Total Symbols:
"+str(last_update)+""+str(size)+""+str(total_dirs)+""+str(total_files)+"
" if page == "/cmd_remove_ocr": # remove ocr image from previews if not pGet["symbol"]=="off": self.pages["/cmd_remove_ocr"] = "
[Info] Discarding image from previews...
" symbol = pGet["symbol"] try: os.remove("core/" + symbol) except: pass if page == "/cmd_move_ocr": # move ocr image from previews to dictionary if not pGet["symbol"]=="off": self.pages["/cmd_move_ocr"] = "
[Info] Adding image from previews to dictionary...
" symbol = pGet["symbol"] letter = pGet["letter"] o = "core/" + symbol d = "dictionary/" + letter try: if not os.path.exists(d): os.makedirs(d) head, tail = os.path.split(symbol) final = d + "/" + tail copyfile(o, final) # copy file to letter on dictionary os.remove(o) # purge from previews except: pass if page == "/cmd_list": # list mods self.pages["/cmd_list"] = "
Waiting for a list of available modules...
" runcmd = "(python -i cintruder --mods-list "+ "|tee /tmp/out) &" if page == "/cmd_list_update": if not os.path.exists('/tmp/out'): open('/tmp/out', 'w').close() with open('/tmp/out', 'r') as f: self.pages["/cmd_list_update"] = "
"+f.read()+"
"
        if page == "/cmd_track": # tracking
            self.pages["/cmd_track"] = "
Waiting for tracking results...
" if pGet["tor"]=="on": cmd_options = cmd_options + "--proxy 'http://localhost:8118' " if pGet["verbose"]=="on": cmd_options = cmd_options + "--verbose " runcmd = "(python -i cintruder --track '"+pGet["tracking_source"]+"' --track-num '"+pGet["tracking_num"]+"' " + cmd_options + "|tee /tmp/out) &" if page == "/cmd_track_update": if not os.path.exists('/tmp/out'): open('/tmp/out', 'w').close() with open('/tmp/out', 'r') as f: self.pages["/cmd_track_update"] = "
"+f.read()+"
"
        if page == "/cmd_tracklist": # list last tracks
            self.pages["/cmd_tracklist"] = "
Waiting for a list of last tracks...
" runcmd = "(python -i cintruder --tracked-list "+ "|tee /tmp/out) &" if page == "/cmd_tracklist_update": if not os.path.exists('/tmp/out'): open('/tmp/out', 'w').close() with open('/tmp/out', 'r') as f: self.pages["/cmd_tracklist_update"] = "
"+f.read()+"
"
        if page == "/cmd_train": # training
            self.pages["/cmd_train"] = "
Waiting for training results...
" if pGet["tor"]=="on": cmd_options = cmd_options + "--proxy 'http://localhost:8118' " if pGet["verbose"]=="on": cmd_options = cmd_options + "--verbose " if not pGet["colourID"]=="off": cmd_options = cmd_options + "--set-id='" + pGet["colourID"] + "' " if not pGet["module"]=="off": cmd_options = cmd_options + "--mod='" + pGet["module"] + "' " if pGet["source_file"]=="off": # from remote url source runcmd = "(python -i cintruder --train '"+pGet["train_url"]+"' " + cmd_options + "|tee /tmp/out) &" else: # from local source source_file = pGet["source_file"] runcmd = "(python -i cintruder --train '"+source_file+"' " + cmd_options + "|tee /tmp/out) &" if page == "/cmd_train_update": if not os.path.exists('/tmp/out'): open('/tmp/out', 'w').close() with open('/tmp/out', 'r') as f: self.pages["/cmd_train_update"] = "
"+f.read()+"
"
        if page == "/cmd_crack": # cracking
            self.pages["/cmd_crack"] = "
Waiting for cracking (bruteforcing) results...
" if pGet["tor"]=="on": cmd_options = cmd_options + "--proxy 'http://localhost:8118' " if pGet["verbose"]=="on": cmd_options = cmd_options + "--verbose " if not pGet["colourID"]=="off": cmd_options = cmd_options + "--set-id='" + pGet["colourID"] + "' " if not pGet["module"]=="off": cmd_options = cmd_options + "--mod='" + pGet["module"] + "' " if not pGet["xml"]=="off": cmd_options = cmd_options + "--xml='" + pGet["xml"] + "' " if pGet["source_file"]=="off": # from remote url source runcmd = "(python -i cintruder --crack '"+pGet["crack_url"]+"' " + cmd_options + "|tee /tmp/out) &" else: # from local source source_file = pGet["source_file"] runcmd = "(python -i cintruder --crack '"+source_file+"' " + cmd_options + "|tee /tmp/out) &" if page == "/cmd_crack_update": if not os.path.exists('/tmp/out'): open('/tmp/out', 'w').close() with open('/tmp/out', 'r') as f: self.pages["/cmd_crack_update"] = "
"+f.read()+"
"
        ctype = "text/html"
        if page.find(".js") != -1:
            ctype = "text/javascript"
        elif page.find(".txt") != -1:
            ctype = "text/plain"
        elif page.find(".ico") != -1:
            ctype = "image/x-icon"
        elif page.find(".png") != -1:
            ctype = "image/png"
        elif page.find(".jpeg") != -1:
            ctype = "image/jpeg"
        elif page.find(".jpg") != -1:
            ctype = "image/jpeg"
        elif page.find(".gif") != -1:
            ctype = "image/gif"
        if page in self.pages:
            return dict(run=runcmd, code="200 OK", html=self.pages[page], ctype=ctype)
        return dict(run=runcmd, code="404 Error", html="404 Error

Page not found...", ctype=ctype) class Command(object): def __init__(self, cmd): self.cmd = cmd self.process = None def run(self, timeout): def target(): self.process = subprocess.Popen(self.cmd, shell=True) thread = threading.Thread(target=target) thread.start() thread.join(timeout) if thread.is_alive(): self.process.terminate() thread.join() if __name__ == "__main__": 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, c_port)) = tcpsock.accept() newthread = ClientThread(ip, c_port, clientsock) newthread.start()