Predator the Thief

January 29, 2020

Overview

Predator the Thief is a sophisticated malicious stealer which has been on the scene for around one and a half years. What started as coding experiments in malware development later evolved into a full-fledged menace to be reckoned with. Current versions of Predator use various anti-debugging and anti-analysis techniques to complicate analysis on the part of researchers while still smoothly performing data stealing.

In this article we provide a retrospective analysis of the evolution process for Predator the Thief, journey into the Darknet and its malware sales, take peeks at the data left behind by the malware authors, and describe the malware itself.

Background

Darknet

Predator the Thief was initially offered for sale on a Russian Darknet forum by Alexuiop1337 more than 1.5 years ago, on June 17, 2018.

It is no longer available there, as this forum states it doesn’t deal with malicious tools anymore:

Screenshot from forum with question about Predator the Thief thread and response stating that selling malware is now forbidden

This was the initial sale offer for Predator:

And some details on the offer:

We have counted at least 5 different versions since then. While it may seem a low number, each version added something significant to the malware and the author is still continuing to enhance its capabilities.

Where it is sold now

Currently Predator is offered on another Russian forum as well as on the Telegram channel. Its price is $150, plus an additional $100 may be paid for the Clipper module which allows the buyer to customize stealing options for crypto-wallets.

At the end of September 2019, this channel had only 773 subscribers. In a single month, the number of subscribers increased by one hundred, with a total of 875 subscribers to Telegram channel as of October 30.

Development of the malware is ongoing and updates to Predator are posted regularly.

This is the transcript of the Telegram message which describes changes in Predator v.3.3.0, the sample we obtained:

Update v.3.3.0 as of 19.08.2019:

Module Clipper

* new module clipper, price is $100

Module Loader

* added option “random filename” for methods ShellExecute and CreateProcess

Panel

* “Domain Detect” for cookies was re-written with AJAX and now works realtime as well as passwords

* changed log view

* separated filters by general parameters, passwords and cookies

* fixed bug with transferring logs to other users

* fixed bug with wrong loader statistics

Stealer:

* temprorary removed support of *.onion domains

* completely changed Outlook harvesting

* implemented harvesting of new cold wallets and fixed paths for harvesting of old ones

* mail client ThunderBird is now displayed correctly in passwords file

* possibility to add one reserve domain to the build

* other minor fixes and tweaks

Peculiar thing is that author uses this channel not only for pure advertisement, but for publications on general topics as well. For example, there is a post on anti-disassembly tricks and their implementation is C/C++ code. Some methods which are implemented in Predator to harden the analysis are described in this article. Sources used in this publication reside in author’s GitHub
https://github.com/Alexuiop1337/AntiDisassembly

It appears that the author puts some love in his creation as well as in what he’s doing overall.

Panel

We were able to obtain Predator the Thief panel source code which helped us to gather more information.

Panel interface looks like this:

It is in Russian which once again proves its origin.

The author of certain panel scripts identifies himself as “melloy”:

* author of this script Melloy

Panel is written in PHP while malware is written in C++. There is nothing controversy in the ability to write code in both languages, however we can’t say for sure that the author of Predator and the author of its panel is the same person.

Links with the actors

The table below contains resources which are linked with the authors of Predator the Thief.

Description Link Where this lead was got from
GitHub https://github.com/Alexuiop1337 Darknet and Telegram channel
Predator Beta (C#) https://github.com/Alexuiop1337/PredatorTT-Beta-Old
Twitter https://twitter.com/alexupi1
VK https://vk.com/alexinde Panel source code

 

Judging by avatars in Twitter and VK, we can say that people (or a single person) behind the accounts like anime girls:

Avatar of the malware author in Twitter

 

Page of the malware author in VK

We can’t say for sure that both malware and panel were written by the same person though certain patterns from these leads match:

  • Prefix “Alex” in a nickname
  • Anime girl in the avatar

Technical details

Malware flow

The entire malicious job is conducted in the address space of original executable. Several layers of unpacking and XOR-decryption are performed until main payload is reached.

Functionality

Malware steals data of various browsers, email clients, crypto-wallets and other software. It also takes desktop screenshot. This information is stored in ZIP archive which resides in memory and then sent to C2C.

 

What it is targeting

It steals credentials from various applications:

Browser and email clients Chrome based browsers
Firefox based browsers
Opera
Outlook
Thunderbird
Crypto-wallets

(any crypto-system which stores `wallet.dat` is affected)

Armory
Atomic
Bytecoin
Electrum
Ethereum
Jaxx
MultiBit
Other software and accounts Authy
BattleNet
Discord
Jabber
NordVPN
Osu
Pidgin
Skype
Steam
Telegram
WinFTP
WinSCP

 

It also gets system information (clipboard included) in the following manner:

As a final touch, Predator the Thief grabs the list of installed software and takes desktop screenshot.

The data is archived and is organized like shown in the following screenshot:

Mutex creation

Some recent versions of Predator the Thief create mutex with name transformed from disk volume serial number.

 

Anti-debug techniques

Predator the Thief implements various techniques to harden the analysis.

1.      Hiding thread from debugger

Current thread is hidden from debugger with the call of NtSetThreadInformation and HideFromDebugger enum argument (11h):

In order to bypass this detection method, we have to skip the call and return 0 (STATUS_SUCCESS) as a result.

Here lies another trap. There is another call right after this call. This time with slightly different arguments:

Note the difference in 3rd and 4th arguments which should be set to NULLs in order for the function to be executed correctly. If wrong arguments are passed, then 0xC0000004 error code is returned. And this is precisely what malware expects from the 2nd call: it is waiting for the error code to be returned. Thread will not be hidden from debugger in this case.

If researcher gives up to temptation of skipping this 2nd call to NtSetThreadInformation function with wrong arguments and will set result to 0, it will lead malware through another branch – which will cause termination instead of correct execution.

To sum it up: 1st call must be skipped. 2nd call must be executed as is, or result must be set to non-zero value.

2.      CheckRemoteDebuggerPresent

This check may be faked in many ways, via plugins (ScyllaHide, OllyAdvanced) or manually. Either way, in order to continue malware debugging, result of this function must be set to 0.

3.      CloseHandle

Consider this code sample:

This code is executed differently depending on whether debugger is present or not. Malware uses this method to check if debugger was detected: it checks if exception handler was executed and that 1 was returned from it. If all the conditions fulfill, malware terminates its execution.

When exception handler returns 1 –  which corresponds to EXCEPTION_EXECUTE_HANDLER – it is a sign that exception has been handled, as described here:
https://docs.microsoft.com/en-us/cpp/cpp/try-except-statement?view=vs-2019

To bypass this check method we have to set return value from exception handler to 0:

Anti-analysis tricks (dynamic)

1.      API bombing

Malware pollutes the API call analysis with a lot of non-meaningful calls:

This is done 28878 times:

This is also true for meaningful operations where the same actions are performed several times to make the log larger:

2.      Checking for installed anti-virus solutions

Malware terminates its execution if successfully loads one of the following DLLs:

  • taleOfTheWorstOne.dll
  • ActaRes.dll
  • SavUIRes.dll

`ActaRes.dll` and `SavUIRes.dll` are both libraries from Symantec Endpoint Protection.

Our guess about `taleOfTheWorstOne.dll` is that this library was used as a kill-switch during malware development.

Anti-analysis tricks (static)

1.      String obfuscation

All the key strings are obfuscated with the help of one of the following instructions:

  • xor
  • sub
  • div
  • not

They are put on stack before decryption. It looks like this:

2.      Dynamic function calling

When calling a function, malware first decrypts names of function and corresponding DLL. Then it refers to GetProcAddress wrapper and makes the call afterwards. It looks like this (decryption is not shown here):

 

3.      Jumps in the middle of instructions

This method was described by the author of Predator in Telegram channel with source code residing on GitHub:
https://github.com/Alexuiop1337/AntiDisassembly

Below we will show how to bypass it during research.

Consider this code in debugger:

Jump is taken in any case and leads to the middle of instruction. The following code is the right one:

Here is the code representation in IDA:

Outlined in red are fake instructions. When attempting to create a function in IDA for this case, an error is shown stating that wrong instructions are encountered.

Replacing the fake function call with NOP is the way to go in such a case so that the function will be created indeed:

Evasion techniques

These checks are performed only if corresponding command is received from the server.

1. Global Table Descriptor check

This trick involves looking at the pointers to critical operating system tables that are typically relocated on a virtual machine. It’s what called “Red Pill” and was first introduced by Joanna Rutkowska:

http://web.archive.org/web/20070325211649/http://www.invisiblethings.org/papers/redpill.html

There is one Local Descriptor Table Register (LDTR), one Global Descriptor Table Register (GDTR), and one Interrupt Descriptor Table Register (IDTR) per CPU. They have to be moved to a different location when a guest operating system is running to avoid conflicts with the host.

On real machines, for example, the IDT is located lower in memory than it is on guest (i.e., virtual) machines.

Note: does not work on newer versions of VMWare Workstation (tested in v10 and v12).

Three instructions are used to check locations of these tables:

  • sidt
  • sldt (not used by malware)
  • sgdt

Predator the Thief uses only two of them: sidt and sgdt.

Code sample:

idt_vm_detect = ((get_idt_base() >> 24) == 0xff);
ldt_vm_detect = (get_ldt_base() == 0xdead0000);
gdt_vm_detect = ((get_gdt_base >> 24) == 0xff);


// sidt instruction stores the contents of the IDT Register (the IDTR which points to the IDT) in a processor register.
ULONG get_idt_base() {
    UCHAR idtr[6];
#if defined (ENV32BIT)
    _asm sidt idtr;
#endif

    return *((unsigned long *)&idtr[2]);
}

// sldt instruction stores the contents of the LDT Register (the LDTR which points to the LDT) in a processor register.
ULONG get_ldt_base() {
    UCHAR ldtr[5] = "\xef\xbe\xad\xde";
#if defined (ENV32BIT)
    _asm sldt ldtr;
#endif
    return *((unsigned long *)&ldtr[0]);
}

// sgdt instruction stores the contents of the GDT Register (the GDTR which points to the GDT) in a processor register.
ULONG get_gdt_base() {
    UCHAR gdtr[6];
#if defined (ENV32BIT)
    _asm sgdt gdtr;
#endif
    return gdt = *((unsigned long *)&gdtr[2]);
}

2. CPU specific

This technique uses `cpuid` instruction to check if malware is run in VM. EAX is set to 1, ECX is set to 0, then `cpuid` instruction is called. If run in VM, 31st bit in ECX is set to 1. Malware checks exactly this bit.

3. Reading status register

This technique uses the smsw instruction which is described in the Intel Software developer’s manual:

Store machine status word in low-order 16 bits of r32/m16; high-order 16 bits of r32 are undefined.

The key here is the undefined high order bits. It has previously been observed that on Intel processors the return value of top 16 bits is consistently 0x8001, while on a virtualized CPU in VMware the target register contains the value preserved before the instruction was executed.

When using this technique, first the target register is initialized with a “magic” value, then smsw is executed. If after execution the target register still contains the “magic” value, the application is treated as if it’s running inside a virtual machine.

This technique doesn’t work in VMware workstation 12.

Network

Predator the Thief initiates two connections to the hardcoded C2C address. First it sends a warm welcome gets configuration file, then it sends stolen data in ZIP archive.

1st step

Config arrives in a classic Base64+RC4 encryption layer:

Please find the decryption script in the `Attachments ` section.

The following five configuration entries are stored in encrypted form:

1 – settings for stealing in this order (for Boolean value: 1 – feature is on; 0 – feature is off):

1 Take webcam snapshot (-3f4)
2 Check VM (-3f3)
3 Steal Skype
4 Steal Steam (-3f1)
5 Take screenshot (-3f0)
6 No log if CIS (-3e8)
7 Self-delete (-3e7)
8 Steal Telegram (-3e6)
9 Steal Windows cookies
10 Max quantity of stolen items

2 – directories where to steal files from and appropriate file masks

3 – host location info

4 – empty field. According to what we have seen on current site, it’s a place for loader module.

5 – contact server for an additional module (in this case: HTTP POST /api/clipper.get). Clipper is a module for grabbing additional crypto-wallets with custom settings.

Note: self-deletion is performed with the help of batch command “/c ping 127.0.0.1 && del [filename]”.

Example of these values is listed below:

Logical part Value
1 [0;0;0;0;1;0;1;0;0;1000]
2 [[%userprofile%\Desktop|%userprofile%\Downloads|%userprofile%\Documents;*.txt,*.png,*.jpg,*.jpeg,;1000;;1]]
3 [Montreal;Canada;45.5029;-73.5723;54.39.186.180;America/Toronto;H4]
4 []
5 [Clipper]

 

2nd step

At this step stolen data is sent to C2C server in ZIP archive:

“p” parameters in the request indicate how many items of certain have been stolen, in this example:

p1=0 & p2=243 & p3=0 & p4=0 & p5=0 & p6=0 & p7=0 & p8=0 & p9=0

And the same information in `Information.txt` file:

Check `What it is targeting` section for what is stored in the archive.

After sending the archive malware terminates its execution.

Updates

Predator is actively evolving; here are the descriptions of changes in versions 3.3.1 and 3.3.2 taken from its official Telegram channel:

* screenshot from changes in version 3.3.1

Predator the Thief update v.3.3.1

Comeback of onion domains

Now build can send data to onion domains so that chance of your server ban is really low.

* build sends info directly without using proxies and the like

** there is no guarantee for the same receive rate as for usual domain. Rate may be lower for onion domain

*** admin panel in TOR doesn’t eliminate chance of server ban but minimizes it to zero

Panel update

  • “not checked” filter was added for displaying all non-verified logs
  • fixed display of statistics of loader and OS
  • fixed display of certain elements in clipper module

Module update: loader

  • added possibility to check if the file has been already launched not to execute it twice

Module update: stealer

  • file grabber was optimized and works with logs up to 100MB
  • screenshot of all the PC monitors is taken
  • enhanced information gathering about PC installed applications
  • changed HWID format (general view is now X..X-X..X-X..X-…)
  • file with information now contains BIOS info as well
  • added possibility to steal Masked Credit Cards and Unmasked Credit Cards (displayed right where all the other CC are)
  • build is cleaned from the most popular anti-virus solutions

Changes in project terms

  • Seller has a right to deny services if you spread builder without crypt. If you clean build is on VT, you will be denied license. The whole responsibility for your build lies solely on you so it’s strongly advised to buy only good crypt from trusted sellers.
  • Now support is granted not for a lifetime but for half a year only (6 months from the moment of buying). All the previous clients are granted half a year support (6 months) from this day.
  • We remind that license is given for one account (telegram or jabber) from where paying was made. If you hadn’t warned that you were going to delete this account and create a new one, in case if you want to restore the license, it would be impossible.

Screenshot with changes in version 3.3.2 follows:

Predator the Thief update v.3.3.2

Stealer update

  • There is a possibility to execute PowerShell script after stealer sends the log. Script should be in base64 form
  • Now file grabber works with links (LNK files)
  • “Exceptions” if grabber are now applied for folder names
  • Added auto-generator of User-Agent, this information will be written to file “Software.txt” (check it before usage, automatic algorithm is not always the best possible solution)
  • Fixed countries for loader
  • Other minor fixes

Previous researches

First publicly known research was conducted by fumik0_:
https://fumik0.com/2018/10/15/predator-the-thief-in-depth-analysis-v2-3-5/

It was v.2.3.5, year 2018. fumik0_ has also covered v.2.3.7.

Since then Predator has evolved and different versions were covered by more researches:
https://securelist.com/a-predatory-tale/89779/
https://www.fortinet.com/blog/threat-research/predator-the-thief-new-routes-delivery.html

Differences in modern samples

There are quite a few differences between current sample (v.3.3.0) and the ones researched previously.  We will list them as bullet points:

  • Anti-debug techniques are very peculiar and not covered in any of previous researches
  • Anti-analysis methods are described partly

Mutex name generation algorithm has completely changed

Conclusion

Though not among the most prevalent malware’s nowadays, Predator the Thief has all the possibilities to become one of them.
The level of dedication that the author puts into his creation promises even more danger from this stealer in the future. Regular updates, evasions, anti-debug techniques, its capabilities, the fact that it can be easily used by thread actors without a lot of technical knowledge – all of these points make Predator a rising star player on malware stealer market, the one that should be definitely reckoned with.

 

IOCs

Hashes

MD5 SHA1
3cb386716d7b90b4dca1610afbd5b146 6e7c5d252c3836eff17a3ad9bf69b8d4be4b81a1
cbcc48fe0fa0fd30cb4c088fae582118 b1114fe6add1b570d16822a80678a0c7bef91795
c44920c419a21e07d753ed607fb6d7ca 28dd84fd59868bf2bacfa49d7c5aa29cd1558e61
cf2273b943edd0752a09e90f45958c85 7df2f80abd86898c9befe482ce558541fa5d4efb
b2cbb3d80c8d830a3b3c2bd568ba1826 c8f3171868b065dcb3af82c9813a35cefa6928e6
dff67a78bb4866f9da5a0c1781ed5348 7d9aa5ca823cd77430063a1f92b737722ee0f05a
25f9ec882eac441d4852f92e0eab8595 3753d1c51cf9612f50817165bbbdca5951e736fd
052ef78b897f555cd79805544e59746e 7c69ca83d9f5a206326562fdf190e444269d2485
b380e0abd3c9515a23cc0ed5a25bd4b9 e7bfd515ac0a0df4e80b43485b0b91ed62e63349

 

Domains

Domain
kent-adam.myjino[.]ru
denbaliberdin.myjino[.]ru
15charliescene15.myjino[.]ru
axixaxaxu1337[.]us
madoko.jhfree[.]net
kristihack46.myjino[.]ru
j946104.myjino[.]ru
sayhello[.]host
u96191l2.beget[.]tech
www.haijiangfriut[.]com
btcinvest[.]company

 

Attachments

Python mutex name generation algorithm

import struct
import win32api

disk_num = 0
res = win32api.GetVolumeInformation(‘c:\\’)
if len(res) != 5:
    print ‘Something went wrong with API function’
    raise Exception
disk_num = res[1]
print ‘Volume serial number (hex): %#08x’ % struct.unpack(‘<I’, struct.pack(‘<i’, disk_num))[0]
init_value = (disk_num * 5) & 0xFFFFFFFF
print ‘Initial value (dec): %d’ % init_value
init_string = str(init_value)
transformed_string = init_string + init_string[2:]
print ‘String value: %s’ % transformed_string
mutex_name = ”
for i in range(0, len(transformed_string)):
    mutex_name += transformed_string[i] if i % 2 == 1 else chr(ord(transformed_string[i]) + 0x40)
print ‘Mutex name: %s’ % mutex_name