Having to remember which arguments to use and what to add can be quite a lot, especially with tools such as Impacket. Recently there’s this pull request which added autocompletion functionalities to NetExec (the successor to CrackMapExec), so I thought I’d enable autocompletion for Impacket, and other python command line tools which use argparse.

This guide will be aimed at the pipx installation of Impacket, the steps will be similar if your Impacket is installed with pip or just a local repository.

The process is quite straightforward, here’s an overview.

First, we need to ensure argcomplete is installed:

pip install argcomplete

Enable argcomplete automatically for all compatible scripts:

sudo activate-global-python-argcomplete

Add the argcomplete package to the tool by using pipx inject <name> argcomplete.

For Impacket, we will do:

pipx inject impacket argcomplete

Then, we will need to modify the files a little:

  • Add import argcomplete after import argparse
  • argcomplete.autocomplete(parser) should be added before options = parser.parse_args() and if len(sys.argv)==1:

The modified files should look something like this:

import argparse
import argcomplete

# Rest of the code

    argcomplete.autocomplete(parser)

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

	options = parser.parse_args()

# More code

Finally, run eval "$(register-python-argcomplete <name>)" to enable autocompletion.

This would be easy if the tool has a single __main__.py or cli.py or entry.py used to parse all arguments, such as the NetExec example earlier or Certipy. But the Impacket examples are a number of different tools, all with their own argparse and arguments, so it can be quite a pain to do it manually.

I have written a short script to simplify the process, I would highly recommend making a snapshot or backup of the files before running it.

#!/bin/bash

if [ $# -eq 0 ]; then
    echo "Usage: $0 <directory>"
    exit
fi

DIR=$1

COUNT=0

for file in "$DIR"/*.py; do
    # Check if the file contains 'import argparse'
    if grep -q "import argparse" "$file"; then
        # Insert 'import argcomplete' after 'import argparse'
        sed -i '/import argparse/a import argcomplete' "$file"
        # Check if 'if len(sys.argv) == 1:' exists in the file
        if grep -q '    if len(sys.argv) == 1:' "$file"; then
            sed -i '/    if len(sys.argv) == 1:/i \   argcomplete.autocomplete(parser)\n' "$file"
        elif grep -q '    if len(sys.argv)==1:' "$file"; then
            sed -i '/    if len(sys.argv)==1:/i \    argcomplete.autocomplete(parser)\n' "$file"
        fi
        ((COUNT++))
    fi
done

echo "$COUNT files modified."

The Impacket examples should be located at ~/.local/pipx/venvs/impacket/bin/ for pipx. Do not run it against ~/.local/bin/, it will remove the symlinks used by pipx.

The script is not perfect, we will still need to modify some files:

  • goldenPac.py needs to be indented at line 1045.
  • keylistattack.py needs to be indented at line 133.
  • kintercept.py: insert import argcomplete at line 29, insert argcomplete.autocomplete(parser) at line 268.
  • mqtt_check.py: insert argcomplete.autocomplete(parser) at line 69.
  • ntlmrelayx.py: insert argcomplete.autocomplete(parser) at line 395.
  • rdp_check.py needs to be indented at line 281.
  • ticketConverter.py: insert argcomplete.autocomplete(parser) at line 40.

Finally, activate argcomplete for the examples:

eval "$(register-python-argcomplete addcomputer.py)"
eval "$(register-python-argcomplete atexec.py)"
eval "$(register-python-argcomplete changepasswd.py)"
eval "$(register-python-argcomplete dcomexec.py)"
eval "$(register-python-argcomplete describeTicket.py)"
eval "$(register-python-argcomplete dpapi.py)"
eval "$(register-python-argcomplete DumpNTLMInfo.py)"
eval "$(register-python-argcomplete esentutl.py)"
eval "$(register-python-argcomplete exchanger.py)"
eval "$(register-python-argcomplete findDelegation.py)"
eval "$(register-python-argcomplete GetADUsers.py)"
eval "$(register-python-argcomplete getArch.py)"
eval "$(register-python-argcomplete Get-GPPPassword.py)"
eval "$(register-python-argcomplete GetNPUsers.py)"
eval "$(register-python-argcomplete getPac.py)"
eval "$(register-python-argcomplete getST.py)"
eval "$(register-python-argcomplete getTGT.py)"
eval "$(register-python-argcomplete GetUserSPNs.py)"
eval "$(register-python-argcomplete goldenPac.py)"
eval "$(register-python-argcomplete karmaSMB.py)"
eval "$(register-python-argcomplete keylistattack.py)"
eval "$(register-python-argcomplete kintercept.py)"
eval "$(register-python-argcomplete lookupsid.py)"
eval "$(register-python-argcomplete machine_role.py)"
eval "$(register-python-argcomplete mimikatz.py)"
eval "$(register-python-argcomplete mqtt_check.py)"
eval "$(register-python-argcomplete mssqlclient.py)"
eval "$(register-python-argcomplete mssqlinstance.py)"
eval "$(register-python-argcomplete net.py)"
eval "$(register-python-argcomplete netview.py)"
eval "$(register-python-argcomplete ntfs-read.py)"
eval "$(register-python-argcomplete ntlmrelayx.py)"
eval "$(register-python-argcomplete ping6.py)"
eval "$(register-python-argcomplete ping.py)"
eval "$(register-python-argcomplete psexec.py)"
eval "$(register-python-argcomplete raiseChild.py)"
eval "$(register-python-argcomplete rbcd.py)"
eval "$(register-python-argcomplete rdp_check.py)"
eval "$(register-python-argcomplete registry-read.py)"
eval "$(register-python-argcomplete reg.py)"
eval "$(register-python-argcomplete rpcdump.py)"
eval "$(register-python-argcomplete rpcmap.py)"
eval "$(register-python-argcomplete sambaPipe.py)"
eval "$(register-python-argcomplete samrdump.py)"
eval "$(register-python-argcomplete secretsdump.py)"
eval "$(register-python-argcomplete services.py)"
eval "$(register-python-argcomplete smbclient.py)"
eval "$(register-python-argcomplete smbexec.py)"
eval "$(register-python-argcomplete smbrelayx.py)"
eval "$(register-python-argcomplete smbserver.py)"
eval "$(register-python-argcomplete ticketConverter.py)"
eval "$(register-python-argcomplete ticketer.py)"
eval "$(register-python-argcomplete tstool.py)"
eval "$(register-python-argcomplete wmiexec.py)"
eval "$(register-python-argcomplete wmipersist.py)"
eval "$(register-python-argcomplete wmiquery.py)"

But wait, those are just a temporary activation, we will need to add that again every reboot or .*rc file is sourced. For a more permanent solution, add the lines above into your .zshrc or .bashrc so that autocomplete is permanently activated.

There is also another solution using register-python-argcomplete psexec.py >> ~/.zshrc, which seems to be faster than adding all those eval lines, it creates the following functions in the file, instead of running the commands one by one, I have added them all to the same functions, so just paste them in:

# Run something, muting output or redirecting it to the debug stream
# depending on the value of _ARC_DEBUG.
# If ARGCOMPLETE_USE_TEMPFILES is set, use tempfiles for IPC.
__python_argcomplete_run() {
    if [[ -z "${ARGCOMPLETE_USE_TEMPFILES-}" ]]; then
        __python_argcomplete_run_inner "$@"
        return
    fi
    local tmpfile="$(mktemp)"
    _ARGCOMPLETE_STDOUT_FILENAME="$tmpfile" __python_argcomplete_run_inner "$@"
    local code=$?
    cat "$tmpfile"
    rm "$tmpfile"
    return $code
}

__python_argcomplete_run_inner() {
    if [[ -z "${_ARC_DEBUG-}" ]]; then
        "$@" 8>&1 9>&2 1>/dev/null 2>&1
    else
        "$@" 8>&1 9>&2 1>&9 2>&1
    fi
}

_python_argcomplete() {
    local IFS=$'\013'
    if [[ -n "${ZSH_VERSION-}" ]]; then
        local completions
        completions=($(IFS="$IFS" \
            COMP_LINE="$BUFFER" \
            COMP_POINT="$CURSOR" \
            _ARGCOMPLETE=1 \
            _ARGCOMPLETE_SHELL="zsh" \
            _ARGCOMPLETE_SUPPRESS_SPACE=1 \
            __python_argcomplete_run "${words[1]}") )
        _describe "${words[1]}" completions -o nosort
    else
        local SUPPRESS_SPACE=0
        if compopt +o nospace 2> /dev/null; then
            SUPPRESS_SPACE=1
        fi
        COMPREPLY=($(IFS="$IFS" \
            COMP_LINE="$COMP_LINE" \
            COMP_POINT="$COMP_POINT" \
            COMP_TYPE="$COMP_TYPE" \
            _ARGCOMPLETE_COMP_WORDBREAKS="$COMP_WORDBREAKS" \
            _ARGCOMPLETE=1 \
            _ARGCOMPLETE_SHELL="bash" \
            _ARGCOMPLETE_SUPPRESS_SPACE=$SUPPRESS_SPACE \
            __python_argcomplete_run "$1"))
        if [[ $? != 0 ]]; then
            unset COMPREPLY
        elif [[ $SUPPRESS_SPACE == 1 ]] && [[ "${COMPREPLY-}" =~ [=/:]$ ]]; then
            compopt -o nospace
        fi
    fi
}
if [[ -z "${ZSH_VERSION-}" ]]; then
    complete -o nospace -o default -o bashdefault -F _python_argcomplete nxc
    complete -o nospace -o default -o bashdefault -F _python_argcomplete certipy
    complete -o nospace -o default -o bashdefault -F _python_argcomplete addcomputer.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete atexec.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete changepasswd.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete dcomexec.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete describeTicket.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete dpapi.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete DumpNTLMInfo.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete esentutl.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete exchanger.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete findDelegation.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete GetADUsers.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete getArch.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete Get-GPPPassword.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete GetNPUsers.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete getPac.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete getST.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete getTGT.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete GetUserSPNs.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete goldenPac.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete karmaSMB.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete keylistattack.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete kintercept.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete lookupsid.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete machine_role.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete mimikatz.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete mqtt_check.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete mssqlclient.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete mssqlinstance.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete net.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete netview.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete ntfs-read.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete ntlmrelayx.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete ping6.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete ping.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete psexec.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete raiseChild.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete rbcd.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete rdp_check.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete registry-read.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete reg.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete rpcdump.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete rpcmap.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete sambaPipe.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete samrdump.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete secretsdump.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete services.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete smbclient.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete smbexec.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete smbrelayx.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete smbserver.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete ticketConverter.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete ticketer.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete tstool.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete wmiexec.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete wmipersist.py
    complete -o nospace -o default -o bashdefault -F _python_argcomplete wmiquery.py
else
    compdef _python_argcomplete nxc
    compdef _python_argcomplete certipy
    compdef _python_argcomplete addcomputer.py
    compdef _python_argcomplete atexec.py
    compdef _python_argcomplete changepasswd.py
    compdef _python_argcomplete dcomexec.py
    compdef _python_argcomplete describeTicket.py
    compdef _python_argcomplete dpapi.py
    compdef _python_argcomplete DumpNTLMInfo.py
    compdef _python_argcomplete esentutl.py
    compdef _python_argcomplete exchanger.py
    compdef _python_argcomplete findDelegation.py
    compdef _python_argcomplete GetADUsers.py
    compdef _python_argcomplete getArch.py
    compdef _python_argcomplete Get-GPPPassword.py
    compdef _python_argcomplete GetNPUsers.py
    compdef _python_argcomplete getPac.py
    compdef _python_argcomplete getST.py
    compdef _python_argcomplete getTGT.py
    compdef _python_argcomplete GetUserSPNs.py
    compdef _python_argcomplete goldenPac.py
    compdef _python_argcomplete karmaSMB.py
    compdef _python_argcomplete keylistattack.py
    compdef _python_argcomplete kintercept.py
    compdef _python_argcomplete lookupsid.py
    compdef _python_argcomplete machine_role.py
    compdef _python_argcomplete mimikatz.py
    compdef _python_argcomplete mqtt_check.py
    compdef _python_argcomplete mssqlclient.py
    compdef _python_argcomplete mssqlinstance.py
    compdef _python_argcomplete net.py
    compdef _python_argcomplete netview.py
    compdef _python_argcomplete ntfs-read.py
    compdef _python_argcomplete ntlmrelayx.py
    compdef _python_argcomplete ping6.py
    compdef _python_argcomplete ping.py
    compdef _python_argcomplete psexec.py
    compdef _python_argcomplete raiseChild.py
    compdef _python_argcomplete rbcd.py
    compdef _python_argcomplete rdp_check.py
    compdef _python_argcomplete registry-read.py
    compdef _python_argcomplete reg.py
    compdef _python_argcomplete rpcdump.py
    compdef _python_argcomplete rpcmap.py
    compdef _python_argcomplete sambaPipe.py
    compdef _python_argcomplete samrdump.py
    compdef _python_argcomplete secretsdump.py
    compdef _python_argcomplete services.py
    compdef _python_argcomplete smbclient.py
    compdef _python_argcomplete smbexec.py
    compdef _python_argcomplete smbrelayx.py
    compdef _python_argcomplete smbserver.py
    compdef _python_argcomplete ticketConverter.py
    compdef _python_argcomplete ticketer.py
    compdef _python_argcomplete tstool.py
    compdef _python_argcomplete wmiexec.py
    compdef _python_argcomplete wmipersist.py
    compdef _python_argcomplete wmiquery.py
fi

Here it is in action:

argcomplete-demo.gif argcomplete-demo.png