# Como identifiquei um golpe em “teste técnico”: análise real de um malware direcionado a desenvolvedores

> Recebi um “teste técnico” que era malware. A engenharia reversa de um golpe direcionado a desenvolvedores: como o código escondia um Remote Code Execution, o que o payload roubava, e os reflexos que evitam isso.

Allan Lancioni. 2025-12-05.
https://allanlancioni.com/pt/artigos/golpe-teste-tecnico

---
## Por que esse caso é importante

Essa semana recebi uma oportunidade “imperdível” no LinkedIn: vaga sênior, salário em USD muito acima da média, remoto, flexível.

Troquei algumas palavras com suposto CEO da empresa, e então ele mandou **o teste técnico.**

Era só um projeto React.

Mas se eu tivesse rodado um `npm start` sem olhar o código, teria entregado chaves, dados pessoais, histórico do navegador e até dinheiro.

Nesse artigo faço a engenharia reversa de um golpe que recebi, explicando como funciona o ataque pelos vetores técnico e social, e mostrando como se prevenir.

## 1. Identificando o primeiro contato

O golpe começa no LinkedIn.

O alvo costuma ser desenvolvedores experientes, especialmente quem já trabalhou com blockchain, criptomoedas ou devs JavaScript. São perfis de alto ROI para o atacante.

O “recrutador” se apresenta como CEO de um projeto novo. O perfil parece legítimo, a empresa também: site básico, descrição coerente, JD bem escrita e vaga pagando acima da média.

O fluxo é:

- ele pede seu CV e GitHub
- diz que você “passou na primeira etapa”
- afirma que a próxima etapa é uma entrevista técnica
- mas antes disso, te envia a codebase para “estudo”, supostamente para você se preparar para a entrevista

É aí que o ataque acontece.

![Mensagem do suposto CEO com um link de repositório do GitHub, borrado, pedindo que eu examine a UI, a estrutura e o fluxo do projeto antes da conversa](/img/golpe-teste-tecnico/mensagem-do-ceo.png)

*Mensagem do suposto CEO*

**Red flags:** salário alto demais, buzzwords como *blockchain/cripto*, codebase antes de entrevista, urgência no processo, perfis e sites com sinais de simulação

## 2. O primeiro alerta: um script de start “inocente” demais

Ao abrir o repositório, algo no `package.json` me chamou atenção:

```json
"start": "npm run check-env && npm run app:pre | react-scripts start
```

Antes de iniciar o projeto React, dois scripts eram executados: `check-env` e `app:pre`.

Ao abrir o `check-env`, encontrei algo bem específico: **o script bloqueava a execução em VSCode, GitPod e outros ambientes isolados.**

***Por que um projeto React impediria execução em ambiente isolado?***

Isso é uma forma do código garantir execução *no terminal real*, com acesso ao Sistema Operacional.

![Trecho de check-environment.js: um if que detecta Gitpod ou Codespaces, imprime que rodar o projeto naquele terminal não é suportado, e encerra o processo](/img/golpe-teste-tecnico/bloqueio-ambiente-isolado.png)

*Código bloqueando execução em ambientes isolados*

## 3. Usando o Copilot como scanner de anomalias

Não rodei o projeto.

Pedi ao Copilot para scanear o projeto em busca de potenciais ameaças.

Ele encontrou isto:

![Relatório do Copilot apontando Remote Code Execution como ameaça principal em frontController.js: uma URL em Base64, o envio de todas as variáveis de ambiente para um servidor externo, e a execução do que volta via new Function](/img/golpe-teste-tecnico/scanner-copilot.png)

*Scanner do Copilot indicando padrões suspeitos*

O arquivo `frontController.js`, executado em `npm run app:pre`, em ~15 linhas, tinha:

- um token grande que na verdade era uma URL ofuscada em Base64
- um uso perigoso de `new Function`
- uma chamada a `verify()` que enviava dados para um servidor desconhecido

Comecei a investigar.

## 4. O ponto crítico: Remote Code Execution (RCE)

Havia apenas um trecho de código suspeito no projeto, e ele estava disfarçado como "verificação de API".

Vamos analisar o código de ataque:

![Bloco de código com uma constante VERIFICATION_TOKEN em Base64 e a função validateApiKey, que chama verify e executa a resposta do servidor com new Function, tudo sob mensagens de log que falam em verificar a chave de API](/img/golpe-teste-tecnico/codigo-malicioso.png)

*Código malicioso*

Esse bloco é o coração do ataque. As funções auxiliares ajudam a mascarar o fluxo:

![As duas funções auxiliares: setApiKey, que é apenas um atob, e verify, que faz um axios.post enviando todo o process.env com um header de segredo](/img/golpe-teste-tecnico/funcoes-auxiliares.png)

*Funções auxiliares do código malicioso*

### O que realmente acontece aqui

- ao iniciar o projeto, a função `validateApiKey()` é executada
- o "Token" é uma URL escondida em Base64
- `setApiKey()` decodifica essa URL
- `verify()` envia uma requisição HTTP para esse servidor externo
- o servidor responde com um script JavaScript completo
- o projeto executa esse script localmente via `new Function("require", response.data)`

O `new Function` funciona como uma porta aberta no ambiente de execução: ele aceita uma string e transforma aquilo em código real. É o mesmo princípio do `eval`, só com outra sintaxe.

> Se você rodar `new Function` vindo da internet, não é azar quando dá errado. É consequência.

Isso é **Remote Code Execution (RCE). O atacante controla o que a sua máquina executa no momento em que você roda o projeto.**

O repositório é só o “veículo”. O ataque real está no servidor.

## 5. Testando o endpoint em ambiente controlado

Ao decodificar o Base64, encontrei a URL:

```
https://ip-api-test.vercel.app/api/ip-check-encrypted/3aeb34a31
```

Via GET, devolvia apenas o IP. Normal.

Mas via POST, replicando headers e variáveis do projeto, recebi exatamente o esperado:

![Resposta do servidor em um terminal: cabeçalhos de um app Express seguidos de um corpo de centenas de milhares de caracteres, tudo em hexadecimal e nomes de variáveis ofuscados](/img/golpe-teste-tecnico/payload-via-curl.png)

*Trecho do payload malicioso retornado pelo servidor via CURL*

**Um payload de ~700k caracteres, totalmente ofuscado**, ou seja, modificado para dificultar a leitura.

![O mesmo payload passado por um beautify: dá para ler hostname, plataforma, diretório home, um hostURL montado por concatenação de strings, e funções de caminho de arquivo ainda ofuscadas](/img/golpe-teste-tecnico/payload-reconstruido.png)

*Código do malware ofuscado parcialmente reconstruído com beautify.js*

## 6. O que o script fazia de verdade

Era malware. **Um stealer voltado para cripto.**

Reconstruindo trecho a trecho com LLMs, ficou claro o funcionamento:

- famílias de browsers separadas
- caminhos específicos por navegador
- lista de IDs de wallets (MetaMask, Binance, etc...)
- arquivos-alvo por wallet
- domínios de destino para envio

![Código reconstruído com os caminhos de perfil de Brave e Chrome nos três sistemas operacionais, e uma função uploadFiles com a lista de IDs de extensão da Chrome Web Store para MetaMask, Binance, Phantom, TronLink, Ronin, Keplr e Solflare](/img/golpe-teste-tecnico/browsers-e-wallets.png)

*Código reconstruído mostrando browsers e wallets*

O alvo: **roubar wallets e sessões armazenadas no navegador do desenvolvedor.**

## 7. Conclusão

O que mais chamou atenção nesse caso não foi o código malicioso em si, mas o contexto em que ele foi entregue.

O ataque não dependia de vulnerabilidade técnica, dependia de confiança.

Uma oferta boa demais, um “teste técnico”, um projeto aparentemente legítimo.

Uma única ação esperada: **rodar o código.**

### Reflexos que vale desenvolver

- **Leia o que vai rodar.** Especialmente `start`, `prestart`, `postinstall`.
- **Código desconhecido só em ambiente isolado.** Use sandbox: WSL, VM ou Docker.
- **IA como scanner.** Um Copilot ou LLM lendo o código com você pode ser bem útil.
- **Repo falso deixa cheiro.** Commits nonsense, autores novos, nada sendo realmente modificado...

![Lista de commits de um repositório: quatro mensagens genéricas do tipo "Implement feature in topIcon4.png" e "Add tests in readme.txt", de autores diferentes, todas no mesmo dia, três delas sem verificação de assinatura](/img/golpe-teste-tecnico/sinais-de-simulacao.png)

*Sinais de simulação em repositório aparentemente legítimo*