Protected: a

Posted on

This content is password protected. To view it please enter your password below:

A stealthier approach to spoofing process command line

Posted on

A well known trick that has been employed in malware for a very long time (this has been publicly discussed on HF since at least 2014: showthread.php?tid=4548593) is spoofing command line argument. More recently, this method got discovered by the wider infosec community and was incorporated into tools like Cobalt Strike. Implementations often go like this: you start a process as suspended with a fake command line argument, patch the PEB with the real argument, and then resume the process. However, this solution is not stealthy at all, as we will see below.

The problem with PEB patching

The method relies on patching the PEB of the process in order to spoof the environment variable prior to the process’s start. This works as the command line argument is just a buffer that is passed to the process and can be modified from usermode. However, this causes some problems for those trying to hide it: it is very easy to spot.

As the kernel does not store a copy of the command line argument anywhere, the only place for monitoring tools to get the command line argument is through reading the process’s PEB. Both Process Hacker and Process Explorer does this and shows the in-memory command line argument. Below is a simple example where I overwrite the first 5 characters with “fake!” and how it shows up in these tools.

Process Explorer
Process Hacker

Any competent sysadmin would open one of these tools and look at your spoofed powershell-or-whatnot command and recognize it for what it is.

Some work has been done by tampering with the UNICODE_STRING structure through manipulation of the length member (processes typically would ignore this internally when using GetCommandLineW/A APIs, however process explorers generally do not and follow the constraints of UNICODE_STRING). This however only allows us to hide a part of the command line parameter, and does not allow us to spoof the entire parameter. The entire string would also still be there in memory, and as it is virtually always NULL-terminated a tool could decide to ignore the length parameter and read until it reaches a NULL byte instead.

Command line internals

To look for alternatives, we must first understand how processes usually get access to the command line parameter, which is through the GetCommandLineW/A parameter. Probably for performance’s sake, the function does not actually access the PEB, instead it reads from a hardcoded pointer to an UNICODE_STRING/STRING.

This is initialized prior to the execution of the entrypoint of the process in BaseDllInitialize (or KernelBaseDllInitialize, as it’s now called on Windows 10) and points to the same information that was in the PEB at this stage.

As a result of this caching, modification of the PEB post-initialization does not affect most process’s attempts to read their own command line parameter, so we can’t just start a process unsuspended and then patch the PEB. However, this does introduce an interesting side effect: we now have two additional places where we can tamper with the command line parameter without it being visible to Process Hacker and similar tools.

Method 1: Patching BaseUnicode/AnsiCommandLine

As seen in the disassembly above, GetCommandLine simply dereferences and returns a hardcoded pointer. While this address is not exported, we can easily retrieve the relevant offset from the GetCommandLine API itself. Frome Windows XP to 10 (I have not validated this on prior Windows versions, but feel free to), the functions has not changed and is as follow:

 mov eax, dword ptr ds:[offset_to_buffer]

And likewise on x64 environments,

 mov rax, qword ptr ds:[offset_to_buffer]

What this effectively means is that we can get the address of GetCommandLine, parse it and extract the pointer (the pattern is A1 34570475 C3 for 32 bit processes), patch the pointer there and voila, any subsequent calls to GetCommandLine will return whatever we want it to. An even neater thing is that everything up until the patching it does not require reading memory from a remote process, as ASLR does not randomize module base address across processes, and as long as you have the same bitness as your target process the address will be the same.

With this method, there are some nuances that needs to be addressed. The first is that from a certain Windows version the function no longer resides in kernel32 but instead in kernelbase. This however is easily addressed and takes no difficulty to deal with. The second is that this needs to be done after the process has started execution (as BaseDllInitialize would just overwrite the pointer otherwise, and kernel32 wouldn’t be loaded yet), this can be remedied by patching the entrypoint with EB FE (a jump to self, an useful instruction to remember for unpacking certain malware), fixing the pointers, suspending the thread, restoring the original bytes and then resuming the main thread. It is not really possible to avoid starting the process as suspended unfortunately due to this timing issue.

Method 2: Modifying GetCommandLine

Another place we can intercept is the pointer to BaseUnicodeCommandLine.Buffer itself (rather than BaseUnicodeCommandLine.Buffer). This requires some code patching and is likely easier to detect via hook scanners which compares with disk, however it is still stealthier than modifying the PEB or simply detouring the API with a jmp. The function always take the form of A1 xxxxxxxx C3 and we can patch it to point to a buffer that we control. This requires two levels of indirection, and we need to patch it with a pointer to a pointer to the command line buffer.

Method 3: Getting BaseDllInitialize to do the dirty work for us

Another option we have is as follow: first start the process suspended, patch the PEB with the to-be-hidden command line argument, patch the process entrypoint with EB FE, resume, wait, restore the original command line argument in PEB, suspend the main thread, restoring the original entrypoint and then resuming the thread. This would work as BaseInitializeDll will copy the hidden command line argument for us to BaseUnicodeCommandLine and BaseAnsiCommandLine and does not require us to interact with them directly. This would also hide the command line from Process Hacker and other similar tools as the patched command line parameter is only pointed to by the PEB for a brief moment, and they would have to somehow read at exactly the correct time to obtain this information.

Some final notes on this method

This solution is not going to work with processes that do not use the GetCommandLine API to retrieve it’s parameters. However, in practice I have not seen any tools or utilities which directly accesses the PEB to get this information about itself or use another method. If other methods exists to retrieve this information, it can probably be similarly addressed through some sort of tampering, and if that is not possible, simply hooking the API would normally suffice. Likewise, if the time ever comes when the API itself changes (which I doubt it will), one can simply switch to hooking to return a different command line parameter.

Some possible injection-less detection vectors would be through comparing the pointer in PEB with the pointer in BaseUnicodeCommandLine and checking the integrity of the GetCommandLine function. Alternatively, one could inject into the process and compare the output of the API with PEB. Either way, it is much more complicated to obtain the real command line parameter than it would be if we simply patched the PEB.


A PoC will be published when I have more time on my hand to clean up my experimental code base. However, the information in this post alone is more than enough for anyone looking to implement the trick to spoof command line arguments in a way that is not easily seen during a red team engagement.

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.

Analysing Remcos RAT’s executable

Posted on

Remcos is a native RAT sold on the forums It is an interesting piece of RAT (and the only one that is developed in a native language other than Netwire) and is heavily used by malware actors. Coded by the author, Viotto, it is self proclaimed to be a legal administration tool. Whether that is true or not is to be understood by people who have seen Remcos malware campaigns and the fact that the author also sells a crypter.

First thing we notice when looking at Remcos RAT is that it uses C++ and the CRT quite heavily. This leads to the output file being rather large (though still small by some standards) at 120kb.

Another interesting thing is that Remcos allows you to extract the license (which is most likely based on the HWID) of the individual who created the stub easily by executing the file with the -l switch. If the sample is packed by a crypter that does not pass the command line parameter, you’ll have to unpack it first.

Static Mutex (compared across multiple bins), runtime detection and hooking as well as memory signature anyone?

Simple resource loading using kernel32 APIs

Fragments from usage of the public password recovery tools developed by NirSoft (/stext is a command line switch used to dump passwords to a text file, reference):

Public pasted runpe (almost identical to this, the only difference is that the Unicode API is used and the input buffer is not freed at the end).

Disabling MSC via registry (I would be surprised if no AVs detect this as suspicious behaviour)
Repeatedly loading the same string over and over again using the .c_str() function (because one cannot store the same static string in a global/local variable and use it for these calls rather than obtaining it again and again every time)

File installation implementation:

Starting the debug console

Very simple (and runtime detected) keylogger using SetWindowsHookExA (13 is the constant for WH_KEYBOARD_LL)

Downloading file using URLDownloadToFileW and then dropping VBS file to replace old executable with new executable for updating:

Resolving some APIs (I am rather curious as to why these specific APIs are resolved dynamically when other suspicious APIs such as WriteProcessMemory and SetThreadContext are imported directly from the IAT0.

Downloading DLL to buffer, map a new memory page and then loading the DLL:

It also seem that the RAT is somewhat modular, DLLs are sent from the controller (or loaded from resource/.data) and functions from it are called.

The functions listed here are only found as strings in remcos samples, which confirms that the module is custom.

Overall, Remcos is not advanced nor extraordinary and a killer for it can be easily be developed when needed. Despite being rather unsophiscated, it is still heavily used by cybercriminals to control infected devices and siphone money from those who are infected.

Sample hash: 46E4CFF5DD847E0A9AB26F2F92E89AE9E1BB14ED (file is available via VirusBay)
IDA Database File: Uploaded to GitHub

Analysis of the CrunchyRoll malware

Posted on

Hello, recently CrunchyRoll was attacked with a DNS Hijack and a malware was delivered. The malware does some strange stuff that I can’t comprehend but here are just my notes from the little effort that I put into it.

Sample SHA1: 7F0C19EEC1913F193B236C59742E469E16CE4DE2

Opening the file up in IDA and traversing to WinMain, we see this:

The file performs startup persistence, and then allocate some memory, copy the shellcode there, and then execute it.

Opening the file up in OllyDbg, we break after the VirtualAlloc call and step into the shellcode (which is rather small).

First, it obtained EIP using the common call-pop method. Strangely however, unlike most malware, it doesn’t have a function that does something like this:
pop eax
push eax
but rater chose to do it via a jump and a call back to pop eax. I suppose this might also be a form of a

Next, it jumps into a bruteforce loop.

After it is complete, EBX’s value is 0xB2FB9B40, which is then flipped with a bswap instruction. We finally reach the self decryptor, having obtained our key:

After that it is a bunch of weird stuff happens that I didn’t really look at but anyways, if you want to continue reverse engineering now you have a little more information I guess.

It seems like the malware receives a shellcode from the CnC and then performs a jmp to it, nothing more.


Regarding reddit, people tends to become stupid and post false information (hurr durr russian ip hurr durr ransomware), please disregard them, thanks. No, it was not hosted in Russia, the CnC is @ an OVH server in France. (145.239.41 dot 131).


Oh and here’s the dumped shellcode for your viewing pleasure.

Download: (password: infected)



bartblaze wrote another nice article regarding this malware, you might want to look into it.