Nossos pipelines de detecção de malware recentemente acenderam um alerta em um pequeno cluster de pacotes no npm que pareciam... familiares.
Pacotes como json-bigint-extend, jsonfx, e jsonfb estavam imitando a popular json-bigint biblioteca: mesma funcionalidade, um arquivo README idêntico e até mesmo um nome de autor desconfortavelmente próximo ao mantenedor original.
Na maioria das vezes, esse padrão indica ataques comuns à cadeia de suprimentos, como typosquatting e dependency confusion, projetados para comprometer sistemas e exfiltrar Secrets. Mas este parecia diferente quase imediatamente.
Não estava tentando atingir a todos. Estava tentando atingir algo.
O sequestro
À primeira vista, json-bigint-extend comporta-se exatamente como o legítimo json-bigint biblioteca: ele exporta as funções familiares de parse/stringify usadas para suportar inteiros grandes em JSON. Na verdade, a maioria dos desenvolvedores e organizações não notaria nada incomum. Este payload é especificamente projetado para permanecer silencioso e só ser acionado quando detecta que está sendo executado dentro de um ambiente alvo específico, verificando o valor de uma variável de ambiente específica chamada SERVICE_NAME.
Assim que detecta que está no ambiente correto, ele instala dois backdoors:
Primeiro, ele instala um middleware Express direcionado, conectado especificamente a uma rota de pagamento (/v1/pay/purchase-goods). Este middleware é projetado para executar dinamicamente código adicional obtido de um endpoint. Após uma inspeção mais aprofundada do código obtido, parece ser um sistema complexo de reescrita de fluxo de caixa usado para manipular um jogo de azar.
const routeInjectionRules = {
'/v1/pay/purchase-goods': {
identify: function (handlers, fn, index) {
...
},
position: 'after',
extraMiddlewares: [function (req, res, next) {
// Translation: [Plugin] Mount risk middleware as post-payment success logic.
log('[插件] 支付成功后的后置逻辑挂载risk');
riskCode(req, res, next); // Executes dynamically fetched code
}]
}
};
Em segundo lugar, um middleware em nível de protótipo que discretamente aplica monkey-patching no Express.js, adicionando um middleware global a cada rota POST. Este middleware escuta por um segredo x-operation cabeçalho e desbloqueia quatro tipos de comandos para o operador:
- RunSQL: executa SQL arbitrário contra o banco de dados de produção.
- RunFileList: lista arquivos e diretórios no lado do servidor.
- RunFileContent: baixa o conteúdo de um arquivo escolhido.
- CompressDownload: baixa um diretório como um arquivo zip.
O painel do operador
Dentro do pacote, há também uma página HTML incorporada para um “Serviço de download de compressão de diretório” (título em chinês: 目录压缩下载服务).

Embora esta página nunca tenha sido conectada em nenhum lugar do código de backdoor que observamos, parece ser uma UI voltada para o operador para navegar e exfiltrar diretórios como arquivos zip.
Manipulando resultados de jogos de azar
A parte assustadora: essa riskCode(...) função chamada no middleware é controlada remotamente e atualizada a cada 30 segundos.
Embora o payload não seja invocado ativamente (ainda), observamos uma lógica capaz de ajustar retroativamente o histórico de jogos recentes de um usuário. O componente mais sofisticado desta backdoor é o fixFlow função, um motor de manipulação de saldo que reescreve retroativamente o histórico de apostas de um usuário para alcançar uma mudança de saldo desejada, mantendo a aparência de jogabilidade legítima.
A orquestração principal acontece neste fixFlow, que executa um pipeline de quatro fases:
// Takes a desired amount as argument
async fixFlow(backupAmount) {
// Phase 1: Load recent cashflow records
const original = await this.getCashFlow();
// Phase 2: Compute required adjustments to betting history
const adjuster = new GameResultAdjuster({ debug: false });
const adjustResult = adjuster.adjustDBData(original, backupAmount);
const { backupRecords, adjustedResult } = adjustResult;
const rewritten = this.writeBackFlowData(backupRecords);
// Phase 3: Validate consistency
const validation = this.validateCashFlowChain(...);
if (!validation.isValid) {
...
}
// Phase 4: Persist to database
await this.updateUserCashFlow(rewritten);
await sendToUser(userId, { pop: false });
await this.updateUserGameRoundFlow(gameTasks);
}
A função carrega registros recentes de fluxo de caixa e os converte em logs de jogo estruturados. Posteriormente, o adjustDBData método gera resultados de apostas substitutos projetados para produzir uma alteração de saldo fabricada. O interessante é que, em vez de depender de um único algoritmo, ele executa duas estratégias concorrentes (greedy vs. backtracking), e seleciona a abordagem com a maior pontuação de "realismo". Após verificar a consistência da cadeia de saldo reescrita, updateUserCashFlow e updateUserGameRoundFlow grava os registros alterados via Prisma de volta ao banco de dados de produção ativo, enquanto sendToUser envia o evento de saldo atualizado para o dispositivo do usuário.
Estratégia de Fraude Greedy
A abordagem greedy divide o valor alvo desejado igualmente entre as rodadas disponíveis. É rápida, mas produz padrões suspeitos. Imagine que você precisa distribuir 300 moedas fabricadas em 3 rodadas de jogo. A abordagem greedy simplesmente divide igualmente: 100 por rodada. Para cada rodada, ela define o pagamento para atingir o resultado desejado daquela rodada. No entanto, isso tende a parecer falso. Jogos reais não atingem resultados consistentes em todas as rodadas.
Busca por Backtracking
A abordagem de backtracking explora todo o espaço de soluções, tentando diferentes combinações de apostas/pagamentos até encontrar uma que atinja o alvo desejado dentro de uma margem de erro de 0,01%. Em vez de se comprometer com decisões imediatamente, ela explora toda a árvore de possibilidades. Tente um valor de aposta, veja onde ele leva e, se não funcionar, desfaça e tente uma aposta diferente. Isso é como resolver um labirinto tentando cada caminho até encontrar a saída. Essa abordagem encontra uma cadeia realista de resultados que considera restrições, como o dinheiro disponível do usuário no momento da aposta.
Funciona da seguinte forma:
- Gerar uma lista de valores de aposta possíveis
- Filtrar apostas que o usuário não pode pagar
- Pontuar cada um pela "alcançabilidade" ao alvo desejado
- Tentar a opção com melhor pontuação primeiro
- Se levar ao sucesso, terminamos
- Se levar ao fracasso, desfazer e tentar a próxima aposta
O algoritmo emprega várias otimizações, como memoization para evitar a reexploração de tentativas falhas, e reachability pruning para pular ramos que não podem matematicamente atingir o alvo desejado.
Pontuação de Qualidade: Fazendo a Fraude Parecer Natural
Após a execução de ambas as estratégias, o sistema aplica um mecanismo sofisticado de pontuação de qualidade que avalia o quão "realista" um histórico de apostas forjado parece. Essa pontuação determina qual saída da estratégia de fraude é utilizada e serve como uma métrica para o sucesso do ataque.
// Gerar uma pontuação de qualidade
const overallQuality = this.evaluateLogsQuality(adjustedGameLogs, completeness.actualNetGain);O evaluateLogsQuality função começa com 100 pontos e deduz penalidades por padrões suspeitos. Algumas dessas penalidades incluem:
- Apostas Impossíveis (Penalidade: -100): Uma aposta que excede o saldo disponível é impossível em um jogo real. Ela seria rejeitada pelo servidor do jogo.
- Pagamentos Órfãos (Penalidade: -2): Um pagamento sem uma aposta correspondente na mesma rodada é estruturalmente inválido. Em um jogo legítimo, todo pagamento é resultado de uma aposta. Um pagamento que aparece do nada sugere adulteração de registros.
- Rodadas Intercaladas (Penalidade: -1 a -40 por gravidade): Jogadores reais geralmente completam uma rodada antes de iniciar outra. Intercalação excessiva, ou seja, iniciar múltiplas rodadas simultaneamente, parece comportamento de bot ou manipulação.
- Multiplicadores Irrealistas (Penalidade: -15): Ganhar com 100x ou mais é raro. Se mais de 10% das rodadas mostrarem multiplicadores extremos, o padrão parece fabricado e uma penalidade é aplicada. O algoritmo guloso simples tem a tendência de produzir este padrão.
- Jogabilidade Monótona (Penalidade: -10): Um jogador que perde todas as rodadas em muitos jogos é suspeito, mesmo jogadores azarados ganham ocasionalmente.
Em conclusão, significa que o objetivo não é apenas fraude. É uma fraude que sobrevive a verificações de consistência interna, fabricando vitórias e perdas enquanto mantém a contabilidade consistente usando um mecanismo inteligente de antideteção.
Bappa Rummy
Não podemos dizer com certeza qual jogo está sendo alvo, mas referências circundantes sugerem que pode ser um aplicativo de apostas chamado Bappa Rummy. Um dos endpoints referenciados no arquivo é gameland.myapptest.top/v1, e uma rápida pesquisa de transparência de certificado SSL para esse domínio mostra hosts relacionados como gali.web.test.myapptest.top. Inspecioná-lo revela o que parece ser uma landing page quebrada ligada ao Bappa Rummy, tornando-o um alvo plausível do backdoor. O aplicativo parece ser amplamente promovido online através de programas de indicação e lojas de aplicativos alternativas, mas não está mais listado na Google Play Store oficial.

Detecção e prevenção
Embora não saibamos quem está por trás do backdoor, a parte assustadora é o que ele faz quando chega ao ambiente certo. Este não é “apenas” um implante de dependência típico que exfiltra código-fonte, Secrets ou dados de clientes.
Em vez disso, ele se conecta diretamente à lógica de negócios, executa código controlado remotamente em tráfego real e pode reescrever o histórico financeiro baseado em banco de dados. Se seu monitoramento assume que os logs do banco de dados são confiáveis, esse tipo de manipulação pode permanecer invisível por muito tempo.
Se você já usa Aikido, este pacote seria sinalizado em seu feed como uma descoberta crítica 100/100.
Ainda não usa Aikido? Crie uma conta gratuita e conecte seus repositórios. O plano gratuito inclui nossa cobertura de detecção de malware (não é necessário cartão de crédito).
Finalmente, ter uma ferramenta que pode interromper malware em tempo real assim que ele aparece pode prevenir uma infecção grave. Esta é a ideia por trás do Aikido Safe Chain, uma ferramenta gratuita e de código aberto que envolve npm, npx, yarn, pnpm e pnpx, e usa tanto IA quanto pesquisadores humanos de malware para detectar e bloquear os mais recentes riscos da cadeia de suprimentos antes que entrem em seu ambiente.
Indicadores de comprometimento
Pacotes e autores:
- jsonfb (por sidoraress)
- jsonfx (por sidoraress)
- json-bigint-extend (por sidoraress e infinitynodestudio)
O backdoor se comunica com um host remoto para atualizações de payload e logging.
Endpoints observados:
https://payment[.]y1pay[.]vip/v1/risk/get-risk-codehttps://payment[.]y1pay[.]vip/v1/risk/loghttps://payment[.]snip-site[.]cchttps://gameland[.]21game[.]livehttps://gameland[.]myapptest[.]top/v1https://gameland[.]nbzysp1[.]com/v1https://gameland[.]21game[.]live/v1
Outros IOCs e comportamentos rastreáveis:
- Requisições contendo
x-operation headercom um dos quatro tokens de operação:- RunSQL (token: cfh2DNITa84qpYQ0tdCz)
- RunFileList (token: m3QiEkg8Y1r9LFTI5e4f)
- RunFileContent (token: Y3SrZjVqWOvKsBdpTCh7)
- CompressDownload (token: SJQf31UJkZ1f88q9m361)
- Modificações em tempo de execução para
express.Route.prototype.post

