PROJETO · KEYLOGGER

Entendendo Eventos de Teclado

Vamos entender como um programa percebe uma ação, chamada evento, e chama uma função de resposta, chamada callback. A demonstração usa um observador de eventos (listener) e os nomes on_press e on_release para distinguir pressionar de soltar uma tecla. Não é preciso conhecer Python de antemão: cada parte será explicada antes de ser usada. O código será construído em etapas executáveis, com um teste logo após cada alteração e um teste integrado no final.

Linux Mint em máquina virtual VS Code e terminal Bash Python 3 · pynput
🛡️ Limites do laboratório: esta aula usa uma demonstração visível, executada somente na VM sob seu controle. Enquanto o listener estiver ativo, ele pode receber eventos de outras janelas da VM, não apenas do terminal. Feche aplicativos que não fazem parte do teste e use somente entradas fictícias; não digite senhas, mensagens privadas ou dados de terceiros. O programa exibe eventos no terminal, mas não cria log.txt nem envia dados. Para encerrar normalmente, pressione e solte ESC. Se o programa não responder ao ESC, pressione Ctrl+C no mesmo terminal. Se o prompt não voltar, encerre o terminal do processo pela interface do VS Code.
Ambiente de referência: os passos desta aula pressupõem a VM Linux Mint 22.3 preparada na Aula 1. Em outra versão do Mint ou em outra distribuição, telas, opções e alguns comandos podem diferir. Confirme a compatibilidade antes de adaptar instruções.
Objetivos

O que você vai aprender

Conceito 01

Evento e callback

Entender a ocorrência que chega ao programa e a função chamada para tratá-la.

Conceito 02

Pressionar e soltar

Diferenciar os eventos associados a on_press e on_release.

Prática

Construção incremental

Editar, executar e conferir o arquivo após cada etapa, sem acumular erros.

Validação

Teste integrado

Verificar os dois callbacks e o encerramento controlado por ESC.

01 · Retomada

Antes de começar

Na Aula 1, o laboratório foi preparado e validado. Nesta aula não vamos refazer essa configuração sem necessidade. Vamos confirmar a pasta de trabalho e, depois, verificar o ambiente Python antes de instalar ou usar uma dependência.

1

Confirmar a pasta do laboratório

No terminal integrado do VS Code, execute o comando abaixo.

Terminal Bash · verificação inicial
pwd

Resultado esperado: o caminho termina em Laboratorio-Keyloggers.

Resultado observado: registre o caminho que apareceu. Se estiver em outra pasta, abra a pasta correta no VS Code antes de continuar.

Status: ☐ aprovado ☐ reprovado ☐ não executado.

2

Verificar o interpretador e o ambiente virtual

Abra um terminal novo e ative o ambiente virtual criado na Aula 1.

Terminal Bash
cd "$HOME/Laboratorio-Keyloggers"
source .venv/bin/activate
python --version
python -c "import sys; print(sys.executable)"
echo "$XDG_SESSION_TYPE"
echo "$DISPLAY"

Confirme a versão registrada na Aula 1 e que o caminho do interpretador termina em .venv/bin/python. As últimas duas linhas mostram o tipo de sessão gráfica e o servidor de exibição. Registre as saídas; não avance se o ambiente virtual não estiver ativo. Se DISPLAY aparecer vazio, abra o VS Code pelo menu gráfico do Linux Mint e crie um terminal integrado novo: o listener precisa herdar a sessão gráfica da VM. Se continuar vazio, pare e peça ajuda ao responsável pelo laboratório.

Registro: anote a versão, o caminho e o status do teste.

Compatibilidade no Linux: pynput usa o servidor gráfico X ou a interface uinput, que permite ao Linux criar dispositivos de entrada virtuais. uinput exige privilégios de administrador; não o use nesta aula e nunca execute o listener com sudo. Wayland é um sistema gráfico; XWayland é uma camada de compatibilidade para aplicativos feitos para o servidor X e pode limitar os eventos que recebem. Confira sua sessão com echo "$XDG_SESSION_TYPE"; se aparecer wayland e o teste não funcionar como descrito, pare e peça ao responsável para configurar uma sessão compatível. Consulte as limitações de plataforma documentadas pelo pynput.
02 · Conceitos

Como o programa reage a um evento

Evento

Um evento é uma ocorrência que um programa pode reconhecer e tratar. No teclado, pressionar uma tecla e soltá-la são eventos distintos. Uma tecla especial, como ESC ou uma seta, também pode gerar eventos, mesmo que não corresponda a uma letra digitada.

O diagrama resume a sequência da demonstração. O listener permanece visível e os callbacks mostram apenas as entradas de teste usadas nesta atividade.

Função, parâmetro e callback

Uma função agrupa instruções que podem ser executadas quando chamadas. Um parâmetro é o nome que aparece na definição para receber um valor. Um callback é uma função entregue a outro componente para que esse componente a chame quando ocorrer uma situação específica.

Por exemplo, ao configurar on_press=ao_pressionar, não estamos escrevendo ao_pressionar(). Estamos passando a própria função ao listener. O listener poderá chamá-la quando detectar um pressionamento.

Analogia: imagine uma campainha. O toque é o evento; a pessoa que atende é a resposta. No programa, o listener percebe o evento e chama o callback. A comparação ajuda a visualizar a relação, mas, no código, o callback recebe um valor que descreve a tecla.
TermoSignificado nesta aulaExemplo
EventoOcorrência a ser tratada.Uma tecla foi pressionada.
FunçãoBloco de instruções nomeado.def ao_pressionar(tecla):
ParâmetroNome que recebe o valor fornecido à função.tecla
CallbackFunção chamada pelo componente que acompanha o evento.ao_pressionar associada a on_press.
ListenerComponente que observa eventos enquanto está ativo.keyboard.Listener(...)

Pressionar não é o mesmo que soltar

Evento de pressão

on_press

Associa um callback ao momento em que a biblioteca informa que uma tecla foi pressionada.

Evento de liberação

on_release

Associa outro callback ao momento em que a biblioteca informa que a tecla foi solta.

Importante: a saída de um listener pode conter teclas especiais e valores que não são letras comuns. Por isso, mesmo uma demonstração pequena deve ficar visível, limitada ao teste autorizado e ser encerrada assim que terminar.
03 · Preparação

Preparar arquivo e dependência

1

Justificar e verificar o pacote

Precisamos da biblioteca pynput porque a demonstração usa pynput.keyboard.Listener, um observador que recebe eventos de teclado enquanto está ativo na VM. Antes de instalar, confira se o pacote já está disponível no ambiente virtual ativo:

Terminal Bash
python -m pip show pynput

Esperado: se instalado, o comando mostra nome, versão e localização. Se não for encontrado, instale somente no ambiente virtual do laboratório:

Terminal Bash · somente se necessário
python -m pip install pynput

Depois da instalação, execute novamente python -m pip show pynput. Não avance até confirmar que o pacote está instalado no ambiente virtual ativo. Nunca execute a instalação com sudo.

Resultado observado/status: registre o que apareceu; marque aprovado, reprovado ou não executado.

2

Criar o arquivo

No VS Code, com .venv ainda ativo, crie um arquivo chamado eventos_teclado.py na pasta do laboratório. Salve o arquivo antes de cada teste. A cada etapa, substitua ou acrescente exatamente o trecho indicado para que o arquivo permaneça executável.

Regra para todos os passos: depois de cada alteração, salve o arquivo e execute python eventos_teclado.py no terminal. Registre o resultado antes de alterar o código novamente.
04 · Construção incremental

Uma etapa de cada vez

As etapas abaixo estão em ordem de dependência: primeiro verificamos que o arquivo pode importar a biblioteca; depois definimos cada callback; em seguida ligamos os callbacks ao listener; por último adicionamos o encerramento por ESC e as mensagens de orientação. O teste de cada etapa acontece antes da próxima mudança.

PASSO 1

Importar a biblioteca

Arquivo: eventos_teclado.py

Python · conteúdo completo desta etapa
from pynput import keyboard

Explicação: from pynput import keyboard importa o módulo que contém a interface de teclado que usaremos. Ainda não há listener ativo nem eventos sendo observados.

Comando de teste · executar o arquivo
python eventos_teclado.py

Esperado: o terminal volta ao prompt sem erro e sem imprimir mensagens. Esse resultado é normal porque só existe uma importação.

Observado/status: anote a saída real; aprovado somente se a execução terminar sem erro.

PASSO 2

Definir o callback de pressionamento

Acrescente a função abaixo depois da importação. Neste ponto, o arquivo completo fica assim:

Python · arquivo completo desta etapa
from pynput import keyboard

def ao_pressionar(tecla):
    # Exibe o valor recebido quando o callback for chamado.
    print(f"Pressionada: {tecla}")

Explicação: def define a função; tecla é o parâmetro; a linha indentada exibe o valor recebido. A função está apenas definida — ainda não foi conectada a um listener, então não será chamada por eventos reais.

Comando de teste · executar o arquivo
python eventos_teclado.py

Esperado: o terminal retorna ao prompt sem saída. O teste verifica que a função pode ser definida sem erro; ainda não comprova o recebimento de eventos. O teste funcional será feito quando a função for conectada ao listener.

Observado/status: registre o resultado; aprovado se não houver erro de sintaxe ou importação.

PASSO 3

Conectar o callback e testar pressionamentos

Acrescente o bloco with ao final do arquivo. O conteúdo completo passa a ser:

Python · arquivo completo desta etapa
from pynput import keyboard

def ao_pressionar(tecla):
    # Exibe o valor recebido quando o callback for chamado.
    print(f"Pressionada: {tecla}")

    # ESC oferece uma saída segura desde o primeiro teste ativo.
    if tecla == keyboard.Key.esc:
        print("Encerrando a demonstração.")
        return False

with keyboard.Listener(on_press=ao_pressionar) as listener:
    print("Demonstração ativa. Use somente teclas de teste.")
    print("Pressione ESC para encerrar.")
    listener.join()

Explicação: keyboard.Listener(...) cria o observador; on_press=ao_pressionar passa a função como callback; with gerencia o recurso; listener.join() mantém o programa aguardando enquanto o listener está ativo.

Comando de teste · executar o arquivo
python eventos_teclado.py

Com o terminal visível, pressione e solte poucas teclas fictícias, sem conteúdo sensível. Nesta etapa, o callback trata os pressionamentos. Para encerrar, pressione ESC; a condição está no callback de pressão.

Esperado: cada tecla de teste produz uma linha que começa com Pressionada:. Ao pressionar ESC, aparece Encerrando a demonstração. e o processo volta ao prompt. Se ESC não funcionar, use Ctrl+C no mesmo terminal.

Observado/status: anote as mensagens e confirme que o prompt voltou. Não marque aprovado sem executar.

PASSO 4

Adicionar o callback de soltura

Agora substitua o conteúdo do arquivo pelo código abaixo, que associa um callback a cada tipo de evento:

Python · arquivo completo desta etapa
from pynput import keyboard

def ao_pressionar(tecla):
    # Exibe o valor recebido no evento de pressão.
    print(f"Pressionada: {tecla}")

    # Por enquanto, ESC encerra quando é pressionada.
    if tecla == keyboard.Key.esc:
        print("Encerrando a demonstração.")
        return False

def ao_soltar(tecla):
    # Exibe o valor recebido no evento de liberação.
    print(f"Solta: {tecla}")

with keyboard.Listener(
    on_press=ao_pressionar,
    on_release=ao_soltar,
) as listener:
    print("Demonstração ativa. Use somente teclas de teste.")
    print("Pressione ESC para encerrar.")
    listener.join()

Explicação: ao_soltar é uma segunda função. O argumento on_release=ao_soltar informa ao listener qual callback chamar quando a tecla for solta. A vírgula separa os argumentos de Listener.

Comando de teste · executar o arquivo
python eventos_teclado.py

Com o terminal visível, pressione e solte algumas teclas fictícias. O encerramento por ESC ainda acontece no evento de pressão: use ESC para parar e aguarde o prompt retornar.

Esperado: para as teclas comuns de teste, aparecem linhas Pressionada: e Solta:. Uma pressão seguida da liberação correspondente deve gerar os dois tipos de mensagem. ESC encerra ao ser pressionada.

Observado/status: registre a saída e marque aprovado, reprovado ou não executado.

PASSO 5

Adicionar encerramento por ESC

Agora vamos fazer o encerramento acontecer quando ESC for solta. Remova de ao_pressionar a condição de parada adicionada no passo anterior e coloque a verificação dentro de ao_soltar, como mostrado abaixo. Assim, o teste também demonstra a diferença entre pressionar e soltar:

Python · função atualizada
def ao_soltar(tecla):
    # Exibe o valor recebido no evento de liberação.
    print(f"Solta: {tecla}")

    # Se ESC for solta, solicita ao listener que pare.
    if tecla == keyboard.Key.esc:
        print("Encerrando a demonstração.")
        return False

Explicação: a condição compara o evento recebido com keyboard.Key.esc. A mensagem torna o encerramento visível. Retornar False neste callback pede ao listener que pare de observar eventos. As três linhas finais precisam estar dentro da função; a condição e o retorno também precisam respeitar a indentação mostrada.

Comando de teste · executar o arquivo
python eventos_teclado.py

Pressione e solte algumas teclas de teste e, por último, pressione e solte ESC.

Esperado: ao soltar ESC, aparece Encerrando a demonstração. e o programa volta ao prompt. Se isso não acontecer, tente Ctrl+C no mesmo terminal; se o prompt não voltar, encerre o terminal do processo. Corrija a condição ou a indentação antes de avançar.

Observado/status: registre o comportamento real.

PASSO 6

Adicionar orientações visíveis e testar o fluxo

Atualize o bloco final para informar ao usuário quando a demonstração está ativa e como encerrá-la. O arquivo completo fica assim:

Python · arquivo completo desta etapa
from pynput import keyboard

def ao_pressionar(tecla):
    # Exibe o valor recebido no evento de pressão.
    print(f"Pressionada: {tecla}")

    # Por enquanto, ESC encerra quando é pressionada.
    if tecla == keyboard.Key.esc:
        print("Encerrando a demonstração.")
        return False

def ao_soltar(tecla):
    # Exibe o valor recebido no evento de liberação.
    print(f"Solta: {tecla}")

    # Se ESC for solta, solicita ao listener que pare.
    if tecla == keyboard.Key.esc:
        print("Encerrando a demonstração.")
        return False

with keyboard.Listener(
    on_press=ao_pressionar,
    on_release=ao_soltar,
) as listener:
    print("Demonstração ativa. Use somente teclas de teste.")
    print("Pressione e solte ESC para encerrar.")
    listener.join()

Explicação: as mensagens ficam dentro do bloco with, depois que o listener é configurado. O join() mantém o fluxo principal aguardando. Quando ESC é solta e o callback retorna False, o listener termina e a execução volta ao terminal.

Comando de teste · executar o arquivo
python eventos_teclado.py

Esperado: as duas mensagens de orientação aparecem; os dois callbacks exibem os eventos; ao soltar ESC, a mensagem de encerramento aparece e o processo termina. Se ESC não encerrar, tente Ctrl+C no mesmo terminal. Se o prompt não voltar, encerre o terminal pela interface do VS Code e investigue antes de prosseguir.

Observado/status: registre a saída real e marque aprovado, reprovado ou não executado.

05 · Leitura defensiva

O que a demonstração faz — e o que não faz

Faz

Observa eventos enquanto ativa

O listener chama os callbacks para os eventos que a biblioteca reporta durante a execução.

Faz

Mostra a atividade

O terminal permanece visível e apresenta mensagens de orientação e de evento.

Não faz

Não grava logs

Este arquivo não cria nem modifica log.txt; registros serão assunto da Aula 4.

Não faz

Não transmite dados

Não há comunicação de rede nem envio de eventos para outra pessoa ou serviço.

O ponto defensivo é perceber que callbacks podem receber valores que revelam atividade do usuário. O fato de um programa ser curto não elimina o risco de privacidade. Mantenha a demonstração dentro do escopo autorizado, não use credenciais nem conteúdo privado e encerre o processo assim que concluir o teste.

Sobre o encerramento: o método normal desta demonstração é pressionar e soltar ESC. Se ESC falhar, pressione Ctrl+C no terminal em que a demonstração está ativa. Confirme que o processo terminou e que o prompt voltou; se não voltar, encerre o terminal pela interface do VS Code e abra um novo antes de continuar.
06 · Teste integrado

Conferência final do arquivo

Antes do teste final, confira se o arquivo foi salvo e se o conteúdo corresponde ao bloco abaixo. Esse bloco reúne somente os elementos trabalhados nesta aula; não inclui armazenamento nem transmissão.

Python · versão integrada esperada
from pynput import keyboard

def ao_pressionar(tecla):
    # Exibe o valor recebido no evento de pressão.
    print(f"Pressionada: {tecla}")

    # Por enquanto, ESC encerra quando é pressionada.
    if tecla == keyboard.Key.esc:
        print("Encerrando a demonstração.")
        return False

def ao_soltar(tecla):
    # Exibe o valor recebido no evento de liberação.
    print(f"Solta: {tecla}")

    # Se ESC for solta, solicita ao listener que pare.
    if tecla == keyboard.Key.esc:
        print("Encerrando a demonstração.")
        return False

with keyboard.Listener(
    on_press=ao_pressionar,
    on_release=ao_soltar,
) as listener:
    print("Demonstração ativa. Use somente teclas de teste.")
    print("Pressione e solte ESC para encerrar.")
    listener.join()
1

Executar o teste completo

Comando obrigatório
python eventos_teclado.py

Pré-condições: terminal visível, ambiente virtual correto, pynput instalado e arquivo salvo.

Procedimento: confirme as mensagens de orientação; pressione e solte uma tecla comum de teste e uma tecla especial não sensível; depois pressione e solte ESC.

Resultado esperado: mensagens de pressão e soltura aparecem; ESC produz a mensagem de encerramento; o processo termina e o prompt retorna.

Resultado observado: descreva a saída real do terminal. Não copie dados privados.

Critério de aprovação: todos os comportamentos esperados foram observados, o encerramento ocorreu e nenhum dado foi salvo ou transmitido.

Status: ☐ aprovado ☐ reprovado ☐ não executado.

Se falhar: registre o erro, feche o terminal do processo se necessário, corrija o problema e repita o teste completo. Não marque como aprovado com base apenas no resultado esperado.

2

Registro de teste por etapa

Para cada passo de 1 a 6, registre:

  • Objetivo: o que a alteração deveria demonstrar.
  • Comando: python eventos_teclado.py.
  • Esperado: o comportamento descrito no passo.
  • Observado: o que realmente aconteceu.
  • Status: aprovado, reprovado ou não executado.
  • Próximo passo: correção necessária ou autorização para continuar.
07 · Fixação

Exercício e checklist

Antes de executar, escreva sua previsão. Depois rode o arquivo e compare sua previsão com o resultado observado. Use somente entradas de teste não sensíveis.

  1. Pressione e solte uma tecla comum. Quais mensagens apareceram?
  2. Pressione e solte uma tecla especial, como uma seta. O valor exibido é igual ao de uma letra?
  3. Pressione e solte ESC. O que faz o listener parar?

Perguntas de compreensão

  1. Qual é a diferença entre um evento e um callback?
  2. Por que definir ao_pressionar() não faz a função executar imediatamente?
  3. Qual argumento associa o callback de pressão ao listener? E qual associa o callback de soltura?
  4. O que a condição tecla == keyboard.Key.esc verifica?
  5. Qual é o papel de return False no callback de soltura?
  6. Por que não devemos usar credenciais ou conteúdo privado durante o teste?

Checklist de conclusão

  • Confirmei pasta, interpretador e dependência antes de executar o código.
  • Executei o arquivo após cada etapa e registrei o resultado observado.
  • Expliquei evento, função, parâmetro, callback e listener com minhas palavras.
  • Diferenciei pressão de liberação.
  • Testei o encerramento por ESC.
  • Executei e registrei o teste integrado.
  • Mantive o terminal visível e usei somente teclas de teste não sensíveis.
  • Confirmei que esta demonstração não grava arquivo nem transmite dados.
Critério de conclusão: você consegue explicar como um evento chega ao callback, diferenciar pressionamento de liberação, demonstrar o encerramento por ESC e documentar o resultado real de cada teste sem confundir expectativa com evidência.
Resumo

O que ficou estabelecido

Nesta aula, construímos uma demonstração transparente com pynput.keyboard.Listener, conectamos callbacks para pressão e liberação, e adicionamos um encerramento visível por ESC. Cada mudança deve ser testada imediatamente com python eventos_teclado.py, antes de seguir para a próxima.

Na próxima aula do cronograma, Aula 4 — Logs, Timestamps e Rastros, vamos estudar registros e timestamps usando dados de teste. Esta aula não grava as teclas em arquivo e não implementa transmissão de dados.

Quiz

Teste seus conhecimentos

Questão 1 de 10Acertos: 0

Aula 2 - Projeto · Keylogger

Material educacional de defesa digital. Execute somente em laboratório autorizado, com atividade visível e dados de teste.

Os resultados esperados são previsões didáticas. Os testes só devem ser marcados como aprovados depois de executados e observados no laboratório.

O que você achou desta aula?