Skip to main content

Busca por domínios, subdomínios, portas | Script automatizados | Solyd One

  • Busca por domínios, subdomínios, portas | Script automatizados | Solyd One

Dependências para executar


Instalar dependências (Debian/Ubuntu)

# atualizar lista de pacotes
sudo apt update

# instalar nmap, parallel, xargs/awk/sed/grep/cut (já vêm com coreutils, mas incluímos nmap e parallel)
sudo apt install -y nmap parallel

# instalar Go (se não tiver) — necessário para instalar assetfinder/httpx/httprobe via 'go install'
sudo apt install -y golang-go

# garantir que $GOPATH/bin esteja no PATH (exemplo)
echo 'export GOPATH=$HOME/go' >> ~/.profile
echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.profile
source ~/.profile

Instalar ferramentas Go (assetfinder, httpx, httprobe)

# instala assetfinder
go install github.com/tomnomnom/assetfinder@latest

# instala httpx (recomendado)
go install github.com/projectdiscovery/httpx/cmd/httpx@latest

# instala httprobe (opcional, fallback)
go install github.com/tomnomnom/httprobe@latest

# confirmar instalações
command -v assetfinder httpx httprobe nmap parallel || true

Observação: se seu go instalar executáveis em $GOPATH/bin ou $HOME/go/bin, garantiu que esse diretório esteja no PATH (veja o passo acima).


Salvar o script no arquivo

Cole o conteúdo do script (que eu forneci anteriormente) num arquivo chamado discover_and_scan_report.sh. Um modo rápido de colar (no terminal):

# cria o arquivo e abre no nano (ou edite no seu editor preferido)
nano discover_and_scan_report.sh
# -> cole o conteúdo do script, salve (Ctrl+O) e saia (Ctrl+X)

Ou, se você tiver o script pronto localmente, copie-o para o diretório desejado.

Tornar executável

chmod +x discover_and_scan_report.sh

Comandos para executar o script (exemplos)

Executar com opções mínimas (paralelismo 5, relatórios CSV+HTML, timeout padrão)

./discover_and_scan_report.sh -d exemplo.com

Executar especificando paralelismo (ex.: 10 jobs simultâneos)

./discover_and_scan_report.sh -d exemplo.com -p 10

Executar apenas gerando CSV

./discover_and_scan_report.sh -d exemplo.com -r csv

Executar apenas gerando HTML

./discover_and_scan_report.sh -d exemplo.com -r html

Aumentar timeout por host (ex.: 600s) — útil se hosts forem lentos

./discover_and_scan_report.sh -d exemplo.com -t 600

Mostrar ajuda do script

./discover_and_scan_report.sh -h

Comandos úteis para checar/abrir resultados

# ver primeiros 30 subdomínios descobertos
head -n 30 subdomains.txt

# ver hosts vivos
cat live_hosts.txt

# ver parte do output do nmap (grepable)
less nmap_results.gnmap

# ver linhas com portas abertas
cat open_ports.txt

# abrir relatório HTML no navegador (local)
xdg-open nmap_report.html 2>/dev/null || echo "Abra nmap_report.html no seu navegador"

Nota sobre privilégios do sistema

  • O script usa nmap -p- -T4 -Pn (scans sem ping). Alguns tipos de scan (por exemplo -sS) requerem privilégios de root para enviar pacotes SYN.

  • Se você quiser rodar nmap com scans que exigem privilégios, execute o script com sudo (cuidado e apenas com autorização):

    sudo ./discover_and_scan_report.sh -d exemplo.com

Script gerado por IA

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'

# discover_and_scan_report.sh
# Uso: ./discover_and_scan_report.sh -d dominio.com [-p 10] [-r csv|html|both|none] [--parallel-mode]
# por padrão: parallelism=5, reports=both

print_usage() {
cat <<EOF
Uso: $0 -d DOMINIO [opções]

Opções:
-d DOMINIO Domínio alvo (ex: exemplo.com) (obrigatório)
-p PARALLEL Nº de jobs paralelos (default: 5)
-r REPORT Tipo de relatório: csv, html, both, none (default: both)
-t TIMEOUT Timeout por nmap em segundos (default: 300)
-h Mostrar esta ajuda
EOF
}

# Defaults
PARALLELISM=5
REPORT="both"
TIMEOUT=300
DOMAIN=""

while getopts "d:p:r:t:h" opt; do
case "$opt" in
d) DOMAIN="$OPTARG" ;;
p) PARALLELISM="$OPTARG" ;;
r) REPORT="$OPTARG" ;;
t) TIMEOUT="$OPTARG" ;;
h) print_usage; exit 0 ;;
*) print_usage; exit 1 ;;
esac
done

if [[ -z "$DOMAIN" ]]; then
echo "Erro: domínio obrigatório."
print_usage
exit 1
fi

# Files
SUBS_FILE="subdomains.txt"
LIVE_FILE="live_hosts.txt"
NMAP_OUT="nmap_results.gnmap" # we'll use grepable-like output appended
OPEN_PORTS="open_ports.txt"
CSV_OUT="nmap_report.csv"
HTML_OUT="nmap_report.html"
TMP_DIR="$(mktemp -d)"
LOG_PREFIX="[discover_and_scan]"

# Colors
RED="\033[0;31m"; GREEN="\033[0;32m"; YELLOW="\033[1;33m"; BLUE="\033[0;34m"; NC="\033[0m"

info(){ echo -e "${GREEN}${LOG_PREFIX} $*${NC}"; }
warn(){ echo -e "${YELLOW}${LOG_PREFIX} $*${NC}"; }
err(){ echo -e "${RED}${LOG_PREFIX} $*${NC}"; }
step(){ echo -e "${BLUE}${LOG_PREFIX} ==> $*${NC}"; }

cleanup() { rm -rf "$TMP_DIR"; }
trap cleanup EXIT

# Dependency checks
MISSING=()
for cmd in assetfinder nmap xargs awk sed grep cut sort tr; do
if ! command -v "$cmd" &>/dev/null; then
MISSING+=("$cmd")
fi
done

# Check probe tools
if command -v httpx &>/dev/null; then
PROBER="httpx"
elif command -v httprobe &>/dev/null; then
PROBER="httrobe" # typo-safe fallback label; we'll call httprobe if available
if ! command -v httprobe &>/dev/null; then
MISSING+=("httpx/httprobe")
fi
else
MISSING+=("httpx/httprobe")
fi

# Prefer GNU parallel if available for best progress UI
if command -v parallel &>/dev/null; then
HAS_PARALLEL=true
else
HAS_PARALLEL=false
fi

if [ ${#MISSING[@]} -ne 0 ]; then
err "Faltando dependências: ${MISSING[*]}. Instale-as antes de continuar."
exit 1
fi

#########################
# 1) Descobrir subdomínios
#########################
step "Descobrindo subdomínios com assetfinder..."
assetfinder --subs-only "$DOMAIN" 2>/dev/null | grep -E "\." | sed 's/^\s*//;s/\s*$//' | tr '[:upper:]' '[:lower:]' | sort -u > "$SUBS_FILE"
SUB_COUNT=$(wc -l < "$SUBS_FILE" || echo 0)
info "Subdomínios encontrados: $SUB_COUNT -> $SUBS_FILE"

if [[ $SUB_COUNT -eq 0 ]]; then
warn "Nenhum subdomínio encontrado. Saindo."
exit 0
fi

#########################
# 2) Detectar hosts vivos (httpx ou httprobe)
#########################
step "Detectando hosts HTTP(s) vivos com ${PROBER}"
> "$LIVE_FILE"

if command -v httpx &>/dev/null; then
# httpx: saída "https://host" etc; usamos -silent e threads
httpx -l "$SUBS_FILE" -silent -threads 50 -status-code -o "$TMP_DIR/httpx_out.txt" 2>/dev/null || true
# extrai host
awk '{print $1}' "$TMP_DIR/httpx_out.txt" | sed -E 's#^https?://##' | cut -d'/' -f1 | sort -u > "$LIVE_FILE"
else
# httprobe
sed 's#^#http://#; s#//$##' "$SUBS_FILE" | httprobe -s -c 50 > "$TMP_DIR/httprobe_out.txt" 2>/dev/null || true
sed -E 's#^https?://##' "$TMP_DIR/httprobe_out.txt" | cut -d'/' -f1 | sort -u > "$LIVE_FILE"
fi

LIVE_COUNT=$(wc -l < "$LIVE_FILE" || echo 0)
if [[ "$LIVE_COUNT" -eq 0 ]]; then
warn "Nenhum host HTTP(s) detectado como vivo. Saindo."
exit 0
fi
info "Hosts vivos detectados: $LIVE_COUNT -> $LIVE_FILE"

#########################
# 3) Varredura nmap paralela (com progresso)
#########################
step "Iniciando varredura nmap (todas portas) com paralelismo = $PARALLELISM"
> "$NMAP_OUT"
> "$OPEN_PORTS"

# nmap command per host
nmap_cmd() {
local host="$1"
# usamos -oG- para saída "grepable" pelo stdout
# -Pn evita ping; -p- = todas portas; --host-timeout para limitar por-host
timeout "$TIMEOUT" nmap -p- -T4 --min-rate=500 -Pn "$host" -oG - 2>/dev/null || true
}

export -f nmap_cmd

TOTAL=$(wc -l < "$LIVE_FILE")
COUNTER_FILE="$TMP_DIR/counter.txt"
echo 0 > "$COUNTER_FILE"

# Helper: increment counter (used por cada job). This avoids race by using flock if available otherwise append.
increment_counter() {
if command -v flock &>/dev/null; then
(
flock 9
cnt=$(cat "$COUNTER_FILE")
cnt=$((cnt+1))
echo "$cnt" > "$COUNTER_FILE"
) 9<> "$COUNTER_FILE"
else
# simple append/read (possible race but acceptable)
cnt=$(cat "$COUNTER_FILE")
cnt=$((cnt+1))
echo "$cnt" > "$COUNTER_FILE"
fi
}

export COUNTER_FILE
export -f increment_counter

# Worker wrapper (used by parallel/xargs) that runs the nmap_cmd and appends to global file and increments progress.
worker() {
host="$1"
# run nmap, capture output
out="$(nmap_cmd "$host")"
# ensure we add a header to the output so grepable lines are preserved
if [[ -n "$out" ]]; then
# write atomically
printf "%s\n" "$out" >> "$NMAP_OUT"
printf "%s\n" "$out" >> "$TMP_DIR/last_out.txt"
fi
# mark progress
increment_counter
}
export -f worker

# Run with GNU parallel if available (nice progress bar)
if $HAS_PARALLEL; then
step "Usando GNU parallel para paralelizar e exibir barra de progresso..."
# parallel will run worker and show a progress bar; we use --lb to preserve line buffering
parallel -j "$PARALLELISM" --bar --lb worker :::: "$LIVE_FILE"
else
# fallback: xargs -P with manual progress monitor
step "GNU parallel não encontrado — usando xargs -P com monitor de progresso simples."
# spawn xargs jobs in background
cat "$LIVE_FILE" | xargs -n1 -P "$PARALLELISM" -I {} bash -c 'worker "$@"' _ {} &
XARGS_PID=$!

# progress loop: print every 1s
while kill -0 "$XARGS_PID" 2>/dev/null; do
completed=$(cat "$COUNTER_FILE" || echo 0)
printf "\rProgress: %d/%d hosts completed" "$completed" "$TOTAL"
sleep 1
done
wait "$XARGS_PID" || true
completed=$(cat "$COUNTER_FILE" || echo 0)
printf "\rProgress: %d/%d hosts completed\n" "$completed" "$TOTAL"
fi

step "Varredura concluída. Extraindo portas abertas..."
# grep por linhas que contêm "/open/" no output grepable
grep "/open/" "$NMAP_OUT" || true > "$OPEN_PORTS" # if none, file may be empty

#########################
# 4) Gerar CSV e HTML (parsing do nmap grepable)
#########################
step "Gerando relatórios: CSV/HTML (opção = $REPORT)"

# CSV header
cat > "$CSV_OUT" <<'CSVHDR'
host,ip,port,proto,state,service,extra
CSVHDR

# Parse grepable lines like:
# Host: 93.184.216.34 (example.com) Ports: 80/open/tcp//http///,443/closed/tcp//ssl/// Ignored...
# We iterate cada linha com Ports: ... e separe por vírgula cada porta
grep -E "^Host:" "$NMAP_OUT" | while IFS= read -r line; do
# extrai IP
ip=$(echo "$line" | awk '{print $2}')
# extrai host entre parênteses (se houver)
host=$(echo "$line" | sed -n 's/^Host:[[:space:]]\+[0-9.]\+\s\*(\([^)]*\)).*/\1/p')
if [[ -z "$host" ]]; then
# nenhuma hostname conhecido, usar ip como host
host="$ip"
fi
# extrai campo Ports:
ports_field=$(echo "$line" | sed -n 's/.*Ports: \(.*\)\t.*$/\1/p')
# fallback: se não houver tab, pega tudo após 'Ports:'
if [[ -z "$ports_field" ]]; then
ports_field=$(echo "$line" | sed -n 's/.*Ports: \(.*\)$/\1/p')
fi
# cada porta separada por ','
IFS=',' read -ra PORTS_ARR <<< "$ports_field"
for p in "${PORTS_ARR[@]}"; do
# Formato de p: 80/open/tcp//http/// -> split por '/'
# garantir remoção de espaços
p_trim=$(echo "$p" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
# Proteção se campo vazio
if [[ -z "$p_trim" ]]; then continue; fi
port=$(echo "$p_trim" | cut -d'/' -f1)
state=$(echo "$p_trim" | cut -d'/' -f2)
proto=$(echo "$p_trim" | cut -d'/' -f3)
service=$(echo "$p_trim" | cut -d'/' -f5)
extra=$(echo "$p_trim" | cut -d'/' -f6- | tr -d '\n' | sed 's/"/""/g')
# write CSV line (quote fields)
printf '"%s","%s","%s","%s","%s","%s","%s"\n' "$host" "$ip" "$port" "$proto" "$state" "$service" "$extra" >> "$CSV_OUT"
done
done

info "CSV gerado: $CSV_OUT"

# HTML generation (simples)
if [[ "$REPORT" == "html" || "$REPORT" == "both" ]]; then
step "Gerando HTML: $HTML_OUT"
cat > "$HTML_OUT" <<'HTMLHEAD'
<!doctype html>
<html lang="pt-BR">
<head>
<meta charset="utf-8"/>
<title>Relatório Nmap</title>
<style>
body { font-family: Arial, sans-serif; padding: 20px; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background: #f2f2f2; }
tr:nth-child(even){ background: #fbfbfb; }
.closed { color: #999; }
.open { color: #060; font-weight: bold; }
</style>
</head>
<body>
<h1>Relatório Nmap - $(date)</h1>
<p>Alvo: ${DOMAIN}</p>
<table>
<thead><tr><th>Host</th><th>IP</th><th>Porta</th><th>Proto</th><th>Estado</th><th>Serviço</th><th>Extra</th></tr></thead>
<tbody>
HTMLHEAD

# read CSV (skip header) and convert to table rows
tail -n +2 "$CSV_OUT" | while IFS= read -r csvline; do
# remove surrounding quotes and split by "," (CSV we generated is quoted and has no embedded commas except in extra)
# use awk to parse safe
host=$(echo "$csvline" | awk -F'","' '{gsub(/^"/,"",$1); print $1}')
ip=$(echo "$csvline" | awk -F'","' '{print $2}')
port=$(echo "$csvline" | awk -F'","' '{print $3}')
proto=$(echo "$csvline" | awk -F'","' '{print $4}')
state=$(echo "$csvline" | awk -F'","' '{print $5}')
service=$(echo "$csvline" | awk -F'","' '{print $6}')
extra=$(echo "$csvline" | awk -F'","' '{gsub(/"$/,"",$7); print $7}')
# escape HTML minimal
esc(){ echo "$1" | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g; s/"/\&quot;/g'; }
state_class=$( [[ "$state" == "open" ]] && echo "open" || echo "closed" )
cat >> "$HTML_OUT" <<HTMLROW
<tr>
<td>$(esc "$host")</td>
<td>$(esc "$ip")</td>
<td>$(esc "$port")</td>
<td>$(esc "$proto")</td>
<td class="${state_class}">$(esc "$state")</td>
<td>$(esc "$service")</td>
<td>$(esc "$extra")</td>
</tr>
HTMLROW
done

cat >> "$HTML_OUT" <<'HTMLFOOT'
</tbody>
</table>
</body>
</html>
HTMLFOOT

info "HTML gerado: $HTML_OUT"
fi

step "Resumo final:"
echo " - Subdomínios: $SUBS_FILE"
echo " - Hosts vivos: $LIVE_FILE"
echo " - Saída nmap (grepable): $NMAP_OUT"
echo " - Linhas com portas abertas: $OPEN_PORTS"
echo " - CSV: $CSV_OUT"
[[ -f "$HTML_OUT" ]] && echo " - HTML: $HTML_OUT"

info "Pronto. Lembre-se de executar apenas contra alvos autorizados."