This article was transferred from the @herrcore blog.
In the past few months we have seen asprox rise to be one of the leading e-mail distributed trojans in North America. Asprox is a lightweight trojan that is used to maintain control of an infected host and either download additional functionality (directly related to the Asprox botnet) or install a second-stage payload to an infected host as part of an affiliate network (partnerkas).
A full overview of the botnet can be found in Trend Micro's report "Asprox Reborn" (note the bot behaviour is now different from what is described in the report) or in Michal Ambroz's excellent post "Asprox Botnet - Phishing Malware As a Service".
This report details the recent evolution of the asprox first-stage trojan, its behaviour, new encryption scheme, new IOCs. While much has already been written about the asprox botnet this report will expose the inner-working of the first-stage trojan in an effort to help researchers and incident responders both understand and protect against this trojan.
A note on semantics: Asprox is also known as Kuluoz by anti-virus vendors. I have been told that asprox is used to refer to the botnet infrastructure while kuluoz refers to the actual trojan. For the sake of simplicity asprox will be the only term used in this report to refer to the malware under analysis.
Asprox e-mails all follow a similar pattern, one that you are sure to be familiar with if you have been investigating malware in the past few months. The e-mail's masquerade as parcel deliveries, airline reservations, court appointments, resumes, etc. The e-mail references an attachment which is usually an attached .zip file that contains the trojan .exe. In October 2013 the e-mails used a link that would download a .zip but since November 2013 all e-mails collected have had attachments.
Examples of Asprox E-Mails
The following posts and reports detail the types of e-mails that asprox is distributed by:
Though the trojan in the zip file is just a PE file the icon has been changed to make it appear as a word document. With the default windows configuration set to hide file extensions the trojan can easily trick a victim into clicking on it.
When the trojan is executed the victim will see Notepad open with a message. This message changes based on the version of asprox but the current string is "Unknown ERROR! Please wait and try again later." This is used to trick the victim into assuming the attachment was an error and nothing malicious has occurred. For a full description of what is happening behind the scenes see the Initial Infection section of this report.
When a victim executes the asprox trojan it will appear as though they have opened a Word document in Notepad, strange but not malicious. However, behind the scenes asprox is busy installing itself on the host. In the next sections the true behaviour of the asprox trojan will be revealed.
The asprox trojan is packed in what appears to be a custom packer which is refreshed for each e-mail campaign. These packers usually have a fairly high detection rate after the first day of the e-mail campaign (initial detection rates are unknown at this time). This report does not examine the packer in detail as it is simply used to inject a process with the asprox trojan.
Injection and Initial Setup
The packer behaviour is as follows:
- unpacks itself to a new process with the same name
- executes a copy of 32bit svchost.exe (on a 64bit host it uses the
- injects the asprox trojan into the new svchost process
The asprox trojan that is injected into the svchost process is a dll. This dll can be extracted from the injected process for further analysis (see Incident Response and Remediation section of this report for further details). Once the asprox.dll is injected it takes over control of the program flow.
The asprox.dll actually has a small code stub that it uses to inject itself into the svchost.exe process so technically this is not the packer. Normally this stub would not be of much interest to us except for the way that gets the addresses for the library functions it uses.
Since it is injected the asprox.dll gets the address of GetProcAddress by "walking" from the Process Environment Block down to the Module List and comparing the module names against a hash of "kernel32.dll" (the hash is 0x6A4ABC5B). This is where we see the first interesting IOC and gain some possible insight into the origins of asprox. The code used to perform this function matches similar code found in Zeus. It is possible that this section was copied from the leaked Zeus source or from a research blog post explaining how it works. Further explanation of this code can be found here.
As for our IOC we can now use a yara rule to search for the following bytes in memory (ex. with Volatility) 0x81 0xff 0x5b 0xbc 0x4a 0x6a which represents the assembly instruction cmp edi,0x6a4abc5b. This IOC by itself is not unique to asprox.
Once the asprox.dll has been successfully injected into svchost.exe it kills its parent processes (the processes started by the packer) leaving an orphan svchost.exe process running under explorer.exe. This is our second IOC; an svchost.exe process running under explorer.exe. Again this IOC is common to many families of malware and not unique to asprox.
The main loop for the asprox.dll is then called through the asprox.dll export "Work". This concludes the initial injection of the asprox.dll.
When the Work function is first called it attempts to create a mutex with a hard coded string. If the mutex is already in use the dll knows that another copy of itself is running and it terminates its host process. Though the hardcoded mutex string does make a unique IOC it is frequently changed so it cannot be relied on as a generic asprox identifier.
Before entering the main loop of the Work function the asprox.dll checks the local user run key
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run to see if any key values have been set for its on-disk .exe file.
If no run key is set then it attempts to hide its presence by copying its on-disk exe to a new file in the
%LOCALAPPDATA% folder. The new file name is a randomly generated string of 8 lowercase letters. The original on-disk .exe file is then deleted. Here we have our next IOC, there will be an .exe in the
%LOCALAPPDATA% folder with a random 8 letter lowercase name.
If there is a run key set then it will skip the file copy function and after 10 successful network communications with the c2 it will set a run key for the on-disk exe. The run key name is generated using 8 random lowercase letters. This provides us with another IOC.
Antivirus/Sandbox/Researcher Detection and Evasion
All versions of the asprox.dll collect the following information from its environment:
- firewall configuration,
- antivirus configuration,
- OS version,
This information is later reported back to the c2 in the
The firewall and antivirus configuration is collected using Microsoft's wbem service via the COM interface. The "ExecQuery" function is called on the wbem object so the input requires ascii strings which can be found in the process memory. These strings provide us with another IOC:
"SELECT * FROM AntiVirusProduct" and
"SELECT * FROM FirewallProduct" (these strings are unicode). This IOC does not indicate malicious behaviour by itself but combined with other IOCs from this report it can be used to identify asprox.
Recent versions of the asprox.dll include examination of the environment in an attempt to determine if the asprox.dll is running in a sandbox or if a researcher is attempting to analyze it. The malware uses the FindWindow function to search for known analysis tools as well as enumerating various registry keys. This information is then passed to the c2 in
<src> element. The window names and registry keys that are searched for are listed below (as of the latest version).
HKEY_LOCAL_MACHINE\SYSTEM\\CurrentControlSet\\* services\\Disk\\Enum 0=VMware
HKEY_LOCAL_MACHINE\SYSTEM\\CurrentControlSet\\services\\Disk\\Enum 0= VBox
HKEY_LOCAL_MACHINE\HARDWARE\\DESCRIPTION\\System\\BIOS\ SystemProductName = VBox
HKEY_LOCAL_MACHINE\HARDWARE\\DESCRIPTION\\System\\BIOS\ SystemProductName = AMIBI
HKEY_LOCAL_MACHINE\HARDWARE\\DESCRIPTION\\System\\BIOS\ SystemManufacturer = AMIBI
The new versions of asprox.dll also added a 2min sleep to its initialization section which I suspect is an attempt at sandbox evasion. We can see when running the version with the sleep in the cuckoo sandbox that the 2min sleep is enough to evade much of the detection.
All of the checks happen in the "setup section" before the main loop in the asprox.dll so you can trick the window name searcher by not running any of your tools until after you see the asprox.dll make its first network call. You can also easily hide the registry keys or write a simple hook for
RegQueryValueEx. Also if there is a run key that matches the image name of the process then the environment analysis is skipped.
Incident Response and Remediation
Asprox is built to enable downloading and installation of a second-stage payload so it is very likely that the asprox.dll will be replaced by another piece of malware if an infected host is not attended to quickly. However, if a system is infected with the asprox.dll the following steps can be used to collect a sample of the .dll and clean the infected host.
Evidence Collection and Host Remediation
- Verify the host is infected with asprox using the IOCs in this report. Note the PID of the svchost.exe process that is running under explorer.exe
- Use your favourite memory dump tool to dump the host memory and save to your analysis system
- Use process explorer to kill the svchost.exe process that is running under explorer.exe
- Open the
%LOCALAPPDATA%folder and delete all instances of the asprox .exe (identified by the random 8 lowercase letter names)
- Open regedit and delete all run keys for the asprox.exe located in
- Open regedit and delete all asprox registry keys in
HKEY_CURRENT_USER\Software\identified by the random 8 lowercase letter names (see more on how to positively identify these keys in the Communication:Group ID section of this report).
- If you want to further analyze the asprox.dll that was injected into the scvhost process you can use volatility an run malfind on the svchost PID that you noted in the above steps.
- Once malfind has completed dumping the injected code you can easily locate the asprox dll in the segments by searching for the "MZ" header. The header will appear in multiple sections but only one of them has the full DLL (the one that has a sub of set-up code before the MZ).
- Use your favourite hex editor to extract the dll.
- Once you have extracted the dll it doesn't contain any anti-debugging/analysis features so you can easily analyze it.
- Post your analysis : )
Asprox communicates with its c2 using HTTP. Traditionally the requests where HTTP GET requests using RC4 encryption with a unique but static key. The Trend Micro report "Asprox Reborn" describes this communication in detail. However, the new versions of asprox use a much more complicated encryption scheme with HTTP POST requests. The new encryption scheme has been described here but this report will elaborate on the description.
Each bot is assigned a unique ID that is both used to identify them to the c2. The ID is generated using the following algorithm:
md5( binary_SID + os_install_date + account_name_string)
RegOpenKeyExA is called to access the os install date registry key the
KEY_WOW64_64KEY flag is not passed on the samDesired argument. Since asprox.dll runs in a 32bit process the fact that it is missing this flag means that when it runs on a 64bit system it will access the wrong registry and the will get a null value. This means that os install date that is used as part of the ID hash will be 0x0000 for all 64bit systems.
In addition to identification a substring of the ID is also used for encryption. The first 4 bytes of the ID are used to create an ID_Key that is used to encrypt and decrypt locally stored values in registry keys as well as encrypt the URL for the c2 communication.
I have developed a small powershell script that will enable you to generate an asprox ID and ID_Key for any system. Note: the script will not work on domain joined systems as the NTAccount method would need to be adapted to get the domain SID.
In addition to a unique ID the bot is assigned a
Group_ID. Though we can't be certain what the
Group_ID is used for we can hypothesize that it is used to track groups of bots and make bot management easier. When asprox.dll runs if there is no run key set for it then it will assign the
Group_ID based on hard coded string in the asprox.dll.
If there is a run key set then it will enumerate all keys in
HKEY_CURRENT_USER\Software and attempt to RC4 decrypt each key value using the ID_Key. It will then compare the decrypted key value against the string "For group!!!!!" if the string matches then it will take the remaining portion of the string (after the for group part) and use that as the
This provides us with another IOC; a registry key in
HKEY_CURRENT_USER\Software with a name composed of 8 random lowercase letters who's value can be decrypted by the host
Key_ID to display the string
For group!!!!!<group_id>. This key is only set when asprox.dll has successfully communicated with the c2 10 times.
Asprox gets its IP addresses from one of two locations, either a registry key, or hard coded in the asprox.dll. Each time asprox.dll makes a new network request to the c2 it uses the same method described above in Group ID to enumerate all the keys under
HKEY_CURRENT_USER\Software, decrypt their values, and compare them to the string "You Fag!!!!!". If the string compare matches then the part of the key after the you fag string is interpreted as an
in_addr struct. This key is only set when asprox.dll receives new IP addresses from the c2.
If no registry key is found then the asprox.dll uses a hard coded ip address that is RC4 encrypted with a hardcoded key. The hardcoded key varies with each version of asprox.
The URL path is hard coded in the asprox.dll as
/index.php?r=gate but it is RC4 encrypted with the
ID_Key and prepended with the
ID_Key before being sent. The new versions of asprox use a POST instead of a GET so no interesting parameters are passed in this URL.
Request Body (XML)
The actual content sent by aprox.dll to the c2 is encapsulated in XML. There are two versions of the XML a slightly older version and a newer version. Both are described below.
|<knock>||XML top element open|
|<group>%s</group>||Group ID string|
|<version>%d</version>||Hardcoded bot version|
|<status>%d</status>||Status of last command|
|<debug>%s</debug>||Environment information such as OS version, 64/32bit, firewall, antivirus|
|</knock>||XML top element close|
|<knock>||XML top element open.|
|<group>%s</group>||Group ID string.|
|<src>%d</src>||Reports if any of the researcher tools or sandbox string are found.|
|<transport>%d</transport>||Reports if asprox is running from a removable drive. This may hint at a possible worm version in the future.|
|<version>%d</version>||Hardcoded bot version.|
|<status>%d</status>||Status of last command.|
|<debug>%s</debug>||Environment information such as OS version, 64/32bit, firewall, antivirus.|
|</knock>||XML top element close|
Once the XML body has been constructed it is bzip compressed and then RC4 encrypted with a dynamically generated key. They key is then RSA encrypted with the following public certificate:
-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----
The encrypted key and body are then sent as part of the POST request body. The format of the POST request varies between the slightly older version and the newer version of the bot. Both formats are described below.
The older version uses
multipart/form-data as the content-type and separates the key and body into two separate streams
name="key" filename="key.bin" and n
The new version uses
application/x-www-form-urlencoded as the content-type and does not have any ascii strings in the body. This eliminates any network IOCs that we might have used from the older version.
If we take a closer look at the data that is being sent in the body we can decipher how the key and body are combined. The first 4 bytes of the body represent the length of the encrypted key (little endian) 0x00000080. This is followed by the encrypted key. The encrypted key is followed by another 4 bytes that represent the length of the encrypted body 0x000000b6. These 4 bytes are then followed by the encrypted body.
The response that is received from the c2 follows the same pattern as described above but instead of a key and body the c2 sends a RSA signed hash of the response data and the actual response data bzip compressed and RC4 encrypted with the key that was sent with the request.
Examining the response we can see the first 4 bytes of the response body represent the length of the RSA signed hash of the data (little endian) 0x00000080. This is followed by the RSA signed hash. The RSA signed hash is followed by another 4 bytes that represent the length of the RC4 encrypted data 0x00000069. These 4 bytes are then followed by the RC4 encrypted data.
Commands and Capabilities
The commands have not changed since the release of the Trend Micro report however their encoding has. The commands are now send in XML encapsulation and are parsed by the MSXML 3.0 COM service. An example of a command XML is displayed below.
<task type="idl" />
The following commands are available to the asprox c2 server.
|idl||Long sleep, no commands.|
|rdl||Download and run asprox module.|
|run||Download .exe, install and run it.|
|rem||Uninstall. This command removes the asprox .exe, run key, and You Fag!!!!! key but it doesn't remove the For Group!!!!! key. This can be used as a potential IOC to prove asprox was installed if it removes itself.|
|red||Update registry keys.|
|upd||Update asprox .exe|
Samples and IOCs
Memory only IOC can be found in IOC Bucket. This IOC is tailored to only match on the memory strings that will be most difficult for the malware authors to modify.
Disk IOC can be found in our IOC repository. The IOC uses OpenIOCv1.1 as it requires regular expressions for file paths and registry keys. It will be posted it IOC Bucket as soon as OpenIOC 1.1 is supported (note* most tools do not yet support OpenIOCv1.1).