(SRDorking) - Simple Recon - Dorking v1.0.0

Ferramenta de dorking em múltiplos motores de busca para coleta de URLs em operações de OSINT e reconhecimento.

Simple Recon URL

Ferramenta de dorking que utiliza multiplos motores de busca para coleta de URLs. O operador informa uma ou mais dorks - a partir de uma string livre (-d, --dork), um arquivo (-D, --dork-file), do catálogo embutido por categoria (--dork-category) ou via stdin - e a ferramenta roda cada dork contra várias fontes de busca em paralelo, devolvendo a união das URLs encontradas. Diferente do resto da família SimpleRecon, não há crawler, não há host semente: a única fonte de dados são os índices das fontes de busca.

[!NOTE] Construída em Python assíncrono, sem lógica de resolução DNS e sem dependências de shell externas. Derivada do SimpleReconURL, reorientada de "uma URL semente" para "uma dork, muitas fontes".

Author:   Cleiton Pinheiro a.k.a MrCl0wn
Blog:     https://blog.mrcl0wn.com
GitHub:   https://github.com/MrCl0wnLab
Twitter:  https://twitter.com/MrCl0wnLab

[!CAUTION] Aviso legal: usar o SimpleReconDorking para atacar alvos sem consentimento mútuo prévio é ilegal. É responsabilidade do usuário final obedecer a todas as leis municipais, estaduais e federais aplicáveis. Os desenvolvedores não assumem qualquer responsabilidade por mau uso ou dano causado por este programa. O catálogo de dorks embutido (config/dork_categorys.json) existe para auditoria e descoberta de exposições em ativos sob sua responsabilidade - não é uma lista de alvos.

Índice


Instalação

git clone https://github.com/osintbrazuca/SimpleReconDorking
cd SimpleReconDorking
pip install -r requirements.txt

Dependências (requirements.txt):

Pacote Para que serve
httpx[socks] Cliente HTTP assíncrono usado por todas as fontes ([socks] habilita proxy socks5:// - veja Proxy)

Todo o resto (sqlite3, asyncio, re, json, ...) é biblioteca padrão do Python 3.10+.

Docker

Roda sem precisar de Python instalado. Dois caminhos de build, mesma imagem, e os argumentos da CLI passam direto:

docker build -t docker/simplerecondorking -f docker/Dockerfile .

# B) direto do GitHub, sem checkout local
docker build -t docker/simplerecondorking - < docker/Dockerfile.remote

# execução (o que vem depois do nome da imagem vai para o simplerecondorking.py)
docker run --rm docker/simplerecondorking -d 'site:target.com ext:sql'

Veja docker/README.md para as opções completas de build, montagem das chaves de API, persistência de resultados (volume do --db) e registro do --watch.


Chaves de API

[!IMPORTANT] As chaves ficam em config/api_keys.json, que está no gitignore justamente para não ser commitado por acidente. Nunca versione esse arquivo preenchido.

{
    "brave": "",
    "github_token": "",
    "intelx_key": "",
    "publicwww": ""
}
Chave Fonte Onde conseguir
brave brave https://brave.com/search/api/
github_token github https://github.com/settings/tokens (escopo public_repo)
intelx_key intelx https://intelx.io/account?tab=developer
publicwww publicwww https://publicwww.com/api.html (plano pago para export=urls)

Toda fonte sem chave configurada retorna um conjunto vazio silenciosamente - nunca interrompe o restante da execução.


Uso

# listar todos comandos
python simplerecondorking.py --help

# uma dork solta
python simplerecondorking.py -d 'site:target.com ext:sql'

# uma categoria inteira do catálogo embutido, com {TARGET} preenchido
python simplerecondorking.py -t target.com --dork-category files

# listar o que existe
python simplerecondorking.py --list-sources
python simplerecondorking.py --list-profiles
python simplerecondorking.py --list-category
python simplerecondorking.py --list-examples

Exemplos em contexto de OSINT

# auditar exposições comuns de um domínio próprio
python simplerecondorking.py -t meudominio.com \
  --dork-category files,config,git_exposure,backup -o json --outfile audit.json

# caçar menções de um domínio em pastes/código, sem operadores de busca
python simplerecondorking.py -d 'meudominio.com' --category code,leak

# combinar uma dork avulsa com uma categoria inteira, no mesmo run
python simplerecondorking.py -d 'intitle:"index of" site:{TARGET}' -t meudominio.com \
  --dork-category panels

# encadear com httpx para confirmar quais URLs ainda respondem
python simplerecondorking.py -t meudominio.com --dork-category files --no-banner | httpx -silent

# rodar atrás de um pool de proxies, trocando ao ser bloqueado
python simplerecondorking.py -t meudominio.com --dork-category files \
  --proxy-file proxies.txt --proxy-rotate round-robin --proxy-rotate-status 403,429


Entrada de dorks

Toda dork é um template: pode conter o placeholder {TARGET}, substituído pelo valor de -t/--target. Uma dork sem {TARGET} é enviada literalmente. Isso é útil para buscar uma assinatura na web inteira, sem alvo.

Flag O que faz
-d, --dork QUERY Uma única dork
-D, --dork-file FILE Arquivo com uma dork por linha (# comenta, linhas em branco ignoradas)
--dork-category CAT[,CAT...] Uma ou mais categorias do catálogo embutido (config/dork_categorys.json)
--stdin Lê dorks adicionais de stdin, uma por linha
-t, --target TARGET Domínio, host, IP ou texto que substitui {TARGET} nas dorks selecionadas
python simplerecondorking.py -d 'site:target.com ext:log' -v 1 --profile fast

As três primeiras fontes são aditivas: dá para combinar -d com --dork-category no mesmo comando. Uma dork que precisa de {TARGET} e não recebe -t é pulada com aviso, nunca enviada com um {TARGET} literal. Isso seria ruído puro em toda fonte.

echo 'site:target.com ext:log' | python simplerecondorking.py --stdin
cat mydorks.txt | python simplerecondorking.py --stdin -t target.com

Catálogo embutido de dorks

O arquivo config/dork_categorys.json é a fonte única do catálogo embutido. A chave raiz dorks contém as categorias. Cada categoria possui:

Campo Tipo Finalidade
description string Resumo exibido por --list-category
operators lista de strings Dorks com operadores como site:, inurl:, intitle: e ext:
operators_out lista de strings Versões equivalentes sem operadores de busca

Estrutura mínima de uma categoria:

{
  "dorks": {
    "api": {
      "description": "API surface and machine-readable specs on {TARGET}",
      "operators": [
        "site:{TARGET} inurl:swagger"
      ],
      "operators_out": [
        "{TARGET} \"swagger\""
      ]
    }
  }
}

Para adicionar uma categoria, inclua uma nova chave dentro de dorks e preencha as duas famílias. Não é necessário alterar código Python. JSON não aceita comentários nem vírgula depois do último item. Um arquivo ausente ou inválido resulta em um catálogo vazio.

Categoria Cobre
files Listagens de diretório e arquivos soltos indexados
config Arquivos de configuração/ambiente que vazam segredos (.env, .ini, web.config...)
panels Painéis de admin, login e gerenciamento
errors Erros de aplicação e stack traces expostos
cloud Buckets S3/GCS/Azure Blob referenciando o alvo
docs Documentos sensíveis indexados (PDF, XLS, DOC, SQL, backup)
git_exposure .git, .svn, .DS_Store, manifestos de dependência expostos
backup Arquivos e dumps de backup alcançáveis
api Specs OpenAPI/Swagger, GraphQL, rotas /api/
remote_access Painéis de VPN, RDP, Citrix, Jenkins, GitLab expostos
cameras Interfaces de câmeras IP/webcam expostas

Seleção da família

O valor de -t/--target define qual lista da categoria será usada:

Valor de --target Família selecionada
Domínio ou host, como example.com ou app.example.com operators
Endereço IPv4 ou IPv6 operators
Texto livre, como Acme Corporation operators_out
Não informado As dorks com {TARGET} são ignoradas com aviso

Essa seleção permite pesquisar organizações, produtos, pessoas e frases sem produzir um operador site: inválido. Fontes que não suportam operadores ainda aplicam Dork.plain_terms() quando recebem uma dork avulsa com operadores.

python simplerecondorking.py --list-category
python simplerecondorking.py -t target.com --dork-category files,config,backup
python simplerecondorking.py -t 'Acme Corporation' --dork-category api,docs

Fontes de busca

python simplerecondorking.py --list-sources

Toda fonte recebe a mesma dork e devolve URLs; a diferença é o quanto cada uma entende de operadores de busca (site:, ext:, inurl:...). Fontes marcadas free-text only não entendem operadores - a dork é convertida automaticamente para termos soltos (Dork.plain_terms()) antes de ser enviada, e isso é registrado em -v 1.

Web

Fonte Exige chave Observações
yahoo Não Suporte completo a operadores; a fonte grande que ainda responde site: sem desafio
bing Não Suporte completo; melhor esforço, costuma servir desafio Cloudflare Turnstile
google Não Scraping de google.com/search: melhor esforço, geralmente bloqueado - use googlecse
googlecse Não Google via Custom Search Engines públicos: cobertura real do Google, sem chave
duckduckgo Não Endpoint lite (sem JS); melhor esforço, sensível a rate limit por IP
startpage Não Resultados do Google via proxy de privacidade; melhor esforço, scraping
brave Sim API oficial da Brave Search, suporte completo a operadores
marginalia Não Índice independente e não comercial; free-text only
searx Não Metabusca federada SearXNG sobre ~72 instâncias públicas (consulta JSON e HTML e une os dois); alto rendimento quando uma instância responde, mas disponibilidade muito variável
searxbrowser Não As mesmas instâncias SearXNG, mas em Chromium headless: resolve os desafios JS (Anubis) que bloqueiam o searx. Lento, exige Playwright
seznam Não Seznam.cz - fonte dominante na República Tcheca, índice próprio, paginação confirmada
naver Não Naver - fonte dominante na Coreia do Sul (~55-60% do mercado), índice próprio, página única
daum Não Daum (Kakao) - 2ª fonte coreana, índice próprio, página única
yahoojp Não Yahoo Japan - operação independente (LY Corporation), mesma base do Yahoo global, paginação confirmada
yandex Não Yandex - índice próprio, operadores exclusivos (host:, rhost:, date: por faixa); melhor esforço
baidu Não Baidu - maior fonte chinesa; melhor esforço, geralmente serve verificação anti-bot
mojeek Não Mojeek - índice próprio; precisa de navegador (requirements-browser.txt), veja abaixo
ecosia Não Ecosia - índice em parceria com a Qwant; precisa de navegador, Cloudflare Turnstile (depende muito de reputação de IP)
swisscows Não Swisscows - índice suíço, foco em privacidade; precisa de navegador (SPA renderizado via JS, sem desafio)
so Não So.com (360 Search) - fonte chinesa (Qihoo 360); precisa de navegador, pagina clicando no botão real "próxima página"
dogpile Não Dogpile - metabusca (Infospace/System1); precisa de navegador, free-text only (operadores disparam um bloqueio WAF), melhor esforço (IP é rate-limitado rápido)
aol Não AOL Search - portal que redireciona para o backend do Yahoo (YHS); suporte completo a operadores, sem navegador

[!NOTE] seznam, naver, daum e yahoojp foram validados ao vivo (2026-08): devolvem links de resultado reais direto no HTML estático, sem exigir JavaScript. aol também: sua busca redireciona para o backend do Yahoo (YHS, "Yahoo Hosted Search"), então herda o mesmo mecanismo de link direto sem navegador. Várias outras fontes pesquisadas nessa rodada - Qwant, MetaGer, Sogou, Ask.com, Lycos, You.com, WebCrawler - foram descartados do catálogo após teste ao vivo via HTTP puro; nenhum foi testado via navegador (ao contrário de mojeek/ecosia/swisscows/so/dogpile abaixo), então um deles pode muito bem se comportar como dogpile se alguém quiser investigar. mojeek, ecosia, swisscows, so e dogpile também bloqueavam via HTTP puro, mas por motivos que um navegador headless resolve - em vez de descartar, foram implementados com Playwright (veja Mojeek, Ecosia, Swisscows, So.com e Dogpile: bypass via navegador).

Código

Fonte Exige chave Observações
grep_app Não Busca de código no grep.app; free-text only, rate limit agressivo (429)
github Sim Busca de código no GitHub; free-text only, a melhor fonte para rotas de API

Código-fonte

Fonte Exige chave Observações
publicwww Sim Busca no HTML/JS/CSS das páginas, não no texto; free-text only

Jurídico

Fonte Exige chave Observações
jusbrasil Não JusBrasil - consulta processual pública (nome/CPF/CNPJ/nº de processo); free-text only, melhor esforço (desafio Cloudflare)

Vazamentos

Fonte Exige chave Observações
intelx Sim Seletores de URL do phonebook do Intelligence X: vazamentos, pastes, dumps; free-text only

Mojeek, Ecosia, Swisscows, So.com e Dogpile: bypass via navegador

Cinco fontes só funcionam de verdade com um navegador de verdade por trás - uma requisição HTTP simples nunca chega ao resultado. Cada uma bloqueia por um motivo diferente:

Fonte Por que HTTP puro falha Como é resolvido
mojeek Checkbox ALTCHA (prova de trabalho client-side) Clique forçado no checkbox + espera pela verificação; token chv reaproveitado nas páginas seguintes
ecosia Cloudflare Turnstile (avaliação comportamental/fingerprint) Espera passiva o desafio resolver sozinho (sem clique), com fallback de clique se um checkbox aparecer
swisscows Sem desafio nenhum - é só um SPA renderizado inteiramente via JavaScript Carrega a página e espera o JS renderizar; sem clique nem verificação
so SPA renderizado via JS e URL real do resultado escondida num atributo data-mdurl, não no href visível (que é um wrapper de redirecionamento so.com/link?m=...) Renderiza a página e lê data-mdurl; pagina clicando no botão real "próxima página" (#snext) em vez de montar a URL com o psid na mão - esse token é gerado por sessão e uma URL construída manualmente não é garantia de funcionar
dogpile Bloqueio direto (403) via requisição HTTP simples; e um WAF da CloudFront bloqueia especificamente site:/filetype:/inurl: na query (confirmado: dois-pontos em termo qualquer passa, esses operadores especificamente não) Renderiza via navegador (passa limpo, HTTP 202); toda dork é rebaixada para termos livres antes de ser enviada - aqui isso não é só "melhor cobertura", é a diferença entre funcionar e ser bloqueado
# preparação única (dependência opcional, download do navegador ~150MB)
pip install -r requirements-browser.txt
playwright install chromium

python simplerecondorking.py -d 'site:target.com' --sources mojeek
python simplerecondorking.py -d 'site:target.com' --sources ecosia
python simplerecondorking.py -d 'site:target.com' --sources swisscows
python simplerecondorking.py -d 'site:target.com' --sources so
python simplerecondorking.py -d 'target.com' --sources dogpile
python simplerecondorking.py -d 'target.com' --profile browser --pages 3

[!NOTE] Sem o Playwright instalado, as cinco fontes se autodesabilitam com uma única mensagem em -v 1 e o restante da ferramenta funciona normalmente - mesmo contrato do browser do SimpleReconURL. mojeek, ecosia e dogpile são melhor esforço, em graus diferentes: mojeek e dogpile bloqueiam por reputação de IP num nível "tudo ou nada" (403 direto quando bloqueado - no caso do dogpile, algumas requisições seguidas da mesma máquina já bastam para disparar); ecosia depende muito mais de reputação de IP/rede porque o Cloudflare Turnstile avalia sinais de automação do navegador além do IP - um Chromium headless rodando de um IP de datacenter tende a nunca passar, mesmo com técnicas comuns de stealth (testado), mas resolve automaticamente numa sessão de navegador real, sem interação nenhuma, segundo relato direto do operador. swisscows e so não têm esse problema - validados ao vivo com resultados reais e paginação funcionando de forma consistente (so precisou trocar a condição de espera de load para domcontentloaded: a página é pesada o bastante para o evento load travar sem necessidade).


Perfis

Grupos de fontes prontas, definidos em config/profiles.json.

python simplerecondorking.py --list-profiles
Perfil Fontes
fast googlecse, yahoo, duckduckgo, seznam, aol - keyless e respondem de forma confiável
web Toda fonte de busca web geral (inclui as de melhor esforço)
keyless Toda fonte que não exige chave
code grep_app, github
intel publicwww, intelx (ambos exigem chave)
browser mojeek, ecosia, swisscows, so, dogpile - precisam de requirements-browser.txt
full Toda fonte registrada
python simplerecondorking.py -d 'site:target.com ext:sql' --profile fast

--profile tem precedência sobre --sources/--category. --exclude é aplicado depois de qualquer seleção, incluindo perfis.


Presets de execução

Como no resto da família SimpleRecon, --config FILE carrega um JSON com valores default para as flags - só é aplicado onde a flag ainda está no default do argparse, então flags explícitas na linha de comando sempre vencem.

cp config/run_config.example.json myrun.json
# edite myrun.json com suas preferências
python simplerecondorking.py -t target.com --dork-category files --config myrun.json

Todas as flags de proxy são chaves válidas do preset (proxy, proxy_file, proxy_source, proxy_profile, proxy_rotate, proxy_rotate_secs, proxy_rotate_reqs, proxy_rotate_status, proxy_rotate_body, proxy_rotate_regex, proxy_retries, proxy_ban_after, proxy_fallback_direct) - o que importa, porque uma linha de comando com pool e rotação fica impronunciável. O mesmo vale para user_agent/ua_file/ua_source/ua_profile e header/header_file/header_source/header_profile, e para o bloco options de um perfil em config/profiles.json.

{
  "proxy_file": "proxies.txt",
  "proxy_rotate": "round-robin",
  "proxy_rotate_status": "403,429",
  "proxy_ban_after": 2
}

[!NOTE] proxy aceita tanto uma string ("http://a:8080") quanto uma lista (["http://a:8080", "http://b:8080"]) - presets escritos antes de --proxy virar repetível continuam funcionando.


Filtros

Por padrão, nada é filtrado: uma dork como "target.com" site:pastebin.com deve mesmo devolver URLs em pastebin.com - é o que foi pedido. Os quatro filtros abaixo são opt-in e combinam entre si como AND (uma URL só sobrevive se passar em todos os filtros ativos); dentro de --filter-string (várias strings separadas por vírgula) o critério é OR - basta casar uma. O que qualquer filtro rejeita não é descartado: vai para extras (visível em -v 3 e persistido no --db).

Flag Mantém a URL se...
--filter-host HOST está em HOST ou um subdomínio dele
--filter-string LIST contém qualquer uma destas strings (case-insensitive)
--filter-regex PATTERN casa com este regex (um padrão só - use | para alternativas, já que vírgula é sintaxe comum de regex)
--filter-file FILE contém qualquer string do arquivo (um termo por linha; soma ao --filter-string)
# sem filtro: mantém tudo que a fonte devolveu
python simplerecondorking.py -d '"target.com" site:pastebin.com' -t target.com

# com --filter-host: hits fora do host vão para extras
python simplerecondorking.py -t target.com --dork-category files --filter-host target.com -v 3

python simplerecondorking.py -t target.com --dork-category files --filter-string ".pdf,.doc,.xls"
python simplerecondorking.py -t target.com --dork-category files --filter-regex '\.(sql|env)$'
python simplerecondorking.py -t target.com --dork-category files --filter-file keywords.txt

Paginação e rate limiting

--pages N (padrão 2, teto 20) controla quantas páginas de resultado cada par (fonte, dork) percorre. Toda fonte paginada ainda aplica seu próprio teto interno - uma cota de API gratuita ou um limiar de anti-bot é quase sempre mais restritivo do que o pedido aqui. --rate-limit N limita requisições concorrentes por fonte; --threads N é o portão de concorrência para os pares (fonte, dork) em voo.

python simplerecondorking.py -t target.com --dork-category files --pages 5
python simplerecondorking.py -d 'site:target.com' --rate-limit 2 --timeout 15

Proxy

--proxy URL é repetível e --proxy-file FILE soma um arquivo por cima, então o pool se monta de qualquer uma das duas formas (ou das duas juntas). Credenciais podem vir embutidas (http://user:senha@host:porta) - elas nunca aparecem nos logs, que mostram http://***@host:porta.

python simplerecondorking.py -d 'site:target.com' --proxy socks5://127.0.0.1:9050
python simplerecondorking.py -d 'site:target.com' --proxy http://a:8080 --proxy http://b:8080
python simplerecondorking.py -t target.com --dork-category files --proxy-file proxies.txt

Direcionamento

--proxy-source e --proxy-profile decidem quem usa o pool - combinam entre si como AND:

Flag Restringe o pool a...
--proxy-source LIST só estas fontes (nomes separados por vírgula); sem a flag, todas usam o pool
--proxy-profile LIST execuções onde o --profile ativo está nesta lista; sem --profile na linha de comando, a guarda nunca abre e o pool fica configurado mas sem uso
# só mojeek e dogpile (as duas fontes mais sujeitas a bloqueio de IP) usam o proxy
python simplerecondorking.py -t target.com --sources mojeek,dogpile \
  --proxy http://a:8080 --proxy-source mojeek,dogpile

# o proxy só vale quando --profile browser está ativo nesta execução
python simplerecondorking.py -t target.com --profile browser \
  --proxy http://a:8080 --proxy-profile browser

Rotação

Flag Efeito
--proxy-rotate MODE sticky (padrão) usa um até falhar; round-robin percorre o pool; random sorteia por requisição
--proxy-rotate-secs N Troca depois de N segundos no mesmo proxy
--proxy-rotate-reqs N Troca depois de N requisições no mesmo proxy
--proxy-rotate-status L Troca ao receber estes códigos (403,429,503)
--proxy-rotate-body L Troca ao casar estas strings no corpo (case-insensitive)
--proxy-rotate-regex PATTERN Troca ao casar este regex no corpo (um padrão só, mesma razão do --filter-regex)
--proxy-retries N Trocas por requisição antes de desistir (padrão 2)
--proxy-ban-after N Tira do pool após N falhas seguidas (padrão 3); um sucesso zera a contagem
--proxy-fallback-direct Permite sair direto quando o pool esgota

Os gatilhos são cumulativos - --proxy-rotate round-robin --proxy-rotate-status 429 é combinação válida. Falha de conexão (proxy morto) conta como gatilho por si só, senão o modo de falha mais comum nunca seria detectado.

python simplerecondorking.py -t target.com --dork-category files \
  --proxy-file proxies.txt --proxy-rotate round-robin \
  --proxy-rotate-status 403,429 --proxy-ban-after 2

[!IMPORTANT] Quando todo o pool é banido, a execução aborta com exit 2 em vez de continuar. Sair direto nesse momento vazaria o IP real justamente quando o operador acreditava estar protegido - por isso é preciso pedir explicitamente com --proxy-fallback-direct.

Duas assimetrias que valem conhecer

Fontes de navegador não rotacionam no meio. O Playwright fixa o proxy no launch, então mojeek, ecosia, swisscows, so e dogpile recebem um proxy por fetch. Não é só custo: o psid do so e o token chv do mojeek estão ligados ao IP que os obteve, então trocar no meio corromperia o resultado. Consequência contra-intuitiva: --proxy-rotate-status 403 não resgata o dogpile, que é justo quem mais devolve 403. O que essas cinco fazem é reportar o bloqueio ao pool, então o --proxy-ban-after retira o proxy queimado para as tarefas seguintes.

Duas fontes fixam um proxy por fetch de propósito. googlecse busca o cse_token num IP e o gasta na chamada seguinte - trocar no meio produziria o 403 que se queria evitar. intelx abre um job de busca cobrado no servidor, e repetir a requisição cobraria a cota duas vezes. Ambas usam proxy normalmente, só não rotacionam dentro da mesma execução.


Dark web / Tor (.onion)

Seis fontes de serviços ocultos entram no catálogo na categoria darkweb:

Fonte Observação (tudo verificado ao vivo)
ahmia Único do grupo que aplica blacklist de material abusivo; código aberto. Sem paginação — devolve o conjunto inteiro numa resposta
torch Índice antigo e amplo, sem filtro. Não pagina: --pages é ignorado de propósito
tor66 Pagina de verdade; também traz um diretório de serviços novos
tordex O de maior cobertura nos testes (175 links contra 68 do torch), pagina de verdade
onionsearch Não precisa de Tor - indexa serviços ocultos mas é consultado por HTTPS comum. Pagina de verdade. Protegido por Cloudflare (veja abaixo)
tor66web Não precisa de Tor - o mesmo índice do tor66, pelo host clearnet tor66.org. Mais raso (15 contra 33 links na mesma query), mas responde sem daemon nenhum

Duas delas dispensam Tor, e por motivos diferentes.

O tor66web consulta o mesmo índice do tor66 pelo host clearnet. Vale saber a diferença medida na mesma query:

Endpoint Do clearnet Via Tor
tor66 (.onion) inalcançável (não há DNS) 33 links
tor66web (tor66.org) 15 links 0 - devolve a home

Ou seja: com Tor disponível o tor66 rende mais que o dobro; sem Tor, o tor66web é o que ainda responde. Rodar os dois juntos é válido e a deduplicação global cuida da sobreposição.

[!WARNING] Não mande o tor66web pelo Tor. Diferente do onionsearch, o tor66.org responde a um nó de saída com HTTP 200 e a própria home — zero resultados, sem erro, nada detectável. Passar --proxy socks5h://... nele gasta requisição e não ganha nada; para sair por Tor use o tor66, que fala com o host .onion e rende mais.

Já o onionsearch devolve URLs .onion mas é consultado em onionsearchengine.com por HTTPS comum, então funciona sem Tor nenhum. Em compensação está atrás do Cloudflare — de um IP de datacenter ele responde 403 (bloqueio de reputação de IP, não desafio resolvível; de um IP residencial costuma passar direto). Quando isso acontece, a saída é mandar só ele pelo Tor:

# só o onionsearch sai pelo Tor; funciona porque ele participa do pool
# normal do --proxy (as outras quatro fontes darkweb nunca usam esse pool)
python simplerecondorking.py -d 'gov.br' --sources onionsearch \
  --proxy socks5h://127.0.0.1:9050 --proxy-source onionsearch -v 1
[*] [proxy] 1/1 proxy(ies) alive, 0 rotation(s), 0 failure(s), mode=sticky
[*] [onionsearch] page=1: 7 url(s)
[*] [onionsearch] page=2: 4 url(s)
[*] [onionsearch] "gov.br" +9 urls

[+] Total unique URLs found: 9

http://redditkrqlgqkdcybwfw37p43vn3tf3fdhdmnqqrsitf247puday35ad.onion/r/law
http://kyb5vrehqma6gsmsrg4jpl5fl6quwhvakq4qui3kffebtpc5r4i54hid.onion/counterfeit-usd-banknotes-on-the-dark-web/index.html
...

O --proxy-source onionsearch é o que impede o proxy de vazar para as outras fontes; com uma fonte só na execução ele é redundante, mas vira essencial ao misturar:

# onionsearch pelo Tor, yahoo direto, na mesma execução
python simplerecondorking.py -d 'minhaempresa.com' --sources onionsearch,yahoo \
  --proxy socks5h://127.0.0.1:9050 --proxy-source onionsearch

A própria ferramenta imprime essa dica ao levar 403.

Um endereço .onion não tem registro DNS público — quem resolve é o próprio daemon Tor. Por isso essas fontes exigem SOCKS5 com DNS remoto (socks5h://, o equivalente ao --socks5-hostname do curl) e só funcionam com um Tor rodando localmente.

# confirme que o Tor está de pé
curl --socks5-hostname localhost:9050 https://ifconfig.ca

# o padrão já é socks5h://127.0.0.1:9050 - não precisa de flag
python simplerecondorking.py -d 'minhaempresa.com' --category darkweb
python simplerecondorking.py -d 'minhaempresa.com' --profile tor -v 1

# porta diferente (o Tor Browser escuta na 9150, não na 9050)
python simplerecondorking.py -d 'vazamento' --category darkweb \
  --tor-proxy socks5h://127.0.0.1:9150

[!IMPORTANT] --tor-proxy e --proxy são independentes e convivem numa execução só. As fontes darkweb nunca usam o pool do --proxy (nem --proxy-rotate, nem --proxy-ban-after), e as fontes clearnet nunca usam o --tor-proxy. Rodar --sources ahmia,yahoo --proxy http://a:8080 faz o ahmia sair por Tor e o yahoo pelo proxy, ao mesmo tempo.

Sem Tor acessível, as quatro fontes REQUIRES_TOR se comportam como as fontes de navegador sem Playwright: contribuem zero, imprimem uma dica do que fazer e não derrubam a execução.

[*] [ahmia] Tor not reachable at socks5h://127.0.0.1:9050 - is the Tor daemon running?

--no-tor: pular as fontes que exigem daemon

Numa máquina sem Tor, essa dica aparece uma vez por fonte por dork — o plano é o produto cartesiano, então --profile full com 10 dorks rende 40 linhas idênticas. O --no-tor tira as quatro da seleção antes do plano ser montado:

python simplerecondorking.py -d 'teste' --profile full --no-tor

O contador Sources: do cabeçalho cai em 4 e a barra de progresso deixa de contar tarefas que nunca poderiam produzir nada.

[!IMPORTANT] A flag chaveia em REQUIRES_TOR, não na categoria darkweb. São seis fontes darkweb e só quatro precisam de daemon: onionsearch e tor66web indexam .onion por HTTP clearnet e continuam rodando. São justamente as que ainda respondem sem Tor — filtrar por categoria removeria exatamente o que interessa a quem usa a flag.

# roda só onionsearch + tor66web
python simplerecondorking.py -d 'minhaempresa.com' --profile tor --no-tor

O padrão é desligado de propósito: a ferramenta não consegue distinguir "não tenho daemon" de "meu daemon caiu agora", e descartar cobertura darkweb em silêncio é o palpite errado para quem usa Tor. Pedir explicitamente uma fonte Tor junto com --no-tor (--sources ahmia --no-tor) esvazia a seleção e para com exit 2; se sobrar alguma fonte (--sources ahmia,yahoo --no-tor), a execução segue e o skip é registrado numa linha.

Se aparecer aviso de SOCKS faltando, o extra do httpx não foi instalado: pip install 'httpx[socks]'.

[!NOTE] As cinco são free-text only — a query vai como texto puro, sem site:/ext:. Foram verificadas só com busca textual, então marcar suporte a operadores seria chute. Vale o mesmo enquadramento do resto do projeto: o uso previsto é auditar exposição de ativos sob sua responsabilidade (credencial vazada, menção à sua marca), não descoberta de alvos.


User-Agent

--ua é um alias curto de --user-agent (mesmo destino, os dois funcionam). Por padrão, sem nenhuma das duas, cada requisição sorteia um User-Agent de navegador real de assets/txt/user_agents.txt - o UA literal do projeto (SimpleReconDorking/1) recebe bloqueio instantâneo em quase toda fonte.

python simplerecondorking.py -d 'site:target.com' --ua "Mozilla/5.0 (compatível)"

--ua-file: um pool em vez de um valor só

--ua-file FILE lê um User-Agent por linha; com mais de um, um é sorteado por tarefa (fonte, dork) - não por requisição dentro da mesma tarefa. Se --ua-file e --ua/--user-agent forem passados juntos, o arquivo vence.

python simplerecondorking.py -t target.com --dork-category files --ua-file meus_uas.txt

Direcionamento

--ua-source/--ua-profile restringem quem recebe o UA customizado (arquivo ou valor único) - mesmo par AND de --proxy-source/--proxy-profile. Fora do direcionamento, a fonte volta ao sorteio automático de sempre.

# só mojeek recebe o UA customizado; as demais sorteiam normalmente
python simplerecondorking.py -t target.com --sources mojeek,yahoo \
  --ua "Mozilla/5.0 (Android 14; Mobile)" --ua-source mojeek

Headers

--header 'JSON' manda cabeçalhos HTTP extras como um objeto JSON - nome e valor como string:

python simplerecondorking.py -d 'site:target.com' \
  --header '{"user-agent": "android", "Cookie": "guest_id_marketing=v1%3A1787"}'

--header-file FILE lê o mesmo formato de um arquivo; se os dois forem passados juntos, mesclam por chave e --header vence em colisão. Os headers extras são mesclados por último, depois de qualquer coisa que a própria fonte já monte (inclusive o resultado de browser_headers()/--ua-file) - por isso --header consegue sobrescrever até o User-Agent, não importa a caixa (user-agent sobrepõe User-Agent normalmente).

python simplerecondorking.py -d 'site:target.com' --header-file headers.json

Direcionamento

--header-source/--header-profile, mesmo par AND das demais famílias de direcionamento (proxy, UA). Fora do direcionamento, a fonte não recebe headers extras nenhum.

python simplerecondorking.py -t target.com --sources aol,yahoo \
  --header '{"X-Custom": "1"}' --header-source aol

[!NOTE] Nas 5 fontes de navegador (mojeek, ecosia, swisscows, so, dogpile), os headers extras vão para o extra_http_headers do Playwright. Se --header também setar user-agent, o cabeçalho HTTP enviado reflete o valor do --header, mas o navigator.userAgent visível para o JavaScript da página continua o do --ua/--ua-file (ou o sorteado automaticamente) - o Playwright não sincroniza os dois. Combinar os dois de propósito para forjar UAs diferentes por camada não foi testado contra um anti-bot de verdade.


Mapa de dorks: grafo JSON e visualização HTML

--network-map inclui um grafo nodes/edges no JSON: uma estrela de três níveis alvo → dork → URL, mais uma aresta direta alvo → filtrado para URLs excluídas por um --filter-* ativo. --network-html FILE escreve uma página HTML autocontida com vis-network para explorar o grafo interativamente, junto com qualquer -o escolhido.

python simplerecondorking.py -t target.com --dork-category files --network-html map.html
python simplerecondorking.py -t target.com --dork-category files -o json --network-map --outfile out.json

Relatório Markdown

-o markdown gera um relatório com resumo, lista completa de URLs, extras e contribuição por fonte e por dork.

python simplerecondorking.py -t target.com --dork-category files -o markdown --outfile report.md

Banco de dados: persistência SQLite

Um --db FILE funciona como armazenamento e fonte de comparação. Sem --db-news, salva a execução inteira (URLs, e em -v 3 também as URLs externas). Com --db-news, compara contra tudo que já foi salvo para aquele -t/--target e imprime + salva só o que é novo.

python simplerecondorking.py -t target.com --dork-category files --db recon.db
python simplerecondorking.py -t target.com --dork-category files --db recon.db --db-news

# inspecionar
python simplerecondorking.py --db recon.db --db-list urls
python simplerecondorking.py --db recon.db --db-list extras
python simplerecondorking.py --db-list history   # log de comandos, config/system.db fixo

Esquema

CREATE TABLE urls (
    id, seed, url, source, dork, first_seen
);
CREATE TABLE extras (
    id, seed, type, value, first_seen
);

config/system.db é um banco separado e fixo (log de comandos + jobs do --watch), nunca passado por --db.


Monitoramento contínuo (--watch)

# registra o comando atual num agendamento cron (armazenado em config/system.db)
python simplerecondorking.py -t target.com --dork-category files --db target.db --quiet \
  --watch-add "0,15,30,45 * * * *"

# roda o agendador (jobs vencidos no mesmo minuto rodam em paralelo)
python simplerecondorking.py --watch

# gerencia os jobs
python simplerecondorking.py --watch-list
python simplerecondorking.py --watch-del 3
python simplerecondorking.py --watch-clear

Formatos de saída

-o {txt,json,csv,ndjson,html,markdown} (padrão txt). ndjson é uma linha JSON por URL - ideal para pipes; html é o mapa interativo; markdown é o relatório humano.

python simplerecondorking.py -t target.com --dork-category files -o json --outfile result.json
python simplerecondorking.py -d 'site:target.com' --no-banner > urls.txt

Encadeando com outras ferramentas

# probing HTTP
python simplerecondorking.py -t target.com --dork-category files --no-banner | httpx -silent

# scanner de vulnerabilidades
python simplerecondorking.py -t target.com --dork-category files --no-banner | httpx -silent | nuclei -t exposures/ -silent

# string-x (strx) - github.com/MrCl0wnLab/string-x
python simplerecondorking.py -t target.com --dork-category files --no-banner \
  | strx -st "echo {STRING}" -module "clc:http_probe" -pm

Criando uma nova fonte

Adicione o arquivo ao diretório de implementações em sources/passive/. A classe deve ter NAME igual ao nome do arquivo. Nenhuma outra mudança é necessária, pois o registro é automático.

from sources.base import BaseSource, Dork

class MinhaFonte(BaseSource):
    NAME = 'minha_fonte'
    DESCRIPTION = 'O que essa fonte faz'
    CATEGORY = 'web'              # web | code | source | legal | leak
    SUPPORTS_OPERATORS = True     # False se a fonte não entende site:/ext:/...
    ROTATE_MID_FETCH = True       # False se trocar de proxy no meio quebraria a fonte

    async def fetch(self, dork: Dork) -> set[str]:
        query = self.query_for(dork)   # já rebaixada para termos soltos se preciso
        urls: set[str] = set()
        async with self._make_client() as client:
            resp = await self._get(client, 'https://exemplo/...')   # ou self._post(...)
        return self._filter_urls(urls)  # aplica --filter-* e remove chrome da própria fonte

Três regras que não são óbvias:

  • Sempre use self._get() / self._post(), nunca client.get()/client.post() direto. São eles que aplicam o --rate-limit e a rotação de proxy - uma fonte que chama o cliente direto escapa dos dois em silêncio.
  • ROTATE_MID_FETCH = False quando a fonte tem um fluxo de várias etapas ligado ao IP (um token obtido numa requisição e gasto na seguinte) ou faz uma requisição com efeito colateral que não pode ser repetida. Ela continua usando proxy - só não troca dentro do mesmo fetch().
  • Nunca deixe fetch() levantar exceção - uma fonte bloqueada ou fora do ar deve contribuir com um conjunto vazio, sem derrubar o restante da execução. A única exceção que atravessa de propósito é a de pool de proxy esgotado, que precisa abortar a execução inteira.

Fontes que usam navegador (Playwright) pegam o proxy com self.browser_proxy() e avisam o pool de bloqueio com self.report_block().


Banners

A arte ASCII em core/banner/asciiart/*.txt é a mesma família visual do string-x e do resto do SimpleRecon: arquivos de texto puro com códigos ANSI já embutidos, um escolhido aleatoriamente a cada execução. Os placeholders [VERSION]/[DESCRIPTION] são substituídos por core/settings.py em tempo de exibição. --no-color (ou NO_COLOR, ou stdout não sendo um TTY) remove os códigos ANSI sem trocar o arquivo.


📄 LICENÇA

Este projeto está licenciado sob a Licença Apache. Veja o arquivo LICENSE para detalhes.

👨‍💻 AUTOR

MrCl0wn


Contribuições ✨

Contribuições de qualquer tipo são bem-vindas!

Lista de contribuidores

⭐ Se este projeto foi útil, considere dar uma estrela!

💡 Sugestões e feedbacks são sempre bem-vindos!

💀 Hacker Hackeia!