Back
Featured image of post TokGrabber (Infostealing Malware)

TokGrabber (Infostealing Malware)

TokGrabber is an information stealing Malware-as-a-Service that steals credentials, tokens, and crypto wallet. The executable that the victim runs is uniquely generated for each customer as it injects a customer identifier into the executable. The malware tries to get around detection by AES_256_CBC encryption and executing malicious code in stages. I am going to walk through how I analysis and reverse engineer this malware. Please note currently most of the script used in the process of analyzing and reverse engineering are all currently privatized as they were a collaboration with other security researchers to figure out ways to detect and possible neutralize such malware. I won’t be going into full detail on how each tool works as it also gives malware developers to figure out ways around these techniques.

Malicious URLS/Domains

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
https://github.com/wanted-by-cia/pRoTeCteDPriVaTeRePo
https://doxbin.wiki/raw/isup.txt
https://doxbin.wiki/raw/webhook?check={customer_key}
https://doxbin.wiki/raw/webhook?exodus={customer_key}
https://doxbin.wiki/raw/webhook?about={customer_key}
https://cfvsiemens.com/raw/isup.txt
https://cfvsiemens.com/raw/webhook?check={customer_key}
https://cfvsiemens.com/raw/webhook?exodus={customer_key}
https://cfvsiemens.com/raw/webhook?about={customer_key}
doxbin.wiki
cfvsiemens.com

Stage Diagram

Tokgrabber Staging Chart

Reverse Engineering

Due to the developers trying to not be detected by Anti-Virus software they decided to use PKG as their compile their Javascript to JS byte code so it’s harder for someone to come along and easily see the code. That doesn’t stop someone who is dedicated or prepared for taking on that task. The easiest way to identify that it’s a PKG executable is checking that end of the executable to see if there is Javascript.

Hex dump of Malware Sample

Setup an Isolated Environment

Because PKG compiles the javascript into byte code we need to be able to install new versions of Node get the right version of V8 to execute the malicious code to determine what it does. So we are going to use docker and n which is a Node version manager that let’s us install and switch node versions on the fly.

1
2
3
4
docker run -it --rm --name tokgrabber -v "$PWD":/usr/src/app -w /usr/src/app node /bin/bash
npm -g install n
bash
which n

Setup of docker container

Start analysis

The first thing we need to do is extract the payload and prelude from the executable which can be done just by parsing information out from the binary. Afterwards we need to brute force the version in the header of the entrypoint file to determine the correct version of Node to use.

Start of analysis

Listen to function calls

Now that we know what version of Node we need to use to continue our analysis we run our tool. This tool uses one of the techniques I can’t go into detail with currently, though generally we capture all the function calls and log them. As we can see since we are not running the entrypoint in the same directory we extract it to we need to install the node modules it needs to continue running. We install the missing module and continue to run our tool and install the missing dependencies.

Error about missing package

Install the missing packages

Execute the tool again

When we run the tool it fails again because the injector it’s trying to download from Github returns a 404. The reason for this is because the file has been renamed from INJECTOR_AES256.js to INJECTOR_AES256_2.js. It seems like this build of the malware is dead. Though that doesn’t stop us from continuing our analysis, we can just intercept the request and swap it for an older version from a commit.

Error due to trying to decrypt 404 error page

1
2
3
if (func == "request" && url == "https://raw.githubusercontent.com/wanted-by-cia/pRoTeCteDPriVaTeRePo/main/INJECTOR_AES256.js") {
    url = "https://raw.githubusercontent.com/wanted-by-cia/pRoTeCteDPriVaTeRePo/ed9a9718ea7317343387f8437214e3fe587e1069/INJECTOR_AES256.js"
}

Breaking the encryption

Now that we intercepted the request to let it download an older version of the INJECTOR_AES256.js we can continue and see how the malware decrypts the payload. Now that we execute our tool one more time, we can see that it is able to retrieve the encryption key from the decryption functions.

1
Encryption Key: 0a62a70ac6427f7720cb217e264437e530d77dc1dda55fcadc32f84309938f21

Encryption key dumped for decrypting injection

Decrypting the Injector

Now that we were able to retrieve the key from the malware we move onto decrypting INJECTOR_AES256.js.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const fs = require('fs');
const crypto = require('crypto');
const axios = require('axios');
const { argv } = require("process");

const key_hash = argv[2];
const url = argv[3];

const key = Buffer.from(key_hash, "hex");

console.log("[-] Downloading injector from url...")
axios.get(url)
  .then(res => {
    console.log("[-] Downloaded encrypted injector")
    const injectorFile = res.data.trim().split(":");

    const iv = Buffer.from(injectorFile[0], "hex");
    const encryptedText = Buffer.from(injectorFile[1], "hex");

    console.log("[-] Decrypting encrypted injector")
    let decipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
    let decrypted = decipher.update(encryptedText);
    decrypted = Buffer.concat([decrypted, decipher.final()]);

    base64Code = decrypted.toString()

    code = Buffer.from(base64Code, "base64")

    console.log("[-] Saving decrypted injector to INJECTOR_AES256_DECRYPTED.js")
    fs.writeFileSync("INJECTOR_AES256_DECRYPTED.js", code.toString('ascii'))
  })
  .catch(error => {
    console.error(error)
  })

Deobfuscate

Now to run my favorite Javascript deobfuscator which is Synchrony. Synchrony does a really good job and cleaning up most obfuscated Javascript payloads enough to go through manually and clean it up. Linked below is the fully deobfuscated and cleaned up code close to the original code without it.

1
2
npm install --global deobfuscator
synchrony deobfuscate INJECTOR_AES256_DECRYPTED.js

Deobfuscate with Synchrony

Detection

Personally I don’t have much experience with creating yara rules but due to the way they check the binary to grab the customer’s key we can use that to identify the malware currently until more signatures are found.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
    meta:
        description = "Tokgrabber - Check if an executable has tokgrabber only string"
        author = "Michael Pivonka (codedninja)"
        date = "02/15/2022"
     
    strings:
        $webhook_regex = /_____________________RTX______________________________(.*?)_____________________STX______________________________/
 
    condition:
        all of them
}