#-*- coding: utf-8 -*-

__module_name__ = "CrackMe" 
__module_version__ = "0.3 beta" 
__module_description__ = "X-Chat2 plugin Hashes look up."
__module_author__ = "Sorcier_FXK <sorcierfxk@kalkulators.org>"

##CrackMe XChat2 plugin
## Latest version here      : http://project.kalkulators.org/download/xchat2_crackme_0.3.tar.gz
## Stand alone version here : http://project.kalkulators.org/<url> // not released at the moment
## Last update : 29 August 2011
## All depencies are included in archive
##
## dependencies : python mhash, python phpass, pycrypto
## 
##		https://github.com/exavolt/python-phpass
##
## How to update 0.2.1b to 0.3 ?
## Download archive, open archive and extract xchat2_crackme.py in your /home/user/.xchat2/
## Create those folders:
## /home/user/.xchat2/crackme/
## /home/user/.xchat2/crackme/db/
## /home/user/.xchat2/crackme/download/
## /home/user/.xchat2/crackme/output/
##
## How to install ?
## Be carefull : Automatic installation mode is only for linux package. (not released)
##		 Only manual installation at the moment. This plugin has tested only 
##		 under linux (Ubuntu). Feedbacks are welcomes :)
##
##	Automatic:
## 		Run "install.sh" with root privileges, load "xchat_crackme.py" in XChat2,
##		ready.
##	Manual:
##		Install dependencies (phpass folder & crypto.py are in archive), copy 
##		"crypto.py" file and 'phpass' folder in your /usr/lib/python2.6/ directory 
##		(for Ubuntu) , install python-mhash & py-crypto via apt-get/aptitude
##		load "xchat2_crackme.py" in XChat2, ready. Type in Xchat2 /crackme config init
##		Done, you are ok.
##
## Thanks to :
##
## 	Yiannis, owner of md5this.com, for add his db in crackme plugin and
##	maker wordlist from websites (mode /harverster grab) :)
##
##
##TODO for validate 0.4 version
##
## recode /hash with 'dynamic motor'
## add filter module
##	-add filter {MD5}b64 -> hex MD5
##	-add filter {SHA}b64 -> hex sha1(pass.salt) (for soloris & linux ldap)
##
##TODO for validate 0.3 version.
##
## add password generator                                                  --> ok
## use sqlite3 for captured plaintexts & not found hashes                  --> in progress
## add hashlists manager                                                   --> in progress
## add MySQL module
## add new hash types for /whatis
## import to pastebin.com API				                   --> ok
## export to pastebin.com API				                   --> ok
## add salt support in /hash function                                      --> ok
## add b64 encoder/decoder                                                 --> ok
## add ROT13 encoder/decoder                                               --> ok
## add harvester to collect plaintext from any sources                     --> in progress
## add new charsets in /password function		                   --> ok
## Remove old look up function, add newest at cracker.kalkulators.org API  --> ok
## add lm look up support via /pwdump switch                               --> ok
##
##TODO for validate 0.2 version.
##
## add hash calculator                                         --> ok
## /whatis => identification hashes module                     --> ok
## /len <string> => string length                              --> ok
## Remplace all "syntax error" messages by "man page"          --> ok
##
##TODO list for dev in 0.3 version.
##
## Bug in harvest mode with google dork
##
##
##BUG Tracker
##
## Ver			Comment
## 0.2.1  bug in function /len with espace char                     --> Fixed
## 0.2.1  DB down crash thread                                      --> Fixed
## 0.2.1  MD5This.com db added, see "Thanks to:" section.
## 0.2    TMTO's API's modified, don't works,                       --> Fixed
## 0.1    command without parameter (ie: '/ntlm') -> crash plug in  --> Fixed

import warnings

def fxn():
	warnings.warn("deprecated", DeprecationWarning)
	import sets
with warnings.catch_warnings():
	warnings.simplefilter("ignore")
	fxn()


import xchat, urllib, urllib2, crypt, random, phpass, hashlib
import base64, sqlite3, time, re, simplejson, ast

from threading import Thread
from crypto import HashMaker



class Pastebin(object):
    prefix_url = 'http://pastebin.com/'
    subdomain_url = 'http://%s.pastebin.com/' # % paste_subdomain
    api_url = 'http://pastebin.com/api_public.php'
    paste_expire_date = ('N', '10M', '1H', '1D', '1M')
    paste_format = (
        'abap', 'actionscript', 'actionscript3', 'ada', 'apache',
        'applescript', 'apt_sources', 'asm', 'asp', 'autoit', 'avisynth',
        'bash', 'basic4gl', 'bibtex', 'blitzbasic', 'bnf', 'boo', 'bf', 'c',
        'c_mac', 'cill', 'csharp', 'cpp', 'caddcl', 'cadlisp', 'cfdg',
        'klonec', 'klonecpp', 'cmake', 'cobol', 'cfm', 'css', 'd', 'dcs',
        'delphi', 'dff', 'div', 'dos', 'dot', 'eiffel', 'email', 'erlang',
        'fo', 'fortran', 'freebasic', 'gml', 'genero', 'gettext', 'groovy',
        'haskell', 'hq9plus', 'html4strict', 'idl', 'ini', 'inno', 'intercal',
        'io', 'java', 'java5', 'javascript', 'kixtart', 'latex', 'lsl2',
        'lisp', 'locobasic', 'lolcode', 'lotusformulas', 'lotusscript',
        'lscript', 'lua', 'm68k', 'make', 'matlab', 'matlab', 'mirc',
        'modula3', 'mpasm', 'mxml', 'mysql', 'text', 'nsis', 'oberon2', 'objc',
        'ocaml-brief', 'ocaml', 'glsl', 'oobas', 'oracle11', 'oracle8',
        'pascal', 'pawn', 'per', 'perl', 'php', 'php-brief', 'pic16',
        'pixelbender', 'plsql', 'povray', 'powershell', 'progress', 'prolog',
        'properties', 'providex', 'python', 'qbasic', 'rails', 'rebol', 'reg',
        'robots', 'ruby', 'gnuplot', 'sas', 'scala', 'scheme', 'scilab',
        'sdlbasic', 'smalltalk', 'smarty', 'sql', 'tsql', 'tcl', 'tcl',
        'teraterm', 'thinbasic', 'typoscript', 'unreal', 'vbnet', 'verilog',
        'vhdl', 'vim', 'visualprolog', 'vb', 'visualfoxpro', 'whitespace',
        'whois', 'winbatch', 'xml', 'xorg_conf', 'xpp', 'z80'
    )

    # Submit a code snippet to Pastebin
    @classmethod
    def submit(cls, paste_code,
                paste_name = None, paste_subdomain = None,
                paste_private = None, paste_expire_date = None,
                paste_format = None):

        # Code snippet to submit
        argv = { 'paste_code' : str(paste_code) }

        # Name of the poster
        if paste_name is not None:
            argv['paste_name'] = str(paste_name)

        # Custom subdomain
        if paste_subdomain is not None:
            paste_subdomain = str(paste_subdomain).strip().lower()
            argv['paste_subdomain'] = paste_subdomain

        # Is the snippet private?
        if paste_private is not None:
            argv['paste_private'] = int(bool(int(paste_private)))

        # Expiration for the snippet
        if paste_expire_date is not None:
            paste_expire_date = str(paste_expire_date).strip().upper()
            if not paste_expire_date in cls.paste_expire_date:
                raise ValueError, "Bad expire date: %s" % paste_expire_date

        # Syntax highlighting
        if paste_format is not None:
            paste_format = str(paste_format).strip().lower()
            if not paste_format in cls.paste_format:
                raise ValueError, "Bad format: %s" % paste_format
            argv['paste_format'] = paste_format

        # Make the request to the Pastebin API
        fd = urllib.urlopen(cls.api_url, urllib.urlencode(argv))
        try:
            response = fd.read()
        finally:
            fd.close()
        del fd

        # Return the new snippet URL on success, raise exception on error
        if argv.has_key('paste_subdomain'):
            prefix = cls.subdomain_url % paste_subdomain
        else:
            prefix = cls.prefix_url
        if not response.startswith(prefix):
            raise RuntimeError, response
        return response

def db_sqlite(param, data):
	if param[0] == 'init.config':
		try:
			start_point = ".xchat2/crackme/db/config.db"
			link = start_point
			con = sqlite3.connect(link)
			con.isolation_level = None
			cur = con.cursor()
			cur.execute('''create table config(output_dir text, input_dir text)''')
			cur.execute('''create table mod(mod_name text, mod_ver text, mod_ip text, mod_port text)''')
			cur.execute('''create table hashlist(h_id int,h_name text, h_type text, h_date text, h_lastup text, h_qty int, h_qty_lastup int, h_list text)''')
			cur.execute("""insert into config values ('.xchat2/crackme/output/', '.xchat2/crackme/download/')""")
			
			return True
		except:
			return False
		cur.close()
		
	if param[0] == 'init':
		print "[>]" + 60 * "-"
		print "[>] Initialization of config.db."
		param[0] = 'init.config'
		statut = db_sqlite(param, data)
		if statut == True:
			print "[>] Success ! config.db is now initialized."
		else:
			print "[>] Error ! Check your paths & rights."

	if param[0] == 'read.config':
		try:
			start_point = ".xchat2/crackme/db/config.db"
			link = start_point
			con = sqlite3.connect(link)
			con.isolation_level = None
			cur = con.cursor()
			cur.execute('''select * from config''')
			r_query = []			
			for raw in cur:
				for x in raw:
					r_query.append(x)
			cur.close()
				
			return r_query
		except:
			return False
	if param[0] == 'read.config.input_path':
		try:
			start_point = ".xchat2/crackme/db/config.db"
			link = start_point
			con = sqlite3.connect(link)
			con.isolation_level = None
			cur = con.cursor()
			cur.execute('''select input_dir from config''')
			r_query = []			
			for raw in cur:
				for x in raw:
					r_query.append(x)
			cur.close()
				
			return r_query
		except:
			return False

	if param[0] == 'read.hashlist.info':
		try:
			start_point = ".xchat2/crackme/db/config.db"
			link = start_point
			con = sqlite3.connect(link)
			con.isolation_level = None
			cur = con.cursor()
			cur.execute('''select h_name, h_type, h_date, h_lastup, h_qty, h_qty_lastup from hashlist''')
			r_query = []			
			for raw in cur:
				r_query.append(raw)
			cur.close()
				
			return r_query
		except:
			return False
	if param[0] == 'read.hashlist.search':
		try:
			start_point = ".xchat2/crackme/db/config.db"
			link = start_point
			con = sqlite3.connect(link)
			con.isolation_level = None
			cur = con.cursor()
			cur.execute('''select h_name, h_type, h_date, h_lastup, h_qty, h_qty_lastup from hashlist where h_name like "%s"''' % ('%' + data[0] + '%'))
			r_query = []			
			for raw in cur:
				r_query.append(raw)
			cur.close()
				
			return r_query
		except:
			return False

	if param[0] == 'write.config.output_path':
		try:
			start_point = ".xchat2/crackme/db/config.db"
			link = start_point
			con = sqlite3.connect(link)
			con.isolation_level = None
			cur = con.cursor()
			cur.execute('''update config set output_dir="%s"''' % data[0])
			cur.close()
			return True
		except:
			return False
	if param[0] == 'write.config.input_path':
		try:
			start_point = ".xchat2/crackme/db/config.db"
			link = start_point
			con = sqlite3.connect(link)
			con.isolation_level = None
			cur = con.cursor()
			cur.execute('''update config set input_dir="%s"''' % data[0])
			cur.close()
			return True
		except:
			return False

	if param[0] == 'write.hashlist':
		#try:
		start_point = ".xchat2/crackme/db/config.db"
		link = start_point
		con = sqlite3.connect(link)
		con.isolation_level = None
		cur = con.cursor()
		cur.execute('''insert into hashlist values ("%s", "%s", "%s", "%s", "%s", %s, %s, "%s")''' % (data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]))
		cur.close()
		#	return True
		#except:
		#	return False

	if param[0] == 'read':
		if len(param) == 2 and param[1] == 'config':
			param = ['read.config']
			statut = db_sqlite(param, data)
			return statut
		if len(param) == 3 and param[1] == 'config' and param[2] == 'input_path':
			param = ['read.config.input_path']
			statut = db_sqlite(param, data)
			return statut
		if len(param) == 3 and param[1] == 'hashlist' and param[2] == 'info':
			param = ['read.hashlist.info']
			statut = db_sqlite(param, data)
			return statut
		if len(param) == 3 and param[1] == 'hashlist' and param[2] == 'search':
			param = ['read.hashlist.search']
			statut = db_sqlite(param, data)
			return statut
		else:
			print "[>] Error DB, check your paths & your rights."
			return False

	if param[0] == 'write':
		if len(param) == 2 and param[1] == 'hashlist':
			param == ['write.hashlist']
			statut = db_sqlite(param, data)
			return statut
		if len(param) == 3 and param[1] == 'config' and param[2] == 'output_path':
			param = ['write.config.output_path']
			statut = db_sqlite(param, data)
			return statut
		if len(param) == 3 and param[1] == 'config' and param[2] == 'input_path':
			param = ['write.config.input_path']
			statut = db_sqlite(param, data)
			return statut
		else:
			print "[>] Error DB, check your paths & your rights."
			return False



def run_md5(hashes):
	print "[>]\0034 Looking for MD5 %s...\0034" % hashes
	log = open('.xchat2/crackme/crackme_wl.txt', 'a+')
        Thread(None, md5_lookup, None, (hashes, log), {}).start()

def run_ntlm(hashes):
	log = open('.xchat2/crackme/crackme_wl.txt', 'a+')
	print "[>]\0034 Looking for NTLM %s... \0034" % hashes
	Thread(None, ntlm_lookup, None, (hashes, log,), {}).start()

def run_lm(hashes):
	log = open('.xchat2/crackme/crackme_wl.txt', 'a+')
	print "[>]\0034 Looking for LM %s... \0034" % hashes
	Thread(None, lm_lookup, None, (hashes, log,), {}).start()

def run_sha1(hashes):
	log = open('.xchat2/crackme/crackme_wl.txt', 'a+')
	print "[>]\0034 Looking for SHA-1 %s...\0034" % hashes
	Thread(None, sha1_lookup, None, (hashes, log,), {}).start()

def md5_lookup(hashes, log):
        try:
                f = urllib2.urlopen('http://cracker.kalkulators.org/API/md5/json/%s/' % hashes)
                data = ast.literal_eval(f.read())
                if data['status'] == 'found':
                        if data['website'] == 'tmto (base64 encoded string)':
                                result = base64.b64decode(data['value'])
                                data['website'] = 'TMTO'
                        else:
                                result = data['value']
                                
                        print "[>] \0033[MD5] %s\0033 : %s:%s" % (data['website'],hashes, result)
                else:
                       result = 'Not found'
                       print "[>] \0033[MD5] %s\0033 : %s" % (hashes, result)
        
                if result != 'Not found':
                       log.write(result+"\n")
                       log.close()                
        except:
                print "[>] cracker.kalkulators.org API appear down for the moment..."                

                        
def sha1_lookup(hashes, log):
        try:
                f = urllib2.urlopen('http://cracker.kalkulators.org/API/sha1/json/%s/' % hashes)
        	data = ast.literal_eval(f.read())
                if data['status'] == 'found':
                        result = data['value']
                        
                        print "[>] \0033[SHA1] %s\0033 : %s:%s" % (data['website'],hashes, result)
                else:
                        result = 'Not found'
                        print "[>] \0033[SHA1] %s\0033 : %s" % (hashes, result)
        
                if result != 'Not found':
                        log.write(result+"\n")
                        log.close()                
        except:
                print "[>] cracker.kalkulators.org API appear down for the moment..."      

def ntlm_lookup(hashes, log):
        try:
                f = urllib2.urlopen('http://cracker.kalkulators.org/API/ntlm/json/%s/' % hashes)
        	data = ast.literal_eval(f.read())
                if data['status'] == 'found':
                        result = data['value']
                        
                        print "[>] \0033[NTLM] %s\0033 : %s:%s" % (data['website'],hashes, result)
                else:
                        result = 'Not found'
                        print "[>] \0033[NTLM] %s\0033 : %s" % (hashes, result)
        
                if result != 'Not found':
                        log.write(result+"\n")
                        log.close()                
        except:
                print "[>] cracker.kalkulators.org API appear down for the moment..."

def lm_lookup(hashes, log):
	try:
                f = urllib2.urlopen('http://cracker.kalkulators.org/API/lm/json/%s/' % hashes)
        	data = ast.literal_eval(f.read())
                if data['status'] == 'found':
                        result = data['value']
                        
                        print "[>] \0033[LM] %s\0033 : %s:%s" % (data['website'],hashes, result)
                else:
                        result = 'Not found'
                        print "[>] \0033[LM] %s\0033: %s" % (hashes, result)
        
                if result != 'Not found':
                        log.write(result+"\n")
                        log.close()                
        except:
                print "[>] cracker.kalkulators.org API appear down for the moment..."



def crackme(word, word_eol, userdata):
	
	if len(word) == 1:
		print "[>]" + 60 * "-"
		print "[>] CrackMe Xchat2 plugin by Sorcier_FXK"
		print "[>] sorcierfxk@kalkulators.org"
		print "[>] Version : %s" % __module_version__
		print "[>] Latest version here : http://project.kalkulators.org/download/xchat2_crackme_0.3.tar.gz"
		print "[>] Project Kalkulator's Knights"
		print "[>] http://project.kalkulators.org"
		print "[>]"
		print "[>] Reverse lookup"
		print "[>] /md5 <hash>                    Looking for MD5 hash on public DB's"
		print "[>] /ntlm <hash>                   Looking for NTLM hash on public DB's"
		print "[>] /sha1 <hash>                   Looking for SHA-1 hash on public DB's"
		print "[>] /pwdump <lm_hash:ntlm_hash>    Looking for LM/NTLM hashes on public DB's"
                print "[>] /pwdump <lm_hash>              Looking for LM hashes on public DB's"
                print "[>] /lm <lm_hash>                  Looking for LM hashes on public DB's"
		print "[>]"	
		print "[>] Tools"
		print "[>] /whatis <hash>                 Identify hash type"
		print "[>] /len <string>                  Chain length"
		print "[>] /hash <type> <string> <n°ite>  Hash calculator"
		print "[>] /password <charset> <len>      Generate random password"
		print "[>] /import <site> <url> <file>    Import hashlist from pastebin"
		print "[>] /export <string>               Export string or text file to pastebin.com"
		print "[>] /harvester <param1> <param2>   Harvest plaintext (from file, URL...)"
		print "[>] /hashlist <param1> <param2>    Manage your hashlists"
		print "[>] /b64 <param> <string>          To encode/decode Base64 string"
		print "[>] /rot13 <param> <string>        To encode/decode ROT13 string"
		print "[>]"
		print "[>] Options"
		print "[>] /crackme                       This page"
		print "[>] /crackme config                View configuration's page"
		print "[>]"
		print "[>] MAN PAGES :"
		print "[>] To Man page's access, type command (ie: /hash, /ntlm...) without parameter"

	elif len(word) == 2 and word[1] == 'config':
		statut = db_sqlite(['read', 'config'], [' '])
		statut = list(statut)
		print "[>]" + 60 * "-"
		print "[>] Actual configuration of CrackMe :"
		print "[>] Output path : %s" % statut[0]
		print "[>] Input path  : %s" % statut[1]
		print "[>]"
		print "[>] To change your Output path type : /crackme config output_path /your/new/path/"
		print "[>] To change your Input path type  : /crackme config input_path /your/new/path/"

	elif len(word) == 3 and word[1] == 'config' and word[2] == 'init':
		param = ['init',' ']
		data = []
		db_sqlite(param, data)

	elif len(word) == 4 and word[1] == 'config' and word[2] == 'output_path':
		param = ['write', 'config', 'output_path']
		dat = word[3]
		data = []
		if dat[len(dat)-1] != '/':
			data.append(dat + '/')
		else:
			data.append(dat)
		statut = db_sqlite(param, data)
		if statut == True:
			print "[>] Configuration updated."
		else:
			print "[>] Error with DB."
	elif len(word) == 4 and word[1] == 'config' and word[2] == 'input_path':
		param = ['write', 'config', 'input_path']
		dat = word[3]
		data = []
		if dat[len(dat)-1] != '/':
			data.append(dat + '/')
		else:
			data.append(dat)
		statut = db_sqlite(param, data)
		if statut == True:
			print "[>] Configuration updated."
		else:
			print "[>] Error with DB."
	else:
		print "[>] Error incorrect parameter : %s" % word[1]
		print "[>] Type /crackme for more informations."

	return xchat.EAT_XCHAT

def md5(word, word_eol, userdata):
	if len(word) > 1:
		hashes = word[1]	
		Thread(None, run_md5, None, (hashes,), {}).start()
	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /md5"		
		print "[>] Syntax informations : /md5 <hash>"
		print "[>] Looking for md5 on public db's"
		print "[>] <hash>   Remplace by your md5 hash"
		print "[>]"
		print "[>] Kalkulator's Knight Web Cracker"
                print "[>] http://cracker.kalkulators.org"
	return xchat.EAT_XCHAT

def ntlm(word, word_eol, userdata):
	if len(word) > 1:
		hashes = word[1]	
		Thread(None, run_ntlm, None, (hashes,), {}).start()
	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /ntlm"		
		print "[>] Syntax informations : /ntlm <hash>"
		print "[>] Looking for ntlm hash on public db's"
		print "[>] <hash>   Remplace by your ntlm hash"	
		print "[>]"
		print "[>] Kalkulator's Knight Web Cracker"
                print "[>] http://cracker.kalkulators.org"
	return xchat.EAT_XCHAT

def pwdump(word, word_eol, userdata):
	if len(word) > 1:
		hashes = word[1]
		hashes = hashes.split(':')
		if len(hashes) == 2:	
			Thread(None, run_lm, None, (hashes[0],), {}).start()
                        Thread(None, run_ntlm, None, (hashes[1],), {}).start()
                else:
                        Thread(None, run_lm, None, (hashes[0].lower(),), {}).start()
                
	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /pwdump"
                print "[>] Man page : /lm"		
		print "[>] Syntax informations : /pwdump <LM:NTLM>"
                print "[>]                     : /pwdump <LM>"
                print "[>]                     : /lm <LM>"
		print "[>] Looking for pwdump hash format on public db's"
		print "[>] <LM:NTLM>   Replace by your hashes (LM & NTLM)"
                print "[>] <LM>        Replace by your LM hash"
		print "[>]"
		print "[>] Kalkulator's Knight Web Cracker"
                print "[>] http://cracker.kalkulators.org"
	return xchat.EAT_XCHAT

def sha1(word, word_eol, userdata):
	if len(word) > 1:
		hashes = word[1]	
		Thread(None, run_sha1, None, (hashes,), {}).start()
	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /sha1"		
		print "[>] Syntax informations : /sha1 <hash>"
		print "[>] Looking for sha1 hash on public db's"
		print "[>] <hash>   Remplace by your sha1 hash"
		print "[>]"
		print "[>] Kalkulator's Knight Web Cracker"
                print "[>] http://cracker.kalkulators.org"
	return xchat.EAT_XCHAT

def length(word, word_eol, userdata):
	if len(word) > 1:
		hashes = word_eol[1]
		print "[>]" + 60 * "-"
		print "[>] String : %s" % hashes
		print "[>] length : %s" % len(hashes)
	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /len"		
		print "[>] Syntax informations : /len <string>"
		print "[>] To calculate length"
		print "[>] <string>    Your chain here"
	return xchat.EAT_XCHAT

def edbase64(word, word_eol, userdata):
	if len(word) > 2:
		if word[1] == 'encode':
			print "[>]" + 60 * "-"
			print "[>] Base64 encoder"
			print "[>] String  : %s" % word[2]
			print "[>] Encoded : %s" % base64.b64encode(word[2])
		elif word[1] == 'decode':
			try:
				data = base64.b64decode(word[2])
				print "[>]" + 60 * "-"
				print "[>] Base64 decoder"
				print "[>] String  : %s" % word[2]
				print "[>] Decoded : %s" % data
			except:
				print "[>] Error, your string is not Base64 encoded"
		else:
			print "[>] Error, parameters : 'encode' or 'decode'"
	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /b64"		
		print "[>] Syntax informations : /b64 <param> <string>"
		print "[>] To encode or decode string  to Base64"
		print "[>] <param>     'encode' or 'decode'"
		print "[>] <string>    Your chain here"
	return xchat.EAT_XCHAT

def rot13(word, word_eol, userdata):
	if len(word) > 2:
		if word[1] == 'encode':
			print "[>]" + 60 * "-"
			print "[>] ROT13 encoder"
			print "[>] String  : %s" % word_eol[2]
			print "[>] Encoded : %s" % word_eol[2].encode('rot13')
		elif word[1] == 'decode':
			try:
				data = word_eol[2].decode('rot13')
				print "[>]" + 60 * "-"
				print "[>] ROT13 decoder"
				print "[>] String  : %s" % word_eol[2]
				print "[>] Decoded : %s" % data
			except:
				print "[>] Error, your string is not Base64 encoded"
		else:
			print "[>] Error, parameters : 'encode' or 'decode'"
	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /rot13"		
		print "[>] Syntax informations : /rot13 <param> <string>"
		print "[>] To encode or decode string  to ROT13"
		print "[>] <param>     'encode' or 'decode'"
		print "[>] <string>    Your chain here"
	return xchat.EAT_XCHAT

def export_data(word, word_eol, userdata):
	Thread(None, export_data_run, None, (word, word_eol, userdata), {}).start()
	return xchat.EAT_XCHAT

def export_data_run(word, word_eol, userdata):
	if len(word) == 3:
		if word[1] == 'file':
			print "[>]" + 60 * "-"
			print "[>] Export to pastebin.com"
			try:
				file_in = open(word[2], 'r')
				data = file_in.read()
				try:
					url = Pastebin.submit(paste_code = data, paste_name = "CrackMe")
					print "[>] Link : %s" % url
				except:
					print "[>] Error pastebin.com down ?"
			except:
				print "[>] Error with your path/file, check your rights."
 		else:
			print "[>] Error Incorect parameter."
			print "[>] Parameters : file"

	elif len(word) == 2:
		print "[>]" + 60 * "-"
		print "[>] Export to pastebin.com"
		try:
			url = Pastebin.submit(paste_code = word_eol[1], paste_name = "CrackMe")
			print "[>] Link : %s" % url
		except:
				print "[>] Error pastebin.com down ?"

	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /export"	
		print "[>] Syntax informations : /export <string>"
		print "[>]                     : /export <param> <path/file>"
		print "[>] To export string/text file to pastebin.com"
		print "[>] WARNING : Max size is 10Mb"
		print "[>] <string>     Your text"
		print "[>] <param>      *Optionnal* See table below"
		print "[>] <path/file>  *Optionnal* File path (ie : /media/usb1/myfile.txt)"
		print "[>]"
		print "[>] Compatible pastebin table :"
		print "[>] Pastebin                Parameter       ie"
		print "[>] pastebin.com            -               /export file /home/user/test.txt"
		print "[>]"
		print "[>] Parameters list :"
		print "[>] Parameter              info                ie"
		print "[>] file      to specificy output path/file    /export file /path/file.txt"    
		return xchat.EAT_XCHAT

def import_data(word, word_eol, userdata):
	Thread(None, import_data_run, None, (word, word_eol, userdata), {}).start()
	return xchat.EAT_XCHAT

def import_data_run(word, word_eol, userdata):
	error_lvl = 0
	## Import from pastebin.com to .txt file (user define file name & path)
	if len(word) == 4:
		if word[1] == "pb":
			link = word[2].split('/')
			link = link[3]
			output_path = word[3]
			print "[>]" + 60 * "-"
			print "[>] Import from pastebin.com %s" % word[2]
			try:
				f = urllib2.urlopen('http://pastebin.com/download.php?i=%s' % link)
				data = f.read()

				if 'jkUAIOE8owUXu8UXIhRLB9oHJsWBfOgJbZzncqHoF4A' in data:
					error_lvl = 1

				if error_lvl < 1:
					try:					
						out = open(output_path, 'w')
						out.write(data+'\n')
						print "[>] Output : %s" % output_path
						print "[>] Import : Success"
					except:
						print "[>] Error with your path/file, check your rights."
						print "[>] Import : Echec !"
			except:
				print "[>] Error with your URL, maybe site down."
				print "[>] Import : Echec !"

	## Import to pastebin.com to .txt file (with random file name)
	elif len(word) == 3:
		if word[1] == "pb":
			link = word[2].split('/')
			link = link[3]
			print "[>]" + 60 * "-"
			print "[>] Import from pastebin.com %s" % word[2]
			try:
				f = urllib2.urlopen('http://pastebin.com/download.php?i=%s' % link)
				data = f.read()

				if 'jkUAIOE8owUXu8UXIhRLB9oHJsWBfOgJbZzncqHoF4A' in data:
					error_lvl = 1

				if error_lvl < 1:
					try:
						output_path = db_sqlite(['read', 'config', 'input_path'], [' '])
						file_name = "%spb-%s.txt" % (output_path[0], link)				
						out = open(file_name, 'w')
						out.write(data+'\n')
						print "[>] Output in your default folder : %s" % file_name
						print "[>] Import : Success"
					except:
						print "[>] Error with your path/file, check your rights."
						print "[>] Import : Echec !"
			except:
				print "[>] Error with your URL, maybe site down."
				print "[>] Import : Echec !"
	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /import"	
		print "[>] Syntax informations : /import <site> <url> <output>"
		print "[>] To import hashlist from pastebin of your choice."
		print "[>] <site>    See table below"
		print "[>] <url>     URL of your post"
		print "[>] <output>  *Optionnal* Output path (ie : /media/usb1/mypast.txt)"
		print "[>]"
		print "[>] Compatible pastebin table :"
		print "[>] Pastebin                Parameter       ie"
		print "[>] pastebin.com            pb              /importe pb"

	if error_lvl == 1:
		print "[>] Error unknow pastebin ID."
	return xchat.EAT_XCHAT

def password(word, word_eol, userdata):
	charset_dico = {1:'abcdefghijklmnopqrstuvwxyz',
			2:'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
			3:'0123456789',
			4:'abcdefghijklmnopqrstuvwxyz0123456789',
			5:'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
			6:'abcdefghijklmnopqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXYZ',
			7:'abcdefghijklmnopqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
			8:'abcdefghijklmnopqrstuvwxyz0123456789!:/;.,?@=+-}])[({%&*$',
			9:'abcdefghijklmnopqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!:/;.,?@=+-}])[({%&*$',
			10:'0123456789abcdef'}

	if len(word) > 2:
		try:
			charset = int(word[1])
			length = int(word[2])
			try:
				multi = int(word[3])
			except:
				multi = 1
			
			if charset < 9 or charset > 0:
				charset = charset_dico[charset]
				print "[>]" + 60 * "-"
				print "[>] Charset :", charset
				print "[>] Length :", length
				result = ''
				for y in xrange(multi):
					for x in xrange(length):
						a = random.randint(1, len(charset)-1)
						result = result + charset[a]					
					print "[>] Random password :", result
					result = ''
		except:
			print "[>] Parameters error, check your syntax or type /password for man page"
	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /password"		
		print "[>] Syntax informations : /password <charset> <length> <number_pwd>"
		print "[>] To generate one or many random passwords."
		print "[>] <charset>    Number of charset, see table below"
		print "[>] <length>     Password length"
		print "[>] <number_pwd> Number of generated password, default is '1'"
		print "[>]"
		print "[>] Charsets :"
		print "[>] [1] Lower a -> z"
		print "[>] [2] Upper A -> Z"
		print "[>] [3] Decimal 0 -> 9"
		print "[>] [4] Lower + decimal a -> 9"
		print "[>] [5] Upper + decimal A -> 9"
		print "[>] [6] Lower + upper a -> Z"
		print "[>] [7] Lower + upper + decimal a -> A -> 9"
		print "[>] [8] abcdefghijklmnopqrstuvwxyz0123456789!:/;.,?@=+-}])[({%&*$"
		print "[>] [9] abcdefghijklmnopqrstuvwxyABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!:/;.,?@=+-}])[({%&*$"
		print "[>] [10] Hexadecimal 0 -> f"	 
	return xchat.EAT_XCHAT

def hashlist(word, word_eol, userdata):
	if len(word) == 2:
		if word[1] == "info":
			param = ['read', 'hashlist', 'info']
			data = []
			statut = db_sqlite(param, data)
			if statut == [] or statut == False:
				print "[>] Error, you don't have hashlist for the moment."
			else:
				print "[>]" + 60 * "-"
				print "[>] List of your hashlists :"				
				print "[>]             Name           Type        N# full       N# left    Success rate"
				count = 0
				stat = []
				for x in statut:
					x = list(x)
					count = count + 1
					if int(x[4]) == int(x[5]):
						percent = 0
						stat.append(percent)
					else:
						percent = (100 / int(x[4])) * int(x[5])
						stat.append(percent)
					print "[>] %0016s %14s      %09d     %09d     %11.2f" % (x[0], x[1], x[4], x[5], percent)
				global_stat = 0
				for x in stat:
					global_stat = global_stat + x
				global_stat = global_stat / count
				print "[>] Total hashlist : %s" % count
				print "[>] Total reversed : %.2f" % global_stat, "%"
	
		elif len(word) == 2 and word[1] == 'search':
			print "[>]" + 60 * "-"
			print "[>] Search hashlist :"
			print "[>] /hashlist search <string>"
			print "[>] <string>  Remplace by you request (max 16 char)"
	
	elif len(word) == 3 and word[1] == 'search':
		print "[>]" + 60 * "-"
		print "[>] Hashlist :"
		print "[>] Search : %s" % word[2]
		if len(word[2]) > 16:
			print "[>] Error, 16 char maximum please."
		else:
			param = ['read', 'hashlist', 'search']
			data = []
			data.append(word[2])
			statut = db_sqlite(param, data)
			if statut != []:
				print "[>] List of your hashlists :"				
				print "[>]             Name           Type        N# full       N# left    Success rate"
				count = 0
				stat = []
				for x in statut:
					x = list(x)
					count = count + 1
					if int(x[4]) == int(x[5]):
						percent = 0
						stat.append(percent)
					else:
						percent = (100 / int(x[4])) * int(x[5])
						stat.append(percent)
					print "[>] %0016s %14s      %09d     %09d     %11.2f" % (x[0], x[1], x[4], x[5], percent)
				global_stat = 0
				for x in stat:
					global_stat = global_stat + x
				global_stat = global_stat / count
				print "[>] Total hashlist : %s" % count
				print "[>] Total reversed : %.2f" % global_stat, "%"
			else:
				print "[>] No result found."
	elif len(word) == 5 and word[1] == 'add':
		error_lvl = 0
		link = word[4].split('/')
		link = link[3]
		print "[>]" + 60 * "-"
		print "[>] Import from pastebin.com %s" % word[3]
		#try:
		f = urllib2.urlopen('http://pastebin.com/download.php?i=%s' % link)
		datas = f.read()
		if 'jkUAIOE8owUXu8UXIhRLB9oHJsWBfOgJbZzncqHoF4A' in datas:
			error_lvl = 1
		if error_lvl < 1:
		#	try:
				data2 = datas.split('\n')
				param = ['write.hashlist']
				ran_int = random.randint(100000, 9999999)
				timing = time.asctime( time.localtime(time.time()))
				data = [str(link)+str(ran_int), word[2], word[3], timing, timing, len(data2), len(data2), datas]
				statut = db_sqlite(param, data)
				print statut					
					#output_path = db_sqlite(['read', 'config', 'input_path'], [' '])
					#file_name = "%spb-%s.txt" % (output_path[0], link)				
					#out = open(file_name, 'w')
					#out.write(data+'\n')
					#print "[>] Output in your default folder : %s" % file_name
					#print "[>] Import : Success"
		#		except:
		#			print "[>] Error with your path/file, check your rights."
		#			print "[>] Import : Echec !"
		#except:
		#	print "[>] Error with your URL, maybe site down."
		#	print "[>] Import : Echec !"
	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /hashlist"		
		print "[>] Syntax informations : /hashlist <param>"
		print "[>] To manage your hashlists."
		print "[>] <param>    See table below"
		print "[>]"
		print "[>] List of parameters :"
		print "[>] Parameter              info                  ie"
		print "[>] info         Show general infos of your    /hashlist info"
		print "[>]                      hashlists"
		print "[>] search          For search hashlist        /hashlist search for more info"
		print "[>] add_pb         For add hashlist from       /hashlist add_pb <name> <type> <url>"
		print "[>]                    Pastebin.com"
		print "[>] add_file       For add hashlist from       /hashlist add_file <name> <type> <path/file>"
		print "[>]                       a file"
		print "[>] delete            Delete hashlist          /hashlist delete <hashlist_ID>"
	return xchat.EAT_XCHAT	

def harvester(word, word_eol, userdata):
	## Thanks to Toxic (md5this.com) for grab mode
	## Original source code here : http://md5this.com/wordextract.py

	def StripTags(text):
		finished = 0
		while not finished:
			finished  =1
			start =  text.find("<")
			if start >= 0:
				stop = text[start:].find(">")
				if stop >= 0:
					text = text[:start] + text[start+stop+1:]
					finished = 0
		return text

	def grabber(min_len, max_len, target, output_file):
		print "[>] Retrieving Source:", target
		source = StripTags(urllib2.urlopen(target).read())
		words = re.findall("\w+", source)
		words = list(sets.Set(words))
		l = len(words)
		print "[>] Found:", l, "words"
		print "[>] Trimming words to length"
		for word in words:
			if not min_len <= len(word) <= max_len:
				words.remove(word)
		print "[>] Removed:", l-len(words), "words"
		print "[>] Writing:", len(words), "words to", output_file
		file = open(output_file,"a")
		for word in words:
			file.writelines(word+"\n")
		file.close()
		print "[>] Task complete"

	def google_api(start, query):
		query = urllib.urlencode({'q' : query})
		url = 'http://ajax.googleapis.com/ajax/services/search/web?v=1.0&rsz=8&start=%s&%s' % (start, query)
		search_results = urllib.urlopen(url)
		json = simplejson.loads(search_results.read())
		return json

	def catch_urls(json):
		results = json['responseData']['results']
		catched_urls = []
		for i in results:
			if i not in catched_urls:
				catched_urls.append(i['url'])
		return catched_urls

	def dorky(gdork):
		sorted_urls = []
		num_cycle = 0
		count = 0
		while count < 1:
			num_cycle = num_cycle + 1
			start = 0
			#dork = 'back filetype:sql'
			json = google_api(start, gdork)
	
			#for x in json['responseData']['cursor']['pages']:
			#	print x
			print "-" * 50
			print "Cycle numbers      : %s" % num_cycle
			print "Dork               : %s" % gdork 
			currentPageIndex = json['responseData']['cursor']['currentPageIndex']
			print "Current page index : %s" % currentPageIndex
			estimatedResultCount = json['responseData']['cursor']['estimatedResultCount']
			print "Result numbers     : %s" % estimatedResultCount
			pages = json['responseData']['cursor']['pages']
			num_pages = len(json['responseData']['cursor']['pages'])
			print "Page numbers       : %s" % num_pages
			if num_pages > 1:
				catched_urls = catch_urls(json)
				index_num = num_pages * 7
				for start in xrange(0, index_num, 8):
					json = google_api(start, gdork)
					catched_urls_tmp = catch_urls(json)
					catched_urls = catched_urls + catched_urls_tmp
	
			for x in catched_urls:
				if x not in sorted_urls:
					sorted_urls.append(x)
		
			print "Num catched URLs   : %s" % len(sorted_urls)
			#for x in sorted_urls:
			#	print x
			time.sleep(120)
			count = count + 1

	if len(word) >= 5 and word[1] == 'grab':
		min_len = int(word[2])
		max_len = int(word[3])
		target = word[4]
		if target[:7] != 'http://':
			target = 'http://' + target
		if len(word) == 5:
			file_name = random.randint(100000,999999)
			output_file = ".xchat2/crackme/output/wl-" + str(file_name) + ".txt"
		else:
			output_file = word[5]
		
		Thread(None, grabber, None, (min_len, max_len, target, output_file,), {}).start()

	if len(word) == 3 and word[1] == 'dork':
		Thread(None, dorky, None, (word[2],), {}).start()

	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /harvester"		
		print "[>] Syntax informations : /harvester <mode> <source> <output>"
		print "[>] To harvest plaintext from many sources."
		print "[>]"
		print "[>] Mode grab : To harvest plaintexts from web sites"
		print "[>] ie : /harvester grab <min_len> <max_len> <target> <output>"
		print "[>] <min_len>   Minumum length word"
		print "[>] <max_len>   Maximum length word"
		print "[>] <target>    Your web site target"
		print "[>] <output>    Output path & file name, if missing plugin put file in :"
		print "[>]             /home/user/.xchat2/crackme/output/ folder"
		print "[>]"
		print "[>] Mode dork : To use Google Dork"
		print "[>] ie : /harvester dork <dork>"
		print "[>] <dork>      Type your dork here (ie : filetype:sql)"
	return xchat.EAT_XCHAT

def whatis(word, word_eol, userdata):
	if len(word) > 1:
		stat = {'md5':0, 'md4':0, 'md2':0, 'sha1':0, 'sha224':0, 'sha256':0,
			'sha384':0, 'sha512':0, 'mysql3':0, 'mysql5':0, 'ntlm':0,
			'md5unix':0, 'sha256unix':0, 'sha512unix':0, 'lm':0, 'md5wp':0,
			'md5phpbb3':0, 'desunix':0, 'pwdump':0}
		hashes = word[1]
	
		def is_hexa(hashes):
			ishexa = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
				'a', 'b', 'c', 'd', 'e', 'f']
			for x in xrange(len(hashes)):
				if hashes[x] not in ishexa:
					return False
					break
			return True

		def is_md(hashes):
			hashes_l = len(hashes)
			hexa = is_hexa(hashes)
			if hashes_l == 32 and hexa == True:
				stat['md5'] = stat['md5'] + 1
				stat['md4'] = stat['md4'] + 1
				stat['md2'] = stat['md2'] + 1
				stat['ntlm'] = stat['ntlm'] + 1
				stat['lm'] = stat['lm'] + 1
				return True
			else:
				return False
	
		def is_sha(hashes):
			hashes_l = len(hashes)
			hexa = is_hexa(hashes)
			if hashes_l == 40 and hexa == True:
				stat['sha1'] = stat['sha1'] + 1
				stat['mysql5'] = stat['mysql5'] + 1
				return True
			if hashes_l == 56 and hexa == True:
				stat['sha224'] = stat['sha224'] + 1
				return True
			if hashes_l == 64 and hexa == True:
				stat['sha256'] = stat['sha256'] + 1
				return True
			if hashes_l == 96 and hexa == True:
				stat['sha384'] = stat['sha384'] + 1
				return True
			if hashes_l == 128 and hexa == True:
				stat['sha512'] = stat['sha512'] + 1
				return True		
			else:
				return False
	
		def is_unix(hashes):
			if hashes[:3] == '$1$' and len(hashes) == 34 and len(hashes[3:11]) == 8:
				stat['md5unix'] = stat['md5unix'] + 1
				return True
			if hashes[:3] == '$5$':
				stat['sha256unix'] = stat['sha256unix'] + 1
				return True
			if hashes[:3] == '$6$':
				stat['sha512unix'] = stat['sha512unix'] + 1
				return True
			else:
				return False
	
		def is_salted(hashes):
			hashes_l = len(hashes)
			hexa = is_hexa(hashes)
			if hashes_l == 13:
				if hexa == False:
					stat['desunix'] = stat['desunix'] + 1
					return True
			if hashes_l == 34:
				if hashes[:3] == '$P$':
					stat['md5wp'] = stat['md5wp'] + 1
					return True
				if hashes[:3] == '$H$':
					stat['md5phpbb3'] = stat['md5phpbb3'] + 1
					return True
				else:
					return False
			else:
				return False

		def is_classic(hashes):
			hashes_l = len(hashes)
			hexa = is_hexa(hashes)
			if hexa == True:
				if len(hashes) == 16:
					stat['lm'] = stat['lm'] + 1
					stat['mysql3'] = stat['mysql3'] + 1
					return True
				else:
					return False
			elif hexa == False:
				try:
					check = str(hashes[:32]) + str(hashes[33:])
				except:
					return False
				if len(check) == 64:
					stat['pwdump'] = stat['pwdump'] + 1
					return True
				else:
					return False		
			else:			
				return False

		def type_md(hashes):
			print "[>]" + 60 * "-"
			print "[>] Hash                : %s" % hashes
			print "[>] Length              : 32"
			print "[>] Probable hash type  : MD2, MD4, MD5, LM, NTLM"
			print "[>] Recommended tool(s) : Oclhashcat, Hashcat, Jtr, PasswordsPro, BarsWF, Cain."
			print "[>] You can use         : /md5 %s" % hashes
			print "[>] You can use         : /ntlm %s" % hashes
	
		def type_sha(hashes):
			print "[>]" + 60 * "-"
			print "[>] Hash : %s" % hashes
			print "[>] Length : %s" % len(hashes)
			if len(hashes) == 40:
				print "[>] Probable hash type  : SHA1, MySQL5"
				print "[>] Recommanded tool(s) : Oclhashcat, Hashcat, Jtr, PasswordsPro, Cain."
				print "[>] You can use         : /sha1 %s" % hashes
			if len(hashes) == 56:
				print "[>] Probable hash type  : SHA-224"
				print "[>] Recommanded tool(s) : ?"
			if len(hashes) == 64:
				print "[>] Probable hash type  : SHA-256"
				print "[>] Recommanded tool(s) : Jtr, PasswordsPro, Hashcat"
			if len(hashes) == 96:
				print "[>] Probable hash type  : SHA-384"
				print "[>] Recommanded tool(s) : Jtr"
			if len(hashes) == 128:
				print "[>] Probable hash type  : SHA-512, Whirlpool"
				print "[>] Recommanded tool(s) : Jtr"
	
		def type_unk(hashes):
			print "[>]" + 60 * "-"
			print "[>] Hash                : %s" % hashes
			print "[>] Length              : %s" % len(hashes)
			print "[>] Hexa                : %s" % is_hexa(hashes)
			print "[>] Probable hash type  : ?"
			print "[>] Recommanded tool(s) : ?"
		
		def type_unix(hashes):
			print "[>]" + 60 * "-"
			print "[>] Hash                : %s" % hashes
			print "[>] Length              : %s" % len(hashes)
			print "[>] Salt                : %s" % hashes[3:11]
			print "[>] Salt length         : %s" % len(hashes[3:11])
			if hashes[:3] == '$1$':
				print "[>] Probable hash type  : md5(unix)"
				print "[>] Recommanded tool(s) : Oclhashcat+, Hashcat, Jtr, PasswordsPro"
			if hashes[:3] == '$5$':
				print "[>] Probable hash type  : sha256(unix)"
				print "[>] Recommanded tool(s) : Jtr"
			if hashes[:3] == '$6$':
				print "[>] Probable hash type  : sha512(unix)"
				print "[>] Recommanded tool(s) : Jtr"
	
		def type_salted(hashes):
			print "[>]" + 60 * "-"
			print "[>] Hash                : %s" % hashes
			print "[>] Length              : %s" % len(hashes)
			if len(hashes) == 13 and is_hexa(hashes) == False:
				print "[>] Probable hash type  : des(unix)"
				print "[>] Recommanded tool(s) : PasswordsPro"
			if len(hashes) == 34:
				if hashes[:3] == '$P$':
					print "[>] Probable hash type  : PHPass, md5(wordpress)"
					print "[>] Recommanded tool(s) : Hashcat, Jtr, PasswordsPro"
				if hashes[:3] == '$H$':
					print "[>] Probable hash type  : md5(phpbb3)"
					print "[>] Recommanded tool(s) : Hashcat, Jtr, PasswordsPro"
			
		def type_classic(hashes):
			print "[>]" + 60 * "-"
			print "[>] Hash                : %s" % hashes
			print "[>] Length              : %s" % len(hashes)
			if len(hashes) == 16:
				if is_hexa(hashes) == True:
					print "[>] Probable hash type  : Mysql3 (old_password), LM"
					print "[>] Recommanded tool(s) : Oclhashcat, Hashcat, Jtr, PasswordsPro"
			if len(hashes) == 65:
				if hashes[32] == ':':
					lmntlm = hashes.split(':')
					print "[>] LM hash             : %s" % lmntlm[0]
					print "[>] NTLM hash           : %s" % lmntlm[1]
					print "[>] Probable hash type  : Pwdump format, LM:NTLM"
					print "[>] Recommanded tool(s) : Oclhashcat, Hashcat, Jtr, PasswordsPro"
		
		ismd = is_md(hashes)
		issha = is_sha(hashes)
		isunix = is_unix(hashes)
		issalted = is_salted(hashes)
		isclassic = is_classic(hashes)
	
		#print ismd, issha, isunix, issalted, isclassic  ##Only for debug
		#print stat                                      ##Only for debug
		if ismd == True and issha == False and isunix == False and issalted == False and isclassic == False:
			type_md(hashes)
		if ismd == False and issha == True and isunix == False and issalted == False and isclassic == False:
			type_sha(hashes)
		if ismd == False and issha == False and isunix == True and issalted == False and isclassic == False:
			type_unix(hashes)
		if ismd == False and issha == False and isunix == False and issalted == True and isclassic == False:
			type_salted(hashes)
		if ismd == False and issha == False and isunix == False and issalted == False and isclassic == True:
			type_classic(hashes)
		if ismd == False and issha == False and isunix == False and issalted == False and isclassic == False:
			type_unk(hashes)
	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /whatis"		
		print "[>] Syntax informations : /whatis <hash>"
		print "[>] Hash types identification"
		print "[>] <hash>     Remplace by your unknow hash"
	return xchat.EAT_XCHAT

def calculator(word, word_eol, userdata):
	Thread(None, calculator_run, None, (word, word_eol, userdata), {}).start()
	return xchat.EAT_XCHAT

def calculator_run(word, word_eol, userdata):
	list_type = ['md5', 'md2', 'md4', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ntlm', 'md5(unix)',
			'sha256(unix)', 'sha512(unix)', 'crc32', 'crc32b', 'lm', 'mysql3', 'mysql5', 'haval256',
			'haval224', 'haval192', 'haval160', 'haval128', 'tiger160', 'tiger128', 'tiger',
			'ripemd320', 'ripemd256', 'ripemd160', 'ripemd128', 'whirlpool', 'ghost', 'snefru256',
			'snefru128', 'md5(wordpress)', 'md5(pass.salt)', 'md5(salt.pass)', 'md2(pass.salt)', 'md2(salt.past)',
			'md4(pass.salt)', 'md4(salt.pass)', 'sha1(pass.salt)', 'sha1(salt.pass)', 'sha224(pass.salt)',
			'sha224(salt.pass)', 'sha256(pass.salt)', 'sha256(salt.pass)', 'sha384(pass.salt)', 'sha384(salt.pass)',
			'sha512(pass.salt)', 'sha512(salt.pass)',]
	
	salt_list = ['md5(pass.salt)', 'md5(salt.pass)', 'md2(pass.salt)', 'md2(salt.pass)', 'md4(pass.salt)', 'md4(salt.pass)',
			'sha1(pass.salt)', 'sha1(salt.pass)', 'sha224(pass.salt)', 'sha224(salt.pass)', 'sha256(pass.salt)',
			'sha256(salt.pass)', 'sha384(pass.salt)', 'sha384(salt.pass)', 'sha512(pass.salt)', 'sha512(salt.pass)',
			]
	if len(word) > 2:
		password = word[2]
		type_h = word[1]
		if len(word) >= 4:
			if type_h in salt_list:
				if len(word) == 4:
					salt = word[3]
					ite = 1
					isint = True
				elif len(word) == 5:
					salt = word[3]
					ite = word[4]
			else:
				try: ite = word[3]
				except:
					ite = 1
					isint = True
		if len(word) == 3:
			try:
				ite = word[3]
			except:
				ite = 1
				isint = True
		if ite != 1:
			try:
				ite = int(ite)
				isint = True
			except:
				isint = False

		if type_h in list_type and isint == True:
			if type_h == 'lm':
				data = password
				for x in xrange(ite):
					data = HashMaker.lm(data)
    			if type_h == 'mysql5':
				data = password
				for x in xrange(ite):
					data = HashMaker.mysql5(data)
    			if type_h == 'mysql3':
				data = password
				for x in xrange(ite):
					data = HashMaker.mysql3(data)
    			if type_h == 'whirlpool':
				data = password
				for x in xrange(ite):
					data = HashMaker.whirlpool(data)
    			if type_h == 'ghost':
				data = password
				for x in xrange(ite):
					data = HashMaker.ghost(data)
    			if type_h == 'snefru256':
				data = password
				for x in xrange(ite):
					data = HashMaker.snefru256(data)
    			if type_h == 'snefru128':
				data = password
				for x in xrange(ite):
					data = HashMaker.snefru128(data)
    			if type_h == 'crc32b':
				data = password
				for x in xrange(ite):
					data = HashMaker.crc32b(data)
    			if type_h == 'crc32':
				data = password
				for x in xrange(ite):
					data = HashMaker.crc32(data)
    			if type_h == 'haval256':
				data = password
				for x in xrange(ite):
					data = HashMaker.haval256(data)
    			if type_h == 'haval224':
				data = password
				for x in xrange(ite):
					data = HashMaker.haval224(data)
    			if type_h == 'haval192':
				data = password
				for x in xrange(ite):
					data = HashMaker.haval192(data)
    			if type_h == 'haval160':
				data = password
				for x in xrange(ite):
					data = HashMaker.haval160(data)
    			if type_h == 'haval128':
				data = password
				for x in xrange(ite):
					data = HashMaker.haval128(data)
    			if type_h == 'tiger160':
				data = password
				for x in xrange(ite):
					data = HashMaker.tiger160(data)
    			if type_h == 'tiger128':
				data = password
				for x in xrange(ite):
					data = HashMaker.tiger128(data)
    			if type_h == 'tiger':
				data = password
				for x in xrange(ite):
					data = HashMaker.tiger(data)
    			if type_h == 'ripemd320':
				data = password
				for x in xrange(ite):
					data = HashMaker.ripemd320(data)
    			if type_h == 'ripemd256':
				data = password
				for x in xrange(ite):
					data = HashMaker.ripemd256(data)
    			if type_h == 'ripemd160':
				data = password
				for x in xrange(ite):
					data = HashMaker.ripemd160(data)
    			if type_h == 'ripemd128':
				data = password
				for x in xrange(ite):
					data = HashMaker.ripemd128(data)
    			if type_h == 'md4':
				data = password
				for x in xrange(ite):
					data = HashMaker.md4(data)
    			if type_h == 'md2':
				data = password
				for x in xrange(ite):
					data = HashMaker.md2(data)
    			if type_h == 'sha512':
				data = password
				for x in xrange(ite):
					data = HashMaker.sha512(data)
    			if type_h == 'sha384':
				data = password
				for x in xrange(ite):
					data = HashMaker.sha384(data)
    			if type_h == 'sha256':
				data = password
				for x in xrange(ite):
					data = HashMaker.sha256(data)
    			if type_h == 'sha224':
				data = password
				for x in xrange(ite):
					data = HashMaker.sha224(data)
    			if type_h == 'sha1':
    				data = password
				for x in xrange(ite):
					data = HashMaker.sha1(data)
    			if type_h == 'md5':
				data = password
				for x in xrange(ite):
					data = HashMaker.md5(data)
			if type_h == 'md5(unix)':
				data = password
				for x in xrange(ite):
					salt = '$1$'
					chain = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
					for x in xrange(8):
						a = random.randint(1,62)
						salt = salt + chain[a-1]
					salt = salt + '$'
					data = crypt.crypt(data, salt)
			if type_h == 'sha256(unix)':
				data = password
				for x in xrange(ite):
					salt = '$5$'
					chain = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
					for x in xrange(8):
						a = random.randint(1,62)
						salt = salt + chain[a-1]
					salt = salt + '$'
					data = crypt.crypt(data, salt)
			if type_h == 'sha512(unix)':
				data = password
				for x in xrange(ite):
					salt = '$6$'
					chain = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
					for x in xrange(8):
						a = random.randint(1,62)
						salt = salt + chain[a-1]
					salt = salt + '$'
					data = crypt.crypt(data, salt)
			if type_h == 'md5(wordpress)':
				t_hasher = phpass.PasswordHash(8, False)
				data = password
				for x in xrange(ite):
					data = t_hasher.hash_password(data)
			if type_h == 'md5(pass.salt)':
				data = password
				data = data + salt
				for x in xrange(ite):
					data = HashMaker.md5(data)
					print data
			if type_h == 'md5(salt.pass)':
				data = password
				date = salt+data
				for x in xrange(ite):
					data = HashMaker.md5(data)
					
			if type_h == 'md2(pass.salt)':
				data = password
				data = data + salt
				for x in xrange(ite):
					data = HashMaker.md2(data)
			if type_h == 'md2(salt.pass)':
				data = password
				date = salt+data
				for x in xrange(ite):
					data = HashMaker.md2(data)
			if type_h == 'md4(pass.salt)':
				data = password
				data = data + salt
				for x in xrange(ite):
					data = HashMaker.md4(data)
			if type_h == 'md4(salt.pass)':
				data = password
				date = salt+data
				for x in xrange(ite):
					data = HashMaker.md4(data)
			if type_h == 'sha1(pass.salt)':
				data = password
				data = data + salt
				for x in xrange(ite):
					data = HashMaker.sha1(data)
			if type_h == 'sha1(salt.pass)':
				data = password
				date = salt+data
				for x in xrange(ite):
					data = HashMaker.sha1(data)
			if type_h == 'sha224(pass.salt)':
				data = password
				data = data + salt
				for x in xrange(ite):
					data = HashMaker.sha224(data)
			if type_h == 'sha224(salt.pass)':
				data = password
				date = salt+data
				for x in xrange(ite):
					data = HashMaker.sha224(data)
			if type_h == 'sha256(pass.salt)':
				data = password
				data = data + salt
				for x in xrange(ite):
					data = HashMaker.sha256(data)
			if type_h == 'sha256(salt.pass)':
				data = password
				date = salt+data
				for x in xrange(ite):
					data = HashMaker.sha256(data)
			if type_h == 'sha384(pass.salt)':
				data = password
				data = data + salt
				for x in xrange(ite):
					data = HashMaker.sha384(data)
			if type_h == 'sha384(salt.pass)':
				data = password
				date = salt+data
				for x in xrange(ite):
					data = HashMaker.sha384(data)
			if type_h == 'sha512(pass.salt)':
				data = password
				data = data + salt
				for x in xrange(ite):
					data = HashMaker.sha512(data)
			if type_h == 'sha512(salt.pass)':
				data = password
				date = salt+data
				for x in xrange(ite):
					data = HashMaker.sha512(data)
			if type_h == 'ntlm':
				data = password
				for x in xrange(ite):
					data = hashlib.new('md4', data.encode('utf-16le')).hexdigest()
			
			print "[>]" + 60 * "-"
			print "[>] String   : %s" % password
			if type_h in salt_list:
				print "[>] Salt     : %s" % salt
			print "[>] Type     : %s" % type_h
			print "[>] Round(s) : %s" % ite
			print "[>] Hash     : %s" % data

		elif isint == True:
			print "[>]" + 60 * "-"			
			print "[>] \0034Syntax error, unknow hash type\0034 %s" % type_h
			print "[>] Complet information here : /hash"
		else:
			print "[>]" + 60 * "-"			
			print "[>] \0034Syntax error, unknow round value\0034 %s" % ite
			print "[>] Complet information here : /hash"
	else:
		print "[>]" + 60 * "-"
		print "[>] Man page : /hash"		
		print "[>] Syntax informations : /hash <type> <string> <n°ite>"
		print "[>] To calculate hash"
		print "[>] <type>    : anyone in the Type list"
		print "[>] <string>  : Type your chain here"
		print "[>] <n°ite>   : Round numbers"
		print "[>]           : ie: (simple md5 aka md5() ) /hash md5 my_password"
		print "[>]           : (triple md5 aka md5(md5(md5))) ) /hash md5 my_password 3"
		print "[>] Type list :"
		print "[>]      crc32, crc32b, ghost, haval128, haval160, haval192, haval224,"
		print "[>]      haval256, lm,md2, md4, md5, md5(unix), ntlm, mysql3, mysql5,"
		print "[>]      ripemd128, ripemd160, ripemd256,ripemd320, sha1, sha224," 
		print "[>]      sha256, sha256(unix), sha384, sha512, sha512(unix), snefru128,"
		print "[>]      snefru256, tiger, tiger128, tiger160, whirlpool, md5(wordpress)"
		print "[>]      md5(pass.salt), md5(salt.pass), md4(pass.salt), md4(salt.pass),"
		print "[>]      md2(pass.salt), md2(salt.pass),'sha1(pass.salt)', 'sha1(salt.pass)',"
		print "[>]     'sha224(pass.salt)', 'sha224(salt.pass)', 'sha256(pass.salt)',"
		print "[>]     'sha256(salt.pass)', 'sha384(pass.salt)', 'sha384(salt.pass)',"
		print "[>]     'sha512(pass.salt)', 'sha512(salt.pass)'"
	
		
	return xchat.EAT_XCHAT


print "[>] CrackMe Plugin Version %s loaded" % __module_version__
xchat.hook_command("crackme", crackme, help="/crackme  : General informations on CrackMe Xchat2 plugin")
xchat.hook_command("md5", md5, help="/md5 <hash>  : Submit MD5 hash on public DBs")
xchat.hook_command("ntlm", ntlm, help="/ntlm <hash>  : Submit NTLM hash on public DBs")
xchat.hook_command("lm", pwdump, help="/lm <hash>  : Submit LM hash on public DBs")
xchat.hook_command("pwdump", pwdump, help="/pwdump <hash>  : Submit LM & NTLM hashes on public DBs")
xchat.hook_command("sha1", sha1, help="/sha1 <hash>  : Submit SHA-1 hash on public DBs")
xchat.hook_command("whatis", whatis, help="/whatis <hash>  : Statistical hashes identifier")
xchat.hook_command("len", length, help="/len <string>  : Chain length")
xchat.hook_command("hash", calculator, help="/hash <type> <string>  : Hash calculator, type /hash for more info")
xchat.hook_command("password", password, help="/password <charset> <length>  : Random password generator, type /password for more info")
xchat.hook_command("b64", edbase64, help="/b64 <param> <string>  : Encoder/Decoder Base64")
xchat.hook_command("rot13", rot13, help="/rot13 <param> <string>  : Encoder/Decoder ROT13")
xchat.hook_command("import", import_data, help="/import <site> <link>  : Import hashlist from pastebin website, type /import for more info")
xchat.hook_command("export", export_data, help="/export <site> <link>  : Export hashlist from pastebin website, type /export for more info")
xchat.hook_command("hashlist", hashlist, help="/hashlist  : Hashlists manager")
xchat.hook_command("harvester", harvester, help="/harvester  : Harvester mode, type /harvester for more informations")
