Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
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.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
StealMyBitcoin-PoC — Uma versão pública do desafio Steal My Bitcoin | Kitploit
Ferramentas/GitHubGitHub/killaboi/stealmybitcoin-poc
Forensia de MemóriaAnálise de VulnerabilidadesExploraçãoExploração de Aplicações WebCTFDesenvolvimento de PayloadsExploração de BináriosLabs e Prática
GitHubkillaboi/stealmybitcoin-poc

StealMyBitcoin-PoC

Uma versão pública do desafio Steal My Bitcoin

Ver Repositório
2164160há 1 diaAinda 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

patrocinado com ❤️ por hextree.io

Prova de conceito do CTF Steal My Bitcoin

Um callback PHP ao vivo contra o desafio Steal My Bitcoin, do início ao fim, em um único arquivo Python de biblioteca padrão.

Python Dependencies Target Lab

Este README explica o stealmybitcoin_poc.py, uma reprodução em Python de arquivo único da sequência de requisições usada na minha execução do CTF Steal My Bitcoin. Ele usa apenas a biblioteca padrão do Python. O script constrói as requisições por conta própria, verifica cada vazamento antes de prosseguir e registra os bytes HTTP de uma nova execução.

Isso provavelmente pode ser feito de forma mais fácil sem toda a parafernália extra de depuração e, como descobri no meu vídeo do John Hammond sobre a Escalação de Privilégios Local do Steam, você provavelmente poderia limpar esta PoC feia.

[!NOTE] ⚠️ Honestamente, por favor, limpe isso ou faça sua própria versão melhor que não esteja amassada pelo Sol. ⚠️

Tudo abaixo foi escrito para o laboratório Docker, não para o desafio ao vivo. O laboratório é um servidor CLI Alpine PHP 8.4.26 local atrás do nginx, que é a mesma build e modelo de worker nos quais os offsets foram calibrados. Monte-o em um minuto e toda a cadeia roda de ponta a ponta na sua própria máquina. A execução ao vivo que de fato resolveu o desafio está mantida como nota histórica no final.

  stage                 what goes out                        what comes back
  ─────────────────────────────────────────────────────────────────────────────
  0  health      GET /php-version.php                 ->  PHP 8.4.26 confirmed
  1  heap leak   249,042 B producer + 8 x   6,672 B   ->  256 B cookie
                 (OOM poisons a worker)                   └─ Zend chunk base
  2  code leak   251,557 B producer + 8 x  92,388 B   ->   16 B cookie
                 (OOM poisons a worker)                   └─ zval_ptr_dtor
  3  callback    368,812 B POST                       ->  forged HashTable runs
                 (fake HashTable + command)               └─ zif_system(cmd)
  ─────────────────────────────────────────────────────────────────────────────
  20 HTTP requests at most. No looping, no retries.

A versão resumida

  1. Um pequeno upload multipart faz o PHP consumir muito mais memória do que o tamanho na rede sugere.
  2. Quando fica sem memória no meio da análise de progresso de upload da sessão, o PHP deixa um estado obsoleto para trás num worker que depois é reutilizado.
  3. Modele corretamente as requisições seguintes e os bytes vazam através dos cookies de sessão. Eu os leio como um endereço de heap e um endereço de código PHP.
  4. Com ambos os endereços, uma requisição final coloca uma estrutura PHP forjada onde a limpeza a encontrará, e a limpeza chama zif_system, o handler do PHP para system.
  5. Esse comando envia de volta um novo marcador de prova e um resultado de print-flag pela conexão que ainda está aberta.

Por que dois endereços? O SO randomiza onde o código e o heap do PHP ficam, de forma independente. O vazamento de heap diz ao script onde colocar a estrutura forjada, o vazamento de código diz onde a função que ele quer chamar realmente reside. Endereços de um worker anterior ou de uma execução anterior não são substitutos seguros, e toda vez que tentei, a tentativa simplesmente falhou.

Conteúdo

  • O laboratório
  • Comece aqui
  • O que cada requisição faz
    • 1. Como um pequeno produtor atinge o limite de memória
    • 2. Como o endereço de heap é recuperado
    • 3. Como o endereço de código PHP é recuperado
    • 4. Como a requisição final chega a system
  • Lendo o resultado
  • Com que frequência realmente funciona
  • A execução ao vivo que resolveu
  • Jargão, brevemente
  • Agradecimentos

O laboratório

Os offsets neste PoC são calibrados para Alpine PHP 8.4.26 executando o servidor CLI embutido com quatro workers. O laboratório reproduz exatamente isso, atrás do nginx, em loopback.

[!IMPORTANT] A build importa mais que a string de versão. Uma stack Debian php:8.4.26-fpm reporta o mesmo PHP/8.4.26, mas tem um layout de binário diferente, então a impressão digital do ponteiro de código nunca corresponderá e a execução aborta no estágio de vazamento de código. Use a imagem Alpine abaixo.

Três pequenos arquivos. Coloque-os num diretório vazio:

public/php-version.php (o endpoint de saúde, e a única página que o PoC precisa)

<?php
header('Content-Type: text/plain');
echo 'PHP ', PHP_VERSION, "\n";
echo 'PID: ', getmypid(), "\n";

print-flag (substituto do binário do desafio, deve ser executável)

#!/bin/sh
printf '%s\n' 'LOCAL_DUMMY_WIF_NEVER_USE'

nginx.conf

events {}
http {
    server {
        listen 80;
        server_name _;
        location / {
            proxy_pass http://ctf-cross-php:8000;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
        }
    }
}

Em seguida, inicialize-o:

docker network create ctf-cross-net

docker run -d --name ctf-cross-php --network ctf-cross-net \
  --read-only --tmpfs /tmp:rw,size=32m,mode=1777 --memory 1g \
  -v "$PWD/public:/app:ro" \
  -v "$PWD/print-flag:/usr/local/bin/print-flag:ro" \
  -e PHP_CLI_SERVER_WORKERS=4 \
  php:8.4.26-fpm-alpine3.23 php -S 0.0.0.0:8000 -t /app

docker run -d --name ctf-cross-nginx --network ctf-cross-net \
  -p 127.0.0.1:18166:80 \
  -v "$PWD/nginx.conf:/etc/nginx/nginx.conf:ro" \
  nginx:1.27-alpine

Verifique:

$ curl -s http://127.0.0.1:18166/php-version.php
PHP 8.4.26
PID: 1

O PID varia conforme o worker que responde, e isso é normal. A linha de versão é a parte que o PoC verifica.

Derrube tudo com docker rm -f ctf-cross-nginx ctf-cross-php && docker network rm ctf-cross-net.

[!TIP] No Windows, execute esses comandos docker run a partir do PowerShell, ou substitua $PWD por um caminho completo de unidade como C:/lab. No Git Bash, $PWD expande para um caminho MSYS como /tmp/..., que o Docker Desktop resolve dentro de sua própria VM. Os bind mounts então criam silenciosamente diretórios vazios onde nginx.conf e print-flag deveriam estar, e os containers sobem quebrados.

Algumas observações sobre essa receita. A imagem é a tag fpm, mas o container executa php -S, então o SAPI é cli-server, que é contra o qual a calibração foi medida. PHP_CLI_SERVER_WORKERS=4 é o que dá aos estágios de vazamento mais de um worker para disputar. Meu próprio harness de laboratório também passava --cap-add SYS_PTRACE --security-opt seccomp=unconfined para poder anexar um tracer aos workers; o PoC em si nunca faz isso, então esses parâmetros foram omitidos acima.


Comece aqui

Python 3.11 ou mais recente, apenas biblioteca padrão, nada para instalar:

Baixar ferramenta