Following the Scent of TrickGate: 6-Year-Old Packer Used to Deploy the Most Wanted Malware

January 30, 2023

Research by: Arie Olshtein

Executive summary

  • Initially observed in July 2016, TrickGate is a shellcode-based packer offered as a service to hide malware from EDRs and antivirus programs.
  • Over the last 6 years, TrickGate was used to deploy the top members of the “Most Wanted Malware” list, such as Cerber, Trickbot, Maze, Emotet, REvil, Cobalt Strike, AZORult, Formbook, AgentTesla and more.
  • TrickGate managed to stay under the radar for years because it is transformative – it undergoes changes periodically. This characteristic caused the research community to identify it by numerous attributes and names.
  • While the packer’s wrapper changed over time, the main building blocks within TrickGate shellcode are still in use today.
  • Check Point Threat Emulation successfully detects and blocks the TrickGate packer.


Cyber criminals increasingly rely on packers to carry out their malicious activities. The packer, also referred to as “Crypter” and “FUD” on hacking forums, makes it harder for antivirus programs to detect the malicious code. By using a packer, malicious actors can spread their malware more easily with fewer repercussions. One of the main characteristics of a commercial Packer-as-a-Service is that it doesn’t matter what the payload is, which means it can be used to pack many different malicious samples. Another important characteristic of the packer is that it is transformative – the packer’s wrapper is changed on a regular basis which enables it to remain invisible to security products.

TrickGate is a good example of a strong, resilient Packer-as-a-Service, which has managed to stay under the cyber security radar for many years and continually improve itself in different ways. We managed to track TrickGate’s breadcrumb trail despite its propensity for rapidly changing its outer wrapper.

Although a lot of excellent research was conducted on the packer itself, TrickGate is a master of disguises and has been given many names based on its varied attributes. Its names include “TrickGate”, “Emotet’s packer”, “new loader”, “Loncom”, “NSIS-based crypter” and more. We connect the dots from previous researches and with high confidence point to a single operation that seems to be offered as a service.

TrickGate over the years.

We first observed TrickGate at the end of 2016. Back then, it was used to deliver Cerber ransomware. Since that time, we are continually observing TrickGate and found it is used to spread all types of malwares tools, such as ransomware, RATs, info-stealers, bankers, and miners. We noticed that many APT groups and threat actors regularly use TrickGate to wrap their malicious code to prevent detection by security products. TrickGate has been involved in wrapping some of the best-known top-distribution malware families, such as Cerber, Trickbot, Maze, Emotet, REvil, CoinMiner, Cobalt Strike, DarkVNC, BuerLoader, HawkEye, NetWire, AZORult, Formbook, Remcos, Lokibot, AgentTesla, and many more.

Figure 1 – TrickGate over the years.

TrickGate Distribution.

We monitored between 40 to 650 attacks per week during the last 2 years. According to our telemetry, the threat actors who use TrickGate primarily target the manufacturing sector, but also attack education facilities, healthcare, finance and business enterprises. The attacks are distributed all over the world, with an increased concentration in Taiwan and Turkey. The most popular malware family used in the last 2 months is Formbook with 42% of the total tracked distribution.

Figure 2 – TrickGate statistics during Oct-Nov 2022.

Attack flow:

Following is an overview of the attack flow that is commonly found in attacks involving TrickGate.

Initial Access

The initial access made by the packer’s users can vary significantly. We monitor the packed samples spreading mainly via phishing emails with malicious attachments, but also via malicious links.

Initial Files

The first stage mainly comes in the form of an archived executable, but we monitored many file types and delivery permutations that lead to the same shellcode. We observed the following file types at the first stage:

Archive: 7Z * ACE * ARJ * BZ * BZ2 * CAB * GZ * IMG * ISO * IZH * LHA * LZ * LZH * R00 * RAR * TAR * TGZ * UU * UUE * XZ * Z * ZIP * ZIPX * ZST.

Executable: BAT * CMD * COM * EXE * LNK * PIF * SCR.

Document: DOC * DOCX * PDF * XLL * XLS * XLSX * RTF.

Shellcode Loader

The second stage is the shellcode loader which is responsible for decrypting and running the shellcode.

We noticed 3 different types of code language used for the shellcode loader. NSIS script, AutoIT script and C all implement similar functionality.


The shellcode is the core of the packer. It’s responsible for decrypting the payload and stealthily injecting it into a new process.


The payload is the actual malicious code and is responsible for carrying out the intended malicious activity. The payloads differ according to the actor who used the packer.

Figure 3 – Attack flow.

Examples of the different attack flows we observed in the past year:

FEB 24, 2022

Figure 4 – LNK flow

RAR: 3f5758da2f4469810958714faed747b2309142ae

LNK: bba7c7e6b4cb113b8f8652d67ce3592901b18a74

URL: jardinaix[.]fr/w.exe

EXE 63205c7b5c84296478f1ad7d335aa06b8b7da536 

Mar 10, 2022

Figure 5 – PDF flow.

PDF: 08a9cf364796b483327fb76335f166fe4bf7c581

XLSX: 36b7140f0b5673d03c059a35c10e96e0ef3d429a

URL: 192.227.196[.]211/t.wirr/XLD.exe

EXE:  386e4686dd27b82e4cabca7a099fef08b000de81 

Oct 3, 2022

Figure 6 – SFX flow.

7Z: fac7a9d4c7d74eea7ed87d2ac5fedad08cf1d50a

EXE: 3437ea9b7592a4a05077028d54ef8ad194b45d2f 

Nov 15, 2022

Figure 7 – AutoIT flow.

R11: 755ee43ae80421c80abfab5481d44615784e76da

EXE: 666c5b23521c1491adeeee26716a1794b09080ec

Shellcode loader

The Shellcode loader usually contains a single function which is responsible for decrypting and loading the shellcode into memory. These are the basic steps:

  1. Read the encrypted shellcode. The encrypted shellcode can be stored in a file on the disc, in the “.rdata” section or as a resource.
  2. Allocate memory for the shellcode, usually by calling VirtualAlloc.
  3. Decrypt the shellcode.
  4. Trigger the shellcode. As we explain below, this can be done using a direct call or by callback functions.

Figure 8 – Shellcode loader – deobfuscated AutoIT version.

Figure 9 – Shellcode loader C version.

In the more recent versions of TrickGate, the shellcode loader abuses the “Callback Functions” mechanism. The loader utilizes many native API calls which take a memory address as an argument of a callback function. Instead of the Callback Function, the loader passes on the address of the newly allocated memory which holds the shellcode.  When Windows reaches the point of the registered events, the DriverCallback executes the shellcode. This technique breaks the flow of the behavior we’re monitoring by having Windows OS run the shellcode at an unknown time. In the shellcode loader above, you can see two examples of this in the images “EnumTimeFormatsA” and “EnumSystemCodePagesW”. 

Shellcode similarity and TrickGate vacation

Usually, when we find code similarity between unrelated malware families, it is more likely that the actors copied from a mutual resource or shared some pieces of code. For a long time, we noticed a unique injection technique that incorporated the use of direct kernel syscalls, but we didn’t realize the significance, thinking it was probably a fragment of shared code.  What caused us to suspect that this unique injection may be controlled solely by one actor is the fact that we saw an occasional “time-off” in operation, and it is very unlikely that several different groups will take a break at exactly the same time. The last break, which was more than 3 months long (from June 13, 2022 to September 26, 2022) was an opportunity for us to verify our suspicion, and dive into the shellcode.

Figure 10 – TrickGate in the last 2 years.

To verify our suspicion, we started to analyze samples across the timeline.

We started our analysis by comparing a fresh sample to an older one. For this test we used

2022-12_Remcos: a1f73365b88872de170e69ed2150c6df7adcdc9c

compared to

2017-10_CoinMiner: 1a455baf4ce680d74af964ea6f5253bbeeacb3de

We know from the behavioral analysis that a similarity exists in the shellcode, so we ran the samples till the point the shellcode is decrypted in memory and then we dumped the shellcode to the disk. Next, we used the Zynamics BinDiff tool (owned by Google) to check similarities in both shellcodes. The results showed a 50% similarity between the tested shellcodes. Fifty percent over a long period of time – more than five years – for quite a large piece of shellcode (~5kb) is unexpected. This automatically raised suspicions that this might be a maintained shellcode, but we needed further evidence in the form of similarity analysis over shorter periods of times to see if it had changed gradually.

Figure 11 – BinDiff result on shellcode extracted 2022-12_Remcos: a1f73365b88872de170e69ed2150c6df7adcdc9c VS 2017-10_CoinMiner: 1a455baf4ce680d74af964ea6f5253bbeeacb3de.

For further analysis, we took random samples from the past 6 years. For each sample, we dumped the shellcode and checked the similarity of the result over time. As you can see in the following graph, the results point to small changes made over time. On the left side we see samples dating from 2016 till 2020 showing about 90% similarity. On the right side, we see a forked version showing a high similarity within itself, but lower similarity with the original version on the left.

Figure 12 – Bindiff result on extracted shellcodes.

We then dived into the gap between the shellcodes to see the impact caused by:

  • Different compilers
  • Obfuscations
  • Evasion modules
  • Persistence modules (run the packet payload at the next login)
  • Function order
  • Local variables vs structures

After we cleaned the gap noise, we got the core functionality of the packer. The author constantly maintained the shellcode but used “building blocks” as described in the next section.

Figure 13 – Control flow graph – on the main injection function. Diffing 2016-07_ Cerber: 24aa45280c7821e0c9e404f6ce846f1ce00b9823 VS 2022-12_Remcos: a1f73365b88872de170e69ed2150c6df7adcdc9c

Figure 14 – Diffing kernel direct call of NtWriteVirtualMemory 2022-12_Remcos: a1f73365b88872de170e69ed2150c6df7adcdc9c VS 2016-07_ Cerber:  24aa45280c7821e0c9e404f6ce846f1ce00b9823

TrickGate shellcode’s construction elements

As mentioned above, the shellcode has been constantly updated, but the main functionalities exist on all the samples since 2016. An overview of the shellcode’s building-blocks can be described as follows:

  • API hash resolving.
  • Load to memory and decrypt the payload.
  • Injection using direct kernel calls.
    • Manually map a fresh copy of ntdll.
    • Dynamically retrieve the kernel syscall numbers.
    • Invoke the desired syscalls.
    • Inject and run the payload.

API hash resolving.

When we analyzed the TrickGate code, no constant strings can be found. Many times, TrickGate intentionally adds clean code and debug strings to throw off any analysis. To hide the needed strings and its intentions, TrickGate uses a common technique called API hashing, in which all the needed Windows APIs are hidden with a hash number. Until January 2021, TrickGate used to hash the shellcode string with CRC32. In the newer version, TrickGate started using a custom hash function.

The equivalent Python hashing functions used in the last 2 years:

def hash_str_ror1(str):
    h = 8998
    for c in str:
        h += ord(c) + (((h >> 1) &amp; 0xffffffff) | ((h << 7) & 0xffffffff))
    return h & 0xffffffff
def hash_str21(str):
    h = 8998
    for c in str:
        h = ord(c) + (0x21 * h)
    return h & 0xffffffff

The following Kernel32 API names have been hashed in TrickGate samples:

API NAMECRC32hash_str_ror1hash_str21

Figure 15 – API hashing.

Load to memory and decrypt the payload.

TrickGate always changes the way the payload is decrypted, so unpacking solutions that we observe now will not work on the next update. Most of the samples use a custom decryption method but on older samples we also saw known cyphers such as RC4 implementation or the use of Windows APIs for encryption.

Injection using direct kernel calls:

After decrypting the payload, the shellcode then injects it into a newly created process. After the process is created using the create_suspended flag, the injection is done by a set of direct calls to the kernel. For every one of these ntdll API calls:  

  • NtCreateSection
  • NtMapViewOfSection
  • NtUnmapViewOfSection
  • NtWriteVirtualMemory
  • NtResumeThread

The following actions are executed:

  • Manually map a fresh copy of ntdll from the disk.
  • Resolve the address of a given hash in the newly mapped ntdll.
  • Dynamically extract the requested System Service Number (SSN).
  • Direct kernel Invoke with the SSN.
    • For Windows 64-bit: Switch to 64-bit mode using “Heaven’s Gate” technique and SYSCALL SSN
    • For Windows 32-bit: Call SYSENTER SSN

Figure 16 – Function call graph SYSCALL ID from Manually mapped DLL.

The way TrickGate invokes direct-syscalls is intriguing, as it uses a technique similar to Hell’s Gate. Hell’s Gate is a technique presented publicly in 2020 as a way to dynamically retrieve and execute direct syscall numbers. Here you can find samples dating to 2016 which manage to accomplish the equivalent action to retrieve and execute direct system calls without the need to maintain a System Service Descriptor Table (SSDT).

Figure 17 – SSN dynamically extracted 2016-07_Cerber:  24aa45280c7821e0c9e404f6ce846f1ce00b9823

The injection module has been the most consistent part over the years and has been observed in all TrickGate shellcodes since 2016.


We created strings correlating the most wanted malware in the last 6 years to a single Packer-as-a-Service named TrickGate, whose transformative abilities make it hard to identify and track. Understanding the packer’s building blocks is of crucial importance to detect the threat, as blocking the packer will protect against the threat in an early stage, before the payload starts to run.

Packers often get less attention, as researchers tend to focus their attention on the actual malware, leaving the packer stub untouched. However, the identified packer can now be used as a focal point to detect new or unknown malware.

Analyzed samples.

























  • Check Point Research Publications
  • Global Cyber Attack Reports
  • Threat Research
February 17, 2020

“The Turkish Rat” Evolved Adwind in a Massive Ongoing Phishing Campaign

  • Check Point Research Publications
August 11, 2017

“The Next WannaCry” Vulnerability is Here

  • Check Point Research Publications
January 11, 2018

‘RubyMiner’ Cryptominer Affects 30% of WW Networks