Yearly Archives

6 Articles

Buer Loader, new Russian loader on the market with interesting persistence

Posted on

In the middle of November, a friend told me of a new malware being sold on Russian forums under the name “Buer Loader”. A translated copy of the thread where it is advertised can be found here. A google search revealed no one having mentioned “Buer Loader” before, nor provided an analysis of it. However, a forum administrator had already provided an analysis of the malware, in which the following screenshot of strings was provided.

With this, we can now hunt for Buer Loader samples. Based on the strings, a variety of samples that drop Buer Loader or is Buer Loader were found. Their hashes are listed below:

ddc4d9fa604cce434ba131b197f20e5a25deb4952e6365a33ac8d380ab543089 fcdf29266f3508bd91d2446f20a73a811f53e27ad1f3e9c1f822458f1f30b5c9

MalwareHunterTeam also found a sample, though he did not refer to it by name. Strings for the file was posted by James_inthe_box.

A large number of samples, such as 0dd7e132fb5e9dd241ae103110d085bc4d1ef7396ca6c84a3b91dc44f3aff50f which was spotted on November 12th multiple times, are packed with Themida. We thankfully found one that wasn’t, with the hash of 6c694df8bde06ffebb8a259bebbae8d123effd58c9dd86564f7f70307443ccd0.

The file in question is a VB6 file, and can be found on Hybrid-Analysis.

After starting, the process executes a shellcode that is stored on the heap. Due to the process not having DEP enabled, the shellcode runs fine.

The shellcode does a typical process hollowing. The original image is unmapped below.

Next NtWriteVirtualMemory is called using DllCallFunction to write the malicious payload.

Dumping it from memory and trimming the overlay, we have a 27kb executable file that appears to be compiled with Visual Studio 2017. This would seem to be our original Buer Loader file. The TimeDateStamp indicates that it was compiled on Thu, 29 Aug 2019 05:48:03 UTC.

The file starts out with checking for debugger by reading PEB->BeingDebugged. If this check is passed, it checks for virtualization, and then enter the real code.

Here, the code uses sidt/sgdt to detect the presence of virtualization. More details on that can be found here.

The bot then enters the “real” main function.

Here, APIs are resolved and strings are decrypted. String decryption is done in a slightly peculiar manner, rather than passing a string directly to the decryption function the pointer to the WORD before it is passed. The first WORD is then ignored, and the rest is decrypted. In order to facilitate easy IDA reference searches, I opted to create a simple struct so that both the call to decrypt and the reference to the strings are in one place.

Interestingly, IDA did not detect the prototype of decrypt_str (and several other functions) correctly, and ignored the parameter passed in ECX. When the file was originally loaded, the original prototype was “unsigned int __cdecl decrypt_str(int length)”. Changing it to “void __usercall decrypt_str(int length, strdec_header *encryptedStr)” is necessary for IDA to decompile the function and calls to it successfully.

I modified an IDAPython script for decrypting strings (a few strings will fail due to duplicates or unicode, but the vast majority works fine). The script can be found on GitLab.

APIs are resolved by hash. The hashing algorithm is the typical ror13 algorithm that is often used in shellcodes.

After resolving the APIs and decrypting strings, the file checks to see whether it is operating in CIS countries. This is mandated as a part of the rule of the forum where the malware operates.

After the check is passed, the file adds itself to startup using a peculiar method. It first gathers the command required to create a task that runs the bot every 2 minutes, and then add that command to the RunOnce key.

After this, it enters the main loop and attempts to ensure persistence. To prevent the file from being deleted (or opened), it performs an interesting technique of forcing open a handle to the file inside the context of Explorer.exe. First, it gets a handle to explorer indirectly by first getting a handle with PROCESS_DUP_HANDLE privilege, and then using DuplicateHandle to create a handle with PROCESS_ALL_ACCESS. Thus far I have not seen this trick in malware but rather only in the cheating scene, perhaps indicative of the author’s involvement in such areas.

After this, it creates a handle to it’s own file with dwSharing set to 0 (thus preventing any other process from accessing the file), and duplicates the handle into the explorer process.

A rather unique choice of persistence that I have not observed before. Interestingly, it would appear that this effectively blocks Hybrid Analysis from reading the file (despite their analysis operating primarily at ring 0), with reports not displaying the file icon. Possibly part of their analysis currently runs from usermode and as a result was blocked by this.

At this point in the analysis, I found out that ProofPoint published an analysis of the loader a few hours before. As such, I’ll refer to their description of the HTTP requests and focus instead on how commands are handled.

The command handling function is decompiled relatively unclean, due to it’s size and the amount of switches and conditions IDA did not do a terrific job, however the decompilation serves it’s purposes. A few things of note:

  • A lot of commands result in the process exiting, and as such SpawnInstanceOfSelf is called beforehand to create another instance of Buer before the command is executed. It is unclear why the loader could not perform the hollowing and continue execution.
  • my_string_compare is equivalent to lstrcmpW and returns 0 if the string matches.
  • Strings are duplicated a lot for unknown reasons.


Memload attempts a very basic process hollowing if the file successfully spawns another instance of itself. API callchain: CreateProcessW->GetThreadContext->ZwUnmapViewOfSection (optional)->VirtualAllocEx->WriteProcessMemory->NtQueryIformationProcess->SetThreadContext->ResumeThread->CloseHandle->ExitProcess.


Depending on the option set and whether it is running under WoW64 or not, LoadDllMem will either “inject” the DLL into itself (by using GetCurrentProcess/INVALID_HANDLE_VALUE as the handle) or repeat the trick of stealing explorer’s handle from itself. The injection is fairly standard, if 64 bit is set it will use heaven’s gate and it will use the normal API otherwise.

To initialize the DLL, a bootstrap shellcode is injected and called. A structure with pointers to the DLL and function pointers are passed to it.


The update mechanism of Buer Loader is relatively simple, and there is not much to say about it.

In conclusion, Buer is a new loader on the Russian malware scene and is relatively complex (especially when contrasted against certain bots such as Amadey). It still show inconsistencies that indicate a developer who is not experienced with low level development however, and it’s anti-analysis methods (such as API hashing or string encryption) are easily defeated with the use of IDAPython.

Taking a look at Baldr stealer

Posted on

MD5: a462c3b291b90b202c6d090881ba6134
File type: PE, Visual C++

Background information

Baldr is a relatively new stealer that became available on some forums early 2019. It was previously analyzed by MalwareBytes ( ). However since MB’s analysis did not include deobfuscation I will be including a deobfuscated version of the malware as well as an analysis of that, which will make things a lot clearer.

The packer

The packer relies on a shellcode which’s decryption begins at around 0x42F8D1 with the VirtualProtect call. Interestingly, a giant array (which is most likely the encrypted shellcode) is assembled on stack, which IDA refuses to decompile as the function is too big, and Ghidra freezes when decompilation is attempted.

The decryption call

It is regardless relatively simple to unpack, and is of the variant that uses a new section to store it’s data (from this point on I shall refer to all such variants as section crypter for the sake of simplicity). By setting a memory breakpoint on the last section and running the sample, we easily are able to find the decryption function and obtain the decrypted payload (which can alternatively be reached directly by setting a hardware breakpoint at 0042CC2E since the decryption function is inside a shellcode that is decrypted at runtime).

Baldr Stealer

After that, we are rewarded with the Baldr payload that customers are given by the developer: a PE file which loads the CLR runtime and then execute the final .NET payload. Instead of wasting time reverse engineering this, it was much more simple to use MegaDumper to obtain the payload. The MD5 of the CLR loader is 183E0610403FB07B88B809A26354CB2E, and the final payload is CAB810FFA40EC642FBCED82E07B9D593 (both available on VirusBay and VirusTotal).

The .NET payload is obfuscated with a modded variant of ConfuserEx with extra mutations. A deobfuscated file is included at the end of the article, which was cleaned by Wadu. The configuration for the file is as follow:

public static string gate_address = “”;
public static string baldr_version = “v3.0”;
    public static string baldr_name = “Baldr”;
    public static 64b30ed2 features = new 64b30ed2
        telegram_steal = true,
        autofill_steal = true,
        cards_steal = true,
        cookies_steal = true,
        execution_time = 0,
        ftp_steal = true,
        grabber_steal = true,
        history_steal = true,
        jabber_steal = true,
        passwords_steal = true,
        screenshot_grabber = true,
        self_delete = true,
        vpn_steal = true

The functions operate as follow:

Telegram Stealer

The telegram stealer operates by finding processes with the name “Telegram” and obtain the directory it is running from. It attempts to find the D877F783D5D3EF8C directory (the directory where Telegram stores it’s data) and steals the files D877F783D5D3EF8C\map0, D877F783D5D3EF8C\map1, D877F783D5D3EF8C0 and D877F783D5D3EF8C1.

Browsers Handler

Baldr obtains autofill information by reading moz_formhistory from Firefox’s formhistory.sqlite. In addition to this, it also recovers history by reading moz_places from places.sqlite and cookies from the table moz_cookies in cookies.sqlite. Passwords are recovered from logins.json. I’ll avoid going into the details of other browsers because anyone can google for 5 minutes and find out how browsers store data.

Screenshot grabber

The screenshot grabber (as most .NET screenshot grabbers do) creates a bitmap the size of the screen and then use Graphics.CopyFromScreen, which uses BitBlt underneath. As such, this function can be monitored to detect screengrabbing attempts (although it is likely that BitBlt is used by legitimate applications as well).

Then, the file is uploaded as screen.jpeg. Strangely enough, the string “screen.jpeg” is base64 encoded, seemingly for no reason.

FTP Stealer

The FTP Stealer retrieves recentservers.xml and sitemanager.xml for FileZilla and wcx_ftp.ini for GHISLER/Total Commander.

Jabber Stealer

The jabber steals the files “\\.purple\\accounts.xml” (Pidgin) and “\\Psi+\\profiles\\default\\accounts.xml” (Psi+) from the Application Data directory.

VPN Stealer

The VPN stealer is capable of stealing from ProtonVPN and NordVPN.

Sleep delay

The file sleeps for 1000 times the entry of this in milliseconds. Strangely enough, the author called this “ExectuionTime” [sic].

That’s about all that Baldr stealer has to offer, however if you notice something that I left out do leave a comment and I will add it to the article. The deobfuscated file’s hash is 22F1E14D938A1DBC8B501050D5CFAA55FF7B4FD9 and it can be found on VirusBay.

NtCrypt and 1DayCrypt and their similarities

Posted on

For reasons I will not be able to provide the specific samples discussed, which I hope will be understandable. So I guess you will have to take my word for the validity of the sample. But I am Mr. Krabs so of course you will take my word for the validity of it.

Some preliminary notes: NtCrypt is a “high end” crypter that was previously analyzed ish by malwarebytes. They never publicly ID-ed the crypter/packer but based on my analysis (and the authors’ own admission) it was NtCrypt. The author is also quite hated by some competitors (or ex-competitors I suppose)

Now that we know some basic information about NtCrypt, there is a new crypter which recently emerged on the script kiddy website Hackforums.

Very fascinating, aside from the imperfect English. A sample obtained was able to allow the confirmation that 1Day crypt is in fact a NtCrypt clone.

Similarity #1: Wrapper

Both NtCrypt and 1Day Crypt relies on stolen projects from Github or other sites as the “vehicle” through which their shellcode is executed. These projects are then used for

Similarity #2: Shellcode delivery

The shellcode resides in the .data section and are encrypted in both cases. They are then decrypted using a xor based algorithm. This differs slightly between the two: the decryption algorithm for 1Day is slightly modified and is obfuscated with jmps over junk bytes (as an anti-disassembly technique). The shellcode is then executed by being passed as a callback to Enum* functions, which in the case of NtCrypt was EnumDesktopsA and 1Day was EnumWindows.

1Day Crypt

These changes are very much understandable, as NtCrypt was released some months ago whereas 1Day Crypt is a very new service. An interesting and unique thing is that in both cases the entrypoint of the shellcode is NOT it’s starting address: EnumFunc is at the offset 5880 in 1Day and 3B40 in NtCrypt. After this, we get to

Similarity #3: Hashing

Both uses a hashing algorithm that looks something like this:

int __cdecl custom_hash_str(unsigned __int8* a1)
  int v2;             // [esp+0h] [ebp-8h]
  unsigned __int8 v3; // [esp+7h] [ebp-1h]

  v2 = 0x1505;
  if (!a1)
    return 0;
  while (1) {
    v3 = *a1++;
    if (!v3)
    v2 = v3 + 33 * v2;
  return v2;

This is then used for

Similarity #4: API resolving

1Day Crypt
NtCrypt. I did not apply the struct so looks a bit different but it is in essence 100% similar

This function resolves API belonging to user32 and gdi dll, and is used for the

Similarity #5: Bitdefender bypass

Both crypters’ entrypoint are practically 100% the same.

1Day Crypt

They both detect Bitdefender’s API through the hash and passes the current executing address to a bitdefender bypass function. The function creates an invisible window called “Tricked” which bypasses a Bitdefender detection where windowless EXEs are sometimes flagged.

The bypass, partially cleaned up

This is why the entrypoint required an E8 00 00 00 00 (which those familiar with shellcode and exploit development will recognize as call $+5) for the purpose of obtaining the EIP and address of the shellcode. This is then used to calculate the offset of a callback function, which is then created using the CreateThread API.

Similarity #6: Storage

One very very unique thing about both crypter is that they are heavily invested in heuristics bypass, which results in them both using some rather innovative techniques that were not seen before. NtCrypt previously stored data in a section called “.arch” which is set to be the Architecture Directory in the PE header.

1Day Crypt on the other hand sets it to the debug directory, with a not-so-nice name.

As expected, the debug directory would be corrupted. However as normal execution does not rely on this directory, the file would not have any problem executing.

Conclusions and some remarks

I’ll avoid going into details about code execution as their injection method is already covered by MalwareBytes (although with some minor mistakes) and anyone can figure out how a PE Loader works by reading MSDN documentation and looking at ReactOS or other resources. It is very fascinating to observe the tendency of monopolization of capitalism happen even on illegal marketplaces for crypters like this, with a crypter developer selling his software under multiple brands to obtain more customers. As not much has changed, reverse engineers who are reasonably experienced will be able to easily tell that the crypter is developed by the same person.


As it turns out, the new 1Day Crypt was some person buying NtCrypt and reselling without permission at a price lower than the original. This is quite strange, however it would mean that their “private stubs” are not really “private” at all, and that they are scamming their customers through this scheme.

Some interesting notes on Revcode

Posted on

Revcode’s author(s) tried to threaten me into taking my article down again. As a result, I did a little bit of digging and I found something particularly interesting. Let’s take a look at their website, most notably the “About and Contact” section.

Here, a VAT number was provided: SE900511095301. Now if we look this up on some VAT search sites, a name is obtained:

Alex Yucel, hmmm. Does this not sound familiar? Oh right, it was one of the Blackshades people.

How fascinating! A Blackshades developer returning and selling malware under the guise of legality? One would think that being in prison for a bit would’ve taught him a lesson. I suppose the 350k he and his “friends” made convinced him otherwise. Another interesting note: they have now added the C++ client. However, what is most strange is that the C++ client does not support Windows XP apparently. Sheer incompetence or what? Who knows, only time will tell.

Analyzing Amadey – a simple native malware

Posted on

Apparently there is a new Russian botnet floating around by the name of Amadey. Despite the very high price tag on Russian forums, it is a very simplistic bot that is quite honestly poorly made.

SHA-1: B7235E2981456D29412AD935BDBCA140B6AD0151

Compiler info (from ExeInfo PE): Microsoft Visual C++ ver 5.0/6.0

Sample given by a friend.

The payload was not spreaded directly but rather was packed with a crypter. The crypter seems to be TitanCrypt, based on the storage method (appended section which contains the payload which was encrypted and then base64 encoded). The crypter’s code is encrypted using a self-decryptor as well as heavily obfuscated, and is executed by using windows API callbacks.

The code being passed as a callback function

The code is put into a layer of self decryption loop, after which we jump into a very obfuscated region of code. After some (and by some I mean a lot) of manual analysis, the important code where the payload is decrypted is identified.

The decryption call:

The code decryption call
After the call

Stepping over the call, we see the region decrypted rather clearly. Dumping this, we get the actual payload.

SHA1: 3E4CD703DEEF2CFD1726095987766E2F062E9C57

Compiler info: FreeBASIC Compiler v0.14 – 0.17

The malware in question is “Amadey”, a new bot that is sold on a Russian forum. Link to thread content in Russian. It goes for $600 for a license, and for the high price cap the author is extra nice in his customer service – he delivered the symbols for us within the binary, allowing reverse engineers to inspect it with great ease : )

Main function
UAC bypass just runs self as admin…
Terrible permission check by creating a file in a privileged folder

Startup is added by executing the command “REG ADD “HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders” /f /v Startup /t REG_SZ /d path_to_folder_containing_the_file”

The bot is not too interesting, it is in fact very simplistic. I would write more about the bot but…there is nothing else to write about. The programmer was nice enough to ship the file with symbols for us, making things a lot easier and in the process of doing so defeated the point of him encrypting strings. All files are available on virustotal and virusbay as usual.

Brief overview and analysis of Static Crypt

Posted on

I’m back, it’s been a while. Static Crypt, a malware crypter is using a C based stub now apparently so I am doing an analysis of it. For context, it has been running for a few years and in the past it was using an AutoIt wrapper which executed a C shellcode. The shellcode has significantly changed since then, and the wrapper is now in C.

SHA256: 0c03cdba0c37a8daa031ec997306ae86f25e4d92f6551bebbbacec03288e788b

File Type: MSVC++ PE32 executable.

First thing we notice is there are not-so-legitimate looking resource entries. Considering there are no off-looking sections we can probably assume that the payload and configuration are stored in resource.

The stub uses copy pasted code from github as junk:

Parts of the disassembled code

It seems that more and more packer are adopting this “technique”. It was also seen in other higher-priced packers like NtCrypt and TitanCrypt.

Setting a breakpoint on kernel32.VirtualProtect and running once, the resulting stack is most interesting. As we can see the third parameter is 0x40, which is PAGE_EXECUTE_READWRITE.

Following 01557450 we can see this confirmed.

Further analysis shows that this is mostly a ripoff of the open source crypter that was released by Luminos months ago. First of all, the jmp-to-entrypoint technique is one that Luminos suggested, as to quote his readme file, “the shellcode needs a JMP instruction added at the top, so it jumps to the entrypoint of it, E9 <32bit little endian>”. Second, we have small push/call/call/ret blocks littered throughout the code.

This is one of the most revealing things about how it is a paste of Luminos’s release: 155B6D5 is equivalent to get_syscall_number and 15578C5 is equivalent to KiFastSystemCall. The disassembly of both confirms this:

155B6D5 disassembly
get_syscall_number code, notably with the same array for the ntdll string

Breaking on the entrypoint of the shellcode, we see the same resource names in the first image passed in as parameters. The first call to shellcode+05after the string “initializers” was load_api(), which searched for APIs using hashed name and saved them to an array.

The next 2 calls (I restarted the debugger so the address is now different) to 8E9F05 (or shellcode+2AA5) retrieves the resources that were passed into the shellcode. The second resource is subsequently decrypted in 2 calls a while after that, the first of which obtains the length of the decryption key, and the second perform xor decryption.

After the second call, we get a PE header as expected:

The final call in the function takes in the APIs structure (which contains the address of the APIs resolved by load_apis()) and then executes the actual payload through runpe. The runpe used is copy pasted verbatim from Luminos’s code, as shown by the first few instructions:

The code it corresponds to

As it is a practically exact copy paste, it faces the same many problems that Luminos’s packer had, which I will not detail as I would rather not help the crypter developer fix it. In short, the runpe creates a new process, uses NtCreateSection and NtMapViewOfSection to map the new payload to the process, and then uses SetThreadContext/GetThreadContext and ResumeThread to execute the payload.

Static Crypt also apparently has a rather “sophisticated” startup mechanism, however the file I received did not have such enabled. The post will be updated when I receive a file with such.

Static Crypt is as such in no way an innovative malware of any sort. However, it is interesting to see a previously AutoIt crypter move to C, even if the C version is simply a poorly copy pasted version of an open source packer, which is plenty of improvement compared to the previous AutoIt loader and shellcode. It comes to show how malware developers can easily make use of publicly available resources to make a profit selling their malware.

Archive containing the extracted shellcode and the original file. Standard password for infected files. The file isn’t “actually malicious” as it is simply Putty crypted, but use a VM anyways.