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
CVE-2019-16784-POC — Uma prova de conceito de exploit para o PyInstaller CVE-2019-16783 | Kitploit
Ferramentas/GitHubGitHub/ckrielle/cve-2019-16784-poc
Escalada de PrivilégiosAnálise de VulnerabilidadesExploraçãoAprendizado e EducaçãoDesenvolvimento de PayloadsExploração de BináriosLabs e Prática
GitHubckrielle/cve-2019-16784-poc

CVE-2019-16784-POC

Uma prova de conceito de exploit para o PyInstaller CVE-2019-16783

Ver Repositório
há 2 anosAinda não revisado

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

POC do CVE-2019-16784

Esta é minha POC para a vulnerabilidade do Windows PyInstaller versão < 3.6 que existe para a opção --onefile. Um atacante poderia alcançar execução de comandos e possível LPE sequestrando uma DLL importada pela DLL do interpretador Python usada pelo binário do PyInstaller. Uma breve explicação da vulnerabilidade e do processo de exploração será apresentada. Meus agradecimentos à Alter Solutions por encontrar a vulnerabilidade e escrever sobre sua descoberta no PagedOut #3 (página 55 do pdf).

A Vulnerabilidade

A vulnerabilidade foi causada por uma criação fraca de um diretório usado pelo PyInstaller em tempo de execução do binário executado. O PyInstaller constrói um diretório _MEIPIDX no diretório temporário do usuário e coloca diferentes coisas nele, como a DLL do interpretador Python usada para executar o código Python empacotado em um executável PE.

O problema com esse processo era que o diretório construído para NT AUTHORITY\SYSTEM era C:\Windows\Temp, o que permitia que alguém tanto o adivinhasse quanto escrevesse dentro dele. Assim, um sequestro de DLL seria possível, por exemplo, quando o interpretador Python fosse executado. Aqui está o commit corrigindo a vulnerabilidade. Em vez de depender apenas de algumas funções padrão da API para criar o diretório, os desenvolvedores implementaram sua própria função para ter mais controle sobre a criação do diretório.

O Processo de Exploração

Como esta foi minha primeira POC, discutirei alguns problemas que encontrei pelo caminho.

Configurando o Ambiente de Teste

Primeiramente, configurar um ambiente para esta POC não foi particularmente difícil, já que tudo que você precisava era da versão correta do pacote. No entanto, quando o instalei, ele travava

root@kitploit:~
Traceback (most recent call last):
  File "c:\users\ckrielle\appdata\local\programs\python\python38\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
...
  File "c:\users\ckrielle\appdata\local\programs\python\python38\lib\site-packages\PyInstaller\building\utils.py", line 653, in <genexpr>
    strip_paths_in_code(const_co, new_filename)
  File "c:\users\ckrielle\appdata\local\programs\python\python38\lib\site-packages\PyInstaller\building\utils.py", line 660, in strip_paths_in_code
    return code_func(co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize,
TypeError: an integer is required (got type bytes)

Depois de pesquisar um pouco, percebi que minha versão do Python era a culpada (estou usando 3.8.10). Minha versão do Python dificultou a instalação de qualquer outra versão 3.8.x, pois na instalação o instalador encontrava minha versão Python38 e retornava um erro. Também tentei compilar outra versão 3.8, mas não consegui porque precisava do Visual Studio 2015, enquanto tenho o 2022. Por fim, escolhi baixar o Python 3.7.5, que funcionou perfeitamente. Então criei um ambiente virtual para a versão 3.7.

Entendi que configurar o ambiente pode variar desde já estar pronto até potencialmente levar muito tempo para configurar corretamente. Embora seja importante, poderia potencialmente tirar a diversão de realmente explorar nosso alvo.

Escrevendo o Exploit

Há duas etapas em nosso processo de exploração: encontrar o diretório do processo empacotado pelo PyInstaller e escrever nossa DLL de exploit lá. Para a primeira parte, podemos encontrar o PID através das funções WINAPI padrão (CreateToolhelp32Snapshot, Process32First, Process32Next). Isso funcionou sem problemas. Depois, precisamos encontrar o último número do diretório _MEI. O exploit original sugere usar apenas a função GetFileAttributesA e verificar se o código de status retornado é FILE_ATTRIBUTE_DIRECTORY. No entanto, isso não funcionou para mim. Minha solução foi criar um arquivo em cada diretório candidato e, se o arquivo fosse criado com sucesso, então o diretório existia. Por algum motivo, o status retornado para o arquivo de GetFileAttributesA era FILE_ATTRIBUTE_ARCHIVE, então verifico isso. Antes de prosseguir, o loop durante a busca do PID é porque queremos injetar nossas DLLs quando o processo alvo é executado, para tê-las prontas antes do carregamento.

Para a DLL, precisamos sequestrar uma DLL que o interpretador Python (python37.dll) importa. Para obter as DLLs que o interpretador importa, poderíamos abrir a DLL com o PE-Bear. Uma das DLLs do sistema importadas é version.dll. Então podemos criar nossa própria DLL e abusar da ordem de busca do carregador do Windows colocando-a no diretório temporário do processo empacotado pelo PyInstaller. Dessa forma, quando ele quiser importar a DLL, importará nossa DLL maliciosa, em vez da correta.

Importações do python37.dll

No entanto, fazer isso não funcionará. A razão é que a importação da função que o interpretador Python chama de version.dll (especificamente VerQueryValueW da imagem) não é resolvida. Então o programa trava. Para resolver esse problema, precisamos fazer proxy de DLL. Em resumo, configuramos nossa DLL maliciosa para exportar as funções da DLL original e trazemos a DLL original renomeada, para que ela possa carregá-la e chamar a função a partir dela. Então, para nosso exploit, compilaremos uma DLL maliciosa com um DllMain que nos permitirá alcançar nossa execução de código. Exportaremos todas as funções da version.dll e copiaremos a version2.dll original do sistema e a colocaremos no mesmo diretório. Dessa forma, version.dll pode encaminhar as chamadas de função para version2.dll. E uma vez que tenhamos essas DLLs, tudo que precisamos fazer é copiá-las no diretório do processo e aguardar a execução de código. Para uma explicação melhor sobre DLL Proxying/Hijacking, leia o artigo vinculado.

Funções Exportadas da version.dll Maliciosa

Mesmo que, em retrospecto, esses passos sejam todos fáceis e diretos, não foi assim durante o desenvolvimento da POC. Antes, demorou um pouco para entender o processo do exploit e, assim que comecei a codificar, comecei a entendê-lo mais. Quanto à DLL, tentei compilá-la eu mesmo da maneira que foi sugerida no repositório da POC da Alter Solutions. Eles têm uma DLL separada para execução de código e outra diferente para proxy, que carregava a payload.dll em tempo de execução (DllMain é chamado no momento do carregamento). No entanto, não consegui compilá-la corretamente. No final, depois de ler o artigo acima, decidi usar o repositório DLLProxyProject, que compilou a DLL que eu queria e pode ser usado genericamente para produzir uma DLL para fins de proxy. Tentei copiar o arquivo DLLMain.cpp e compilá-lo com o arquivo de cabeçalho exports.h. E embora tenha executado, produziu um erro:

root@kitploit:~
Fatal Python error: init_sys_streams: can't initialize sys standard streams
OSError: [WinError 6] The handle is invalid

Current thread 0x00002ea8 (most recent call first):

Esse erro poderia ser evitado com o arquivo Utils.cpp, então decidi manter aquele projeto para minha compilação de DLL (embora teria sido melhor se eu tivesse feito completamente sozinho).

Explorando Nosso Alvo

Depois de configurar o ambiente (usei psexec para obter um shell NT AUTHORITY\SYSTEM), executei o exploit, executei o binário alvo e obtive execução de código como administrador.

Sucesso da POC

Considerações Finais

Esta foi uma experiência muito boa, e estou feliz por ter passado por ela. Realmente quero produzir mais POCs para outras CVEs, e este foi um primeiro alvo perfeito. Ler a descrição da vulnerabilidade foi interessante, pois entendi que a principal dificuldade de implementar uma POC por conta própria é preencher as lacunas para coisas que o autor não explicou (seja de propósito ou não) e apenas entender o que você está lendo. Foi uma vulnerabilidade simples, então não me esforcei muito para entendê-la. Num futuro próximo, depois de fazer mais algumas, tentarei fazer uma POC para uma vulnerabilidade de corrupção de memória.

Baixar ferramenta