
PoC e análise de um estouro de buffer local baseado em pilha (stack-buffer-overflow) no dataSIMS Avionics ARINC 664-1 v4.5.3, com detalhamento do payload, script de reprodução e correções do registro CVE.
Estouro de buffer local baseado em pilha no dataSIMS Avionics ARINC 4.5.3 (Data Device Corporation)
Olá, sou Kağan Çapar. Em fevereiro de 2020, encontrei um estouro de buffer local baseado em pilha no software de barramento de dados dataSIMS da DDC e publiquei uma prova de conceito no Exploit-DB em fevereiro de 2021. Quase cinco anos depois, em janeiro de 2026, a VulnCheck atribuiu a ele o CVE-2021-47881 como um CVE retroativo — fiquei sabendo da atribuição depois do fato, e não por meio dela.
Este repositório é o registro de arquivo dessa descoberta: o PoC original preservado tal como publicado, uma porta byte-idêntica para Python 3, uma análise anotada do payload e correções para dois problemas no registro do CVE publicado.
Escopo, desde já. Este é um registro, não uma análise de causa-raiz. O dataSIMS é um software comercial de código fechado, não há patch do fornecedor, e não testei novamente isso contra uma versão atual. O que é verificável aqui é verificado e mostrado; todo o resto é apontado em Limitações. Se você veio aqui esperando a profundidade do CVE-2026-5201, leia essa nota primeiro.
| CVE | CVE-2021-47881 |
| CWE | CWE-121 — Estouro de buffer baseado em pilha |
| CVSS v4.0 | 6.7 MÉDIO — AV:L/AC:L/AT:N/PR:N/UI:A/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N (VulnCheck) |
| CVSS v3.1 | 8.4 ALTO — AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (VulnCheck) |
| Afetado | dataSIMS Avionics ARINC 664-1, versão 4.5.3 |
| Fornecedor | Data Device Corporation |
| CNA | VulnCheck |
| Descoberta | 2020-02-17 |
| PoC publicado | 2021-02-19 — EDB-49577 |
| CVE publicado | 2026-01-23 (NVD) |
| Patch do fornecedor | nenhum publicado |
| Testado em | Windows 10 Enterprise x64 |
O componente afetado é o módulo ARINC 664-1 do dataSIMS 4.5.3. Ele relê um arquivo de resultado que — apesar do módulo ao qual pertence — se chama milstd1553result.txt; o nome é um artefato do fornecedor herdado da linhagem MIL-STD-1553 do pacote, não uma indicação de qual módulo é afetado. Fornecer uma versão excessivamente longa desse arquivo, com formato definido por um atacante, estoura um buffer de pilha de tamanho fixo durante o caminho de releitura e sobrescreve o endereço de retorno salvo. A falha termina com controle total do EIP:
EIP 42424242 <- 'BBBB' from the payload
ECX 42424242
C0000005 <- STATUS_ACCESS_VIOLATION
O PoC publicado tem 1040 bytes e para na sobrescrita do EIP. Ele não alcança execução de código, e nunca foi essa a intenção — veja Explorabilidade.
O layout de campos do PoC, verificado ao executar a porta (py poc/poc_py3.py --layout):
| Campo | Offset | Tamanho | Conteúdo |
|---|---|---|---|
junk | 0 / 0x000 | 600 | 0x41 preenchimento |
align | 600 / 0x258 | 8 | "22221111" |
prop | 608 / 0x260 | 380 | 0x43 preenchimento |
imp | 988 / 0x3dc | 10 | "bzhrturlu2" |
imp2 | 998 / 0x3e6 | 9 | "aracag" 0x13 "1z" |
overwrite | 1007 / 0x3ef | 4 | 0x42 × 4 → endereço de retorno salvo |
buf | 1011 / 0x3f3 | 29 | stub de decodificação shikata_ga_nai |
| total | 1040 | sha256 530efb5efef917082e40dcf379f5e0a526375724af18aba6f0270f794f96d066 |
O offset do EIP é 1007. Não é um número que você obtém do !mona findmsp ou do pattern_offset.rb — é a soma de cinco campos ajustados manualmente. O PoC original foi construído ampliando uma falha até o endereço de retorno se mover, não localizando o offset analiticamente. Estou registrando isso em vez de embelezar: uma reescrita limpa encontraria a distância real até o endereço de retorno salvo e eliminaria align, imp e imp2 por completo, já que nenhum deles carrega significado. imp/imp2 são strings de preenchimento, não imports.
buf é um stub msfvenom shikata_ga_nai de 29 bytes. Desmontado com ndisasm -b32:
00000000 DAC1 fcmovb st1 ; junk FPU op (sgn signature)
00000002 D97424F4 fnstenv [esp-0xc] ; GetPC
00000006 58 pop eax ; eax = &stub
00000007 BB0B7E9762 mov ebx,0x62977e0b ; XOR key
0000000C 33C9 xor ecx,ecx
0000000E B101 mov cl,0x1 ; <-- ONE 4-byte block
00000010 315819 xor [eax+0x19],ebx ; decode block at +0x19
00000013 83E8FC sub eax,-4 ; eax += 4
00000016 035815 add ebx,[eax+0x15] ; key schedule
00000019 E9 db 0xe9 ; <-- encoded block, not code
0000001A 8B db 0x8b
0000001B 7C9C jl 0xffffffb9
Duas coisas decorrem disso, e ambas significam que o payload jamais poderá ser executado:
mov cl,0x1 — o loop de decodificação está configurado para um único bloco de 4 bytes. Não há payload real por trás dele, apenas esses 4 bytes.\xe2\xf4 (loop) está ausente. Um stub sgn completo encerra o loop de decodificação com loop antes do corpo codificado. Aqui a execução cai direto de add ebx,[eax+0x15] em E9 8B 7C 9C — que naquele momento ainda está codificado e, de qualquer forma, não é uma sequência de instruções válida.Portanto, o stub é um espaço reservado que ocupa a cauda do payload. Isso corresponde a como o PoC foi descrito no Exploit-DB, e é a leitura honesta: esta é uma demonstração de controle do EIP, não um exploit funcional.
Avaliando isso como um corretor de exploits ou um fornecedor faria, em vez de como o vetor CVSS v3.1 o faz:
milstd1553result.txt é um arquivo que o próprio aplicativo produz, em um local que o mesmo usuário já controla. Um atacante que consiga reescrevê-lo geralmente já consegue executar código como esse usuário. Isso o torna um bug de robustez muito mais do que um bug de segurança.EIP em um build x86 da era 2020 diz pouco por si só. Transformá-lo em execução exige uma estratégia de DEP/ASLR — um módulo sem /DYNAMICBASE, uma cadeia ROP ou uma sobrescrita parcial. Nada disso foi feito, e não verifiquei quais mitigações acompanham o build atual.UI:A do CVSS v4.0 reflete a realidade; o UI:N do v3.1, não.Se alguém quiser tornar isso genuinamente interessante, as superfícies produtivas não são, de modo algum, este arquivo: o driver de kernel que a DDC distribui para suas placas PCIe 1553/664 (manipulação de IOCTL → LPE), qualquer parse de quadros ARINC 664/AFDX voltado à rede e os formatos de arquivo de entrada que o pacote consome de fontes não confiáveis. Esses cruzam fronteiras reais. Este aqui, não.
O registro do CVE carrega dois defeitos que valem ser declarados abertamente, já que está publicado sob o meu nome.
A designação de produto do registro — "dataSIMS Avionics ARINC 664-1 versão 4.5.3" — está correta. O componente afetado é o módulo ARINC 664, como consta no título original do meu Exploit-DB.
O defeito é a referência de fornecedor que a CNA anexou. A NVD cita BU-69414, que é a página de produto do software MIL-STD-1553 da DDC — uma pilha de databus diferente da que esta descoberta afeta. ARINC 664 é AFDX (Ethernet comutada com perfil, ARINC 664 Parte 7); MIL-STD-1553 é um barramento de comando/resposta duplamente redundante de 1 Mbps. São padrões sem relação entre si.
A causa provável da citação incorreta é o nome do arquivo de resultado. O dataSIMS nomeia o arquivo de resultado do módulo ARINC 664 como milstd1553result.txt — um resquício da linhagem MIL-STD-1553 do pacote. Qualquer pessoa que leia a descrição do CVE e procure uma página de produto correspondente do fornecedor seguirá essa string direto para a linha 1553, que é o que aparentemente aconteceu. O nome do arquivo não é evidência do módulo afetado, e um registro que aponta para a página do produto 1553 envia defensores para auditar o componente errado.
Ambos os vetores vêm da VulnCheck e se contradizem nos dois pontos que importam:
| v3.1 (8.4 ALTO) | v4.0 (6.7 MÉDIO) | |
|---|---|---|
| Interação do usuário | UI:N — nenhuma | UI:A — exigida |
| Impacto | C:H/I:H/A:H — CID completo | VC:N/VI:N/VA:H — apenas disponibilidade |
Ambos não podem estar corretos. O vetor v4.0 é o defensável: o PoC demonstra uma falha, não divulgação ou perda de integridade. A pontuação 8.4 do v3.1 superestima a descoberta, e prefiro afirmar isso aqui a me beneficiar dela.
Nada aqui requer o software alvo — o PoC apenas grava o arquivo malformado. Disparar o estouro exige o dataSIMS 4.5.3, que é um software comercial licenciado que este repositório não distribui.
# print the field map, write nothing
py poc/poc_py3.py --layout
# write the 1040-byte payload
py poc/poc_py3.py -o milstd1553result.txt
Em seguida, carregue o arquivo no build afetado sob um depurador e observe a sobrescrita do EIP. poc/49577.py é o código-fonte original em Python 2, arquivado na íntegra; ele não será executado no Python 3.
A porta produz um arquivo byte-idêntico de 1040 bytes (sha256 530efb5e…). Três coisas precisaram mudar, e uma coisa que parece um bug não é:
print len(win32) é uma instrução no Python 2 e um SyntaxError no Python 3.str com um shellcode bytes. O Python 2 permitia porque str era bytes; o Python 3 levanta TypeError.open(..., "w") precisa se tornar "wb". Em modo texto, o Python 3 codificaria em UTF-8 cada byte ≥ 0x80 do stub — 0xda → 0xc3 0x9a — corrompendo silenciosamente o payload e alterando seu comprimento.imp2 = "\x61\x72\x61\x63\x61\x67\x131\x7a" não é uma peculiaridade dependente de versão. \x aceita exatamente dois dígitos hexadecimais tanto no Python 2 quanto no 3, então \x131 é 0x13 seguido do caractere 1. O campo tem 9 bytes em ambos. Apenas parece errado.Declarado explicitamente para que ninguém precise adivinhar o que foi feito e o que não foi:
EIP é o resultado completo.| Data | Evento |
|---|---|
| 2020-02-17 | Vulnerabilidade encontrada |
| 2021-02-19 | PoC publicado — EDB-49577 |
| 2026-01-22 | Advisory da VulnCheck publicado |
| 2026-01-23 | CVE-2021-47881 publicado na NVD |
| 2026-06-17 | Registro da NVD modificado pela última vez |
Kağan Çapar — GitHub · Exploit-DB · LinkedIn · X