Aikido

O MECCHA CHAMELEON não consegue esconder-se do RCE

Escrito por
Robbe Van Roey

Resumo: Descobrimos outra vulnerabilidade de execução remota de código (RCE) de tipo «delayed» no MECCHA CHAMELEON. Ao jogar num mapa criado pelo atacante, este pode explorar uma função exposta para gravar ficheiros de forma arbitrária no sistema da vítima. Isto pode levar à execução remota de código no sistema da vítima após um reinício. Comunicámos o problema aos responsáveis pela manutenção do jogo, que corrigiram a vulnerabilidade na atualização 4.0.0. Esta atualização é instalada automaticamente antes do arranque do jogo.

Se és um jogador, provavelmente já ouviste falar do MECCHA CHAMELEON. Este jogo de escondidas online tornou-se uma obsessão mundial, tendo vendido 15 milhões de cópias no seu primeiro mês!

Como jogador, tens uma tarefa muito engraçada: encontrar um bom esconderijo e pintar uma personagem branca em branco para se misturar com o cenário. Depois, um dos teus amigos virá à tua procura. Ganhas se o caçador não te conseguir encontrar. É tão simples quanto isso!

Página inicial do Meccha Chameleon

Os mapas criados pela comunidade são uma grande parte do encanto do jogo. Qualquer pessoa pode criar um novo mapa onde os jogadores se possam esconder e publicá-lo através do Steam Workshop. Estes novos mapas podem ser uma galeria de arte, áreas nostálgicas de outros jogos e assim por diante.

Loja Meccha Chameleon, com vários mapas jogáveis

Houve uma característica específica que nos chamou a atenção: quando jogas num servidor, o anfitrião da sala escolhe o mapa e, em seguida, todos os jogadores nessa sala são instados a descarregar esse mapa (o ecrã avisa-te se ainda não o tiveres descarregado e estiveres a atrasar o jogo!). Isso é muito prático, mas também significa que entrar numa partida pode implicar carregar um mapa criado por alguém que nunca conheceste. Queríamos descobrir o que esse mapa descarregado podia realmente fazer.

No passado, o MECCHA CHAMELEON já tinha sofrido um RCE aquando do carregamento do mapa, tal como detalhado nesta publicação do blogue. Esse bug específico já foi corrigido, mas será que isso eliminou todas as vias de acesso ao RCE?

O que é, afinal, um mapa MECCHA CHAMELEON?

Podes pensar que um mapa se resume a alguns recursos: modelos para o cenário e texturas para que tudo tenha o aspeto correto. É assim que um mapa funciona em muitos jogos, em que o ficheiro descarregado descreve o nível, enquanto o próprio jogo controla a lógica.

Os mapas do MECCHA CHAMELEON oferecem ainda mais controlo. O jogo foi desenvolvido com o Unreal Engine 5.6.1 e os seus mapas podem conter Blueprints. O Blueprint é o sistema de programação visual da Unreal. É possível ligar nós para que algo aconteça quando um jogador carrega num botão, entra numa área ou simplesmente carrega o mapa.


https://dev.epicgames.com/documentation/unreal-engine/introduction-to-blueprints-visual-scripting-in-unreal-engine

É claro que um mapa não pode chamar todas as funções dentro do Unreal ou do MECCHA CHAMELEON. Uma função nativa tem primeiro de ser exposta ao Blueprint. Quando o mapa é iniciado, os seus gráficos são executados dentro do processo do MECCHA CHAMELEON. Se um gráfico chamar uma função exposta, o jogo executa essa ação utilizando a conta e as permissões do jogador.

Isto significa que os mapas personalizados constituem uma superfície de ataque interessante:

  • Um anfitrião da sala pode solicitar a todos os outros jogadores que descarreguem e executem um mapa.
  • Esse mapa pode, então, executar gráficos Blueprint dentro do jogo.

Então, comecei a prestar atenção às funções do motor a que conseguia aceder.

Encontrar funções que podem ser chamadas

Felizmente, não precisamos de adivinhar quais são as funções que o Unreal disponibiliza. Podemos abrir um gráfico de Blueprint e clicar com o botão direito do rato numa área vazia. O Unreal apresenta então um menu pesquisável de nós que podem ser adicionados a esse gráfico.

Do ponto de vista da segurança, o meu interesse centrou-se principalmente nas funções que interagiam de alguma forma com o sistema operativo. Por isso, procurei aquelas que continham guardar, exportação, escrever, registo, open, lançamento, e load. Passámos de uma lista enorme de APIs para uma lista mais fácil de gerir, que eu pudesse analisar.

Assim, uma a uma, fui analisando essas funções até me deparar com Concluir a gravação da saída. Este destacou-se porque permitia criar um ficheiro no sistema de ficheiros com um caminho que pode ser absoluto ou relativo. Também armazena a saída de áudio, que provavelmente poderemos controlar de alguma forma.

Gravar ficheiros em qualquer local

Portanto, para utilizar o Concluir a gravação da saída Na função, quem estiver a criar um mapa deve iniciar uma gravação, reproduzir um som e, em seguida, parar a gravação. Em seguida, indicamos um nome e um caminho para guardar o ficheiro. A função está documentada em pormenor aqui.

Então, este é um caso bem claro de «Basta indicar qualquer diretório e qualquer nome de ficheiro, e podemos guardar esses ficheiros em qualquer lugar do sistema», certo?

Pois é. Basta fornecer C:/Utilizadores/Público/ como caminho do ficheiro e gravar os ficheiros nesse local, ou pode indicar um caminho relativo. O diretório predefinido utilizado é C:\Users\<user>\AppData\Local\Chameleon\Saved\BouncedWavFiles, pelo que, ao indicar um caminho que comece por ../../../../../, poderíamos aceder à pasta pessoal do utilizador sem precisarmos de saber o seu nome de utilizador.

Assim, agora podemos gravar ficheiros em qualquer local do sistema de ficheiros. A forma mais fácil de transformar isso numa execução remota de código diferida é gravar um executável em C:\Users\<user>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup. Sempre que o seu dispositivo for iniciado, irá executar automaticamente todos os ficheiros desta pasta.

Por isso, indicámos este valor como nome do registo:

../../../../Roaming/Microsoft/Windows/Menu Iniciar/Programas/Inicialização/poc.exe

E quando criámos e implementámos o nosso mapa, reparámos que...

Funcionou, mais ou menos? De facto, gravámos um ficheiro na pasta de arranque. Mas a extensão .exe não ficou mantida. O Unreal Engine está a adicionar a extensão .wav a qualquer nome de ficheiro que introduzamos e, por isso, o Windows continua a tratar o ficheiro como um WAV em vez de um executável.

Remover a extensão .wav

Pensei um pouco sobre como poderíamos contornar isto. O que temos aqui é um caso clássico de dois sistemas diferentes que partem de pressupostos diferentes. O Unreal Engine tem a sua forma de lidar com um caminho e o Windows tem a sua forma de interpretar um caminho. Só tinha de encontrar uma discrepância entre eles.

No caso do Unreal Engine, é incrivelmente simples: basta detetar uma cadeia de caracteres e acrescentar .wav nisso. O Windows é um pouco mais complexo. O Windows tem limites máximos para o comprimento dos nomes de ficheiros e caracteres que não são permitidos num caminho, tais como o carácter nulo (U+0000).

Mas o que acontece quando tentamos criar um ficheiro com um carácter nulo no nome? Bem, na maioria das vezes, aparece um erro:

Mas nem todas as APIs geram um erro. Algumas APIs de nível inferior interpretam, de facto, os bytes nulos como um caractere terminador e descartam tudo o que se segue:

E se tentássemos usar o nosso mapa malicioso para guardar uma gravação em:

POC.exe\u0000IGNORADO

Podemos ver que funcionou! Agora já podemos guardar ficheiros com nomes à escolha em locais à escolha no sistema de ficheiros!

Mas continua a haver uma questão importante. Estamos apenas a gravar os bytes de uma gravação de áudio WAV num ficheiro com um .exe extensão. Temos de controlar, de alguma forma, também o conteúdo desse ficheiro para o tornar executável!

A janela pop-up indica: «Esta aplicação não pode ser executada no seu PC»

Bytes maliciosos numa gravação de áudio

Tínhamos agora um novo desafio pela frente. Estávamos a guardar uma gravação de áudio real como ficheiro WAV num local arbitrário. Mas, para que esta exploração funcionasse, também precisávamos de conseguir controlar o que era gravado nesse ficheiro.

Para tal, vamos utilizar um ficheiro WAV PCM não comprimido. O WAV é o formato de ficheiro container, que contém alguns metadados seguidos de dados de áudio. Os ficheiros WAV podem armazenar áudio em vários formatos, pelo que o .wav A extensão, por si só, não nos diz como as amostras são codificadas.

PCM significa Modulação por Código de Pulso. Com o PCM, cada medição da onda sonora é armazenada diretamente como um número. A nossa prova de conceito utilizou PCM de 16 bits, pelo que cada amostra ocupava exatamente dois bytes. «Não comprimido» significa que esses números foram gravados sem passar por um codec, como o MP3.

Um ficheiro WAV PCM não comprimido é composto por valores de amostras de áudio. Se controlarmos esses números com precisão, controlamos também os bytes utilizados para os armazenar.

Isto é muito importante porque a compressão de áudio normal procura preservar a forma como um som é percebido, e não os bytes exatos de cada amostra. Assim, uma versão comprimida pode soar idêntica, embora contenha bytes muito diferentes.

Um ficheiro WAV simplificado tem o seguinte aspeto:

+-------------------------------+
| Cabeçalho RIFF/WAVE              |  Criado pelo Unreal
| Formato, canais, frequência de amostragem |
| Tamanho da secção de dados      |
+-------------------------------+
| Amostras PCM 0                  |  Controlada através da onda sonora
| Amostra PCM 1                  |
| Amostra PCM 2                  |
| ...                           |

O Unreal controla o cabeçalho, incluindo o RIFF e WAVE identificadores. Não podemos modificá-los porque o nosso controlo sobre o ficheiro só começa na secção de dados PCM. Isso exclui muitos executáveis da nossa exploração. Não podemos carregar um ficheiro normal .exe ou .dll, uma vez que ambos necessitam de um cabeçalho PE válido para serem executados.

Por isso, precisávamos de um tipo de ficheiro cujo analisador não exigisse que o cabeçalho fosse encontrado no primeiro byte. As Aplicações HTML do Windows revelaram-se a solução ideal.

Um Aplicação HTML é um formato antigo do Windows com o .hta extensão. O ficheiro assemelha-se bastante a uma página web: pode conter HTML, CSS e JScript ou VBScript. O Windows abre-o com mshta.exe (Microsoft HTML Application Host).

A diferença importante em relação a uma página web normal reside no local onde esse script é executado. Um ficheiro HTA é tratado como uma aplicação de ambiente de trabalho, em vez de uma página dentro da área de segurança do navegador. O seu script pode criar objetos COM do Windows, incluindo WScript.Shell, o que pode dar início a outro processo.

Uma versão simplificada da nossa carga útil de prova de conceito tem o seguinte aspeto:

[RIFF/WAVE header ...]
<html>
  <head>
    <hta:application />
    <script>
      new ActiveXObject("WScript.Shell").Run("calc.exe");
    </script>
  </head>
</html>

Quando este ficheiro for aberto, mshta.exe ignora os metadados do ficheiro WAV que se encontram no início e executa o script. Em seguida, WScript.Shell abre a Calculadora.

O desafio que restava era inserir esse código HTML e esse script nas amostras PCM do ficheiro WAV.

Our payload used 16-bit PCM. Each sample is a 16-bit number stored in little-endian order, meaning the least significant byte is written first. Take the sample value 0x683C: it appears in the WAV as 3C 68, which also happens to be the ASCII text <h.

The same conversion works for a longer string. The text <html> has these ASCII bytes:

3C 68 74 6D 6C 3E

Ao agrupá-los em pares, obtemos três valores de amostra de 16 bits:

Bytes:    3C 68 | 74 6D | 6C 3E
Amostras:  0x683C  0x6D74  0x3E6C

Quando esses samples são gravados novamente num ficheiro WAV em little-endian, os bytes originais reaparecem. Na verdade, foi preciso muita experimentação para que isto funcionasse, mas, no final, conseguimos criar um ficheiro WAV verdadeiro que continha o nosso hta carga útil.

Um ficheiro de texto com muitos símbolos aleatórios, uma vez que se trata de um ficheiro WAV

Montar o mapa

Nesta fase, cada parte funcionava por si só. O que faltava era integrar tudo num mapa que pudesse executar o ataque completo de uma só vez, assim que o nível fosse carregado.

Por isso, associamos a Começar a jogar e faça o seguinte:

  1. Iniciar Gravação de Saída num submix privado (para evitar interferências do áudio habitual do jogo)
  2. PlaySound2D com o nosso PCM não comprimido já preparado
  3. Parar a gravação da saída usando ../../../../Roaming/Microsoft/Windows/Menu Iniciar/Programas/Inicialização/poc.exe\u0000IGNORADO como nome do ficheiro
Gráfico do Blueprint do Unreal Engine que mostra a cadeia de ataque: o evento «BeginPlay» liga-se aos nós «Start Recording Output», «Play Sound 2D» e a um «Delay»; em seguida, um nó «Finish Recording Output» grava um ficheiro WAV num caminho malicioso da pasta de arranque.

Criámos o mapa e publicámo-lo (em privado!) no Steam.

Mapa do POC, com um meme do Borat como descrição

E foi assim que chegámos a este vídeo de prova de conceito:

Então, o MECCHA CHAMELEON já é seguro?

A vulnerabilidade que comunicámos já foi corrigida e já não pode ser explorada. A Parar a gravação da saída A função já não cria quaisquer ficheiros (nem mesmo os ficheiros pretendidos).

Também verificámos todos os mapas do Steam Workshop para ver se algum já estava a tirar partido desta falha, mas não encontrámos nenhum que o estivesse a fazer.

No entanto, enquanto trabalhávamos neste PoC, várias pessoas entraram em contacto connosco para nos informar de que poderiam existir outras vulnerabilidades no MECCHA CHAMELEON. Não forneceram detalhes e estas vulnerabilidades não foram comprovadas nem verificadas por nós.

Por isso, apelamos à vossa cautela e vigilância ao jogarem utilizando mapas personalizados. Recomendamos que joguem apenas nos mapas oficiais fornecidos pela MECCHA CHAMELEON.

Cronograma de divulgação

  • 11 de agosto de 2026: Tentei entrar em contacto através do Twitter
  • 12 de agosto de 2026: Tentei entrar em contacto através do Discord
  • 13 de agosto de 2026: Tentei entrar em contacto com o apoio ao cliente da Steam e enviar um e-mail para o endereço do programador
  • 17 de agosto de 2026: Consegui contactá-los novamente através do Twitter. O programador respondeu que iria resolver o problema.
  • 20 de agosto de 2026: Foi lançada a versão MECCHA CHAMELEON 4.0.0 com uma correção para esta vulnerabilidade
Compartilhar:

https://www.aikido.dev/blog/meccha-chameleon-rce

Verificar por malware

Comece Gratuitamente
4.7/5
Cansado de falsos positivos?

Experimente Aikido como 100 mil outros.
Começar Agora
Obtenha um tour personalizado

Confiado por mais de 100 mil equipes

Agende Agora
Escaneie seu aplicativo em busca de IDORs e caminhos de ataque reais

Confiado por mais de 100 mil equipes

Iniciar Escaneamento
Veja como o pentest de IA testa seu aplicativo

Confiado por mais de 100 mil equipes

Iniciar Testes

Fique seguro agora

Proteja seu código, Cloud e runtime em um único sistema centralizado.
Encontre e corrija vulnerabilidades rapidamente de forma automática.

Não é necessário cartão de crédito | Resultados da varredura em 32 segundos.