Some samples of this new version, as for the previous release, are debug releases. We could therefore identify the following debug strings:
d:\work\scontroller(2.0) (....)\shellcode\shellcode\ d:\work\scontroller(2.6)(lz1)\shellcode\shellcode\ d:\work\scontroller(3.0)(....)(demo)(....)\shellcode\shellcode\ d:\work\scontroller(4.0)\shellcode\shellcode\
We could link all these new PlugX versions to the following internal version numbers:
20130524 20130810 20130905 20131205
The only sample with version 20130524 is the one with the scontroller(2.0) debug string. We’ll see later that this is an intermediate version between the most evolved “PlugX v1” samples and the new “PlugX v2” ones. The compilation dates range from July 2013 to December 2013.
As for the previous PlugX version, there is no direct relation between the debug strings and the internal versions (versions with debug strings 3.0 and 4.0 are the most advanced ones, but still have internal version number 20130810).
The new PlugX uses a new, custom, cipher algorithm. While the previous one was a slightly modified version of the one used in Destory, this one has nothing in common with them:
Here is the basic implementation in Python:
v1=key i=0 out="" while i<len(data): v1 = (((v1 << 7) - (v1 >> 3)) + i + 0x713a8fc1) & 0xffffffff v2 = ((v1 >> 24)&0xff) ^ ((v1 >> 16)&0xff) ^ ((v1 >> 8)&0xff) ^ (v1&0xff) out = out+chr(ord(data[i])^v2) i = i+1
This algorithm is used for configuration encryption, network communications encryption as well as for strings encryption, which is a new feature to slow down reverse engineering.
Starting from scontroller(2.0) version, the ICMP protocol has been added as a method to join the C&C. The data is transmitted as a payload of Echo reply (ICMP Type 0) packets.
The HTTP protocol has also evolved. Data is transmitted in a POST request matching the following pattern:
where the %p are random hexadecimal dwords. The following quadruples of headers are used in the request:
HHV1 / HHV2 / HHV3 / HHV4 LZ-ID / LZ-Ver / LZ-Compress / LZ-Size IXP / IXL / IXK / IXN FZLK1 / FZLK2 / FZLK3 / FZLK4 CC1 / CC2 / CC3 / CC4 ASH-1.0 / ASH-1.1 / ASH-1.2 / ASH-1.3 X-Session / X-Status / X-Size / X-Sn
The latest version, identified as scontroller(4.0), uses a new HTTP protocol. The request is no longer a POST but a GET, and data is transmitted base64 encoded in a “Cookie” header.
Once the base64 is decoded, we have a ciphered buffer which encryption key is the first dword, and ciphered data is the remaining.
This same sample also has a brand new module, XSoDNS.cpp, allowing the RAT to contact its C&C over DNS. The data is also base64 encoded, and sent as a subdomain of the C&C in the DNS segment (C&C has been faked as “126.96.36.199” in the following screenshot):
Firefox proxy stealing
The version identified as scontroller(3.0) has a new module, identified as XFirefoxProxy.cpp in the debug strings.
This module parses the prefs.js file to grab information about the configured proxy servers.
The configuration file has a size of 0x2540 bytes, except for the scontroller(2.0) version (which has a size of 0x1d18 bytes, as for the latest “v1” samples). The growth of the configuration is due to new features in the RAT.
More process injection
The new version can inject itself in up to 4 different processes. The full path of the processes are specified in the configuration.
The RAT can be configured to take screen captures at regular intervals, and store them in a local folder, for later retrieval. The configuration parameters are:
- Local storage path
- Capture quality
- Captures interval
- # of days to keep the screenshots
Previously unused strings
The previously unused strings are now part of new features, and a third one has been added:
- Online pass: a password is defined, and checked during the initial handshake with the C&C. If the password sent by the C&C is different than the one defined in the configuration, the RAT stops the connection. This can be used when a single C&C is used to receive connections from many infected systems. If a different password is used for different infected companies, the bot herder can filter the connections to the C&C to match a specific company at one time.
- Memo: a free string sent to the C&C with the host information. This might be used to identifiy a specific sample of the malware.
Harlan Carvey regretted that our previous post about PlugX did not give more information for IR investigators to identify a PlugX infection, especially about the configuration parsing.
We thus decided to release our Volatility plugin to identify and parse PlugX configuration in a memory dump. The plugin works for all PlugX variants we identified so far, with various configuration lengths.
$ python vol.py plugxconfig -f mem.dmp Volatility Foundation Volatility Framework 2.3.1 -------------------------------------------------------------------------------- Process: svchost.exe (1864) PlugX Config (0x2540 bytes): Flags: True True True True True True True True True True True Timer 1: 10 secs Timer 2: 0 secs C&C Address: dns.lookipv6.com:80 (TCP / HTTP) C&C Address: dns.lookipv6.com:53 (UDP / ICMP) C&C Address: dns.lookipv6.com:8080 (TCP / HTTP / UDP / ICMP) C&C Address: dns.lookipv6.com:53 (UDP / ICMP) Persistence Type: Service + Run Key Install Dir: %AUTO%\RasTls Service Name: RasTls Service Disp: RasTls Service Desc: Symantec 802.1x Supplicant Registry hive: 80000001 Registry key: Software\Microsoft\Windows\CurrentVersion\Run Registry value: Supplicant Injection: True Injection process: %windir%\system32\svchost.exe Online Pass: TEST Memo: nsc Mutex: My_Name Screenshots: False Screenshots params: 10 sec / Zoom 100 / 16 bits / Quality 50 / Keep 3 days Screenshots path: %AUTO%\screen
The plugin can be found on our bitbucket repository. Feel free to give us your feedback and/or report any bug!