The OceanLotus Group (aka APT32 and APT-C-00) is known for its attacks in East Asia. A number of studies on the group’s work were published last year, including
CyberReason documents, a
FireEye review, and a description of the watering-hole of the
Volexity attack. As we can see, the group updates the backdoors, infrastructure and infection vectors.
OceanLotus continues to target companies and government agencies in East Asian countries. According to ESET telemetry, OceanLotus’s priorities are in Vietnam, Laos, Cambodia and the Philippines.
A few months ago, we discovered and analyzed one of their newest backdoors. It implements several tools that make it difficult to analyze and avoid detection - they will be discussed in a post.
')

Spread
To convince the victim to launch a malicious dropper, the attackers use different methods.
Dual extensions and fake application icons (Word, PDF, etc.)
There is a chance that droppers are distributed via email attachments. We observed the following file names:
-
Mi17 Technical issues - Phonesack Grp.exe
(Mi-17 - Russian helicopter model)
-
Chi tiet don khieu nai gui saigontel.exe
(translated from Vietnamese - “details of the claim sent to Saigontel”, Saigontel is a Vietnamese telecommunications company)
-
Updated AF MOD contract - Jan 2018.exe
-
remove_pw_Reschedule of CISD Regular Meeting.exe
-
Sorchornor_with_PM_-_Sep_2017.exe
-
20170905-Evaluation Table.xls.exe
-
CV_LeHoangThing.doc.exe
(fake resumes were also found in Canada)
All of these files have something in common - launching a password-protected bait document. It is unclear whether somewhere in the data of the transmitted letter is a password, or the document should not open.
Fake installers
Several fake installers pretending to be installers or software updates were seen in watering hole campaigns. One example is the repackaged Firefox installer described by 360 Labs on
Freebuf (in Chinese).
Another sample we saw was called
RobototFontUpdate.exe
. It probably spread through compromised sites, but we do not have sufficient evidence of this.
All described files, whether they were distributed via mail or downloaded when visiting a compromised site, delivered the same backdoor component. In the post, we will analyze the sample of
RobototFontUpdate.exe
and show how it manages to execute the malicious payload in the system.
Technical analysis
The installation and execution process depends on multi-layer obfuscation, namely, component encryption, PE file reconstruction, shell-code loading and side-loading technology (fill). The latter was described in a previous ESET study on the
Korplug .
Review progress
The attack consists of two parts: the dropper and the launcher. Each step of each part of the process will be explained in detail in the appropriate section. The two schemes below provide a brief overview of the overall progress of malware.
Figure 1. Dropper progress
Figure 2. Backdoor progressAlmost all of these components are obfuscated. Obfuscation is based on teams of a pair of complementary conditional transition. For each of the forms: JZ / JNZ, JP / JNP, JO / JNO, and so on, each pair makes the transition to the same goal. The sequence is interspersed with garbage code that uses the stack pointer, but does not change the value of the conditional flag. It turns out that the transition takes place within one branch. This leads to problems in the decompilation process due to the use of positive values of the stack pointer.
Figure 3. Complementary conditional transitionIn addition, some basic program elements add one address to the stack, and then end on a JMP / CALL, while other basic elements add two addresses and end with the RET command. The second addition of the element is the called function, and the first is the address of the next basic program element where the transition will be made. Thus, the basic elements of the program are created without parent objects.
Figure 4. PUSH / JMP TechniqueAs a result of a combination of two obfuscation techniques, “beautiful” graphics are obtained:
Figure 5. Obfuscating the run sequenceIt's easy to notice the trash code. It can be ignored when analyzing samples, if you know the scheme of application.
Dropper
Stage 1. Bait Document
In recent months, OceanLotus used several baits. One of them is the fake font update software
Roboto Slab regular
TrueType. Font selection seems a bit strange, as it does not support many East Asian languages.
Figure 6. RobototFontUpdate font update iconWhen executing, a binary file decrypts its resources (XOR, 128 bytes, hard-coded key) and recovers decrypted data (LZMA). Legitimate RobotoSlab-Regular.ttf file
(SHA1:
912895e6bb9e05af3a1e58a1da417e992a71a324
) is written to the
%temp%
folder and is launched using the Win32 API function
ShellExecute
.
The shellcode is executed, decoded from resources. After performing the fake font update, it injects another application, whose sole purpose is to remove the dropper. This "erase" application is implemented as
%temp%\[0-9].tmp.exe
.
Stage 2. Shell Code
The same shellcode is applied at each stage.
Shell code - custom PE loader. It restores the executable file in memory - decrypts all sections and calculates the necessary movements and other indents. Shell code uses three Windows API functions:
VirtualAlloc
,
RtlMoveMemory
and
RtlZeroMemory
.
The
RtlZeroMemory
function
RtlZeroMemory
used to reset fields in the PE header. It is impossible to rely on automatic memory dump, because the MZ / PE headers are damaged.
The shell code calls the input function in the decrypted PE, and then the export function
DLLEntry
.
Stage 3. Real Dropper
{103004A5-829C-418E-ACE9-A7615D30E125}.dll
This executable file decrypts resources using the AES algorithm in CBC mode through the Windows API. Hard-coded key has a size of 256 bits. After decryption, the compressed data is unpacked (LZMA algorithm).
If the process is run as an administrator, the malware ensures persistence by creating a service. Otherwise, the classic Run registry key is used (
HKCU\SOFTWARE\Microsoft\ Windows\CurrentVersion\Run;DeviceAssociationService;rastlsc.exe
).
If the dropper code is executed with administrator rights, it tries to write the files listed below into the folder
C:\Program Files\Symantec\Symantec Endpoint Protection\12.1.671.4971.104a\DeviceAssociationService\
, if not, it writes them to the
%APPDATA%\Symantec\Symantec Endpoint Protection\12.1.671.4971.104a\DeviceAssociationService\
folder
%APPDATA%\Symantec\Symantec Endpoint Protection\12.1.671.4971.104a\DeviceAssociationService\
:
-
rastlsc.exe
(SHA1:
2616da1697f7c764ee7fb558887a6a3279861fac
, copy of the legitimate Symantec Network Access Control application,
dot1xtra.exe
)
-
SyLog.bin
(SHA1:
5689448b4b6260ec9c35f129df8b8f2622c66a45
, encrypted backdoor)
-
rastls.dll
(SHA1:
82e579bd49d69845133c9aa8585f8bd26736437b
, malicious DLL that is being
rastlsc.exe
by
rastlsc.exe
)
The path varies from sample to sample, but the pattern is similar. Depending on the rights, the malware resets files to
%ProgramFiles%
or
%appdata%
. We also observed:
-
\Symantec\CNG Key Isolation\
-
\Symantec\Connected User Experiences and Telemetry\
-
\Symantec\DevQuery Background Discovery Broker Tasks\
These paths are used by various Symantec products.
After reaching persistence and implementing an executable file, a legitimate file,
rastlsc.exe
, executed using
CreateProcessW
.
We also observed the version (
{BB7BDEC9-B59D-492E-A4AF-4C7B1C9E646B}.dll
), which executes
rastlsc.exe
with the
krv
parameter. We will discuss in detail below.
Backdoor component: rastlsc.exe fill
The OceanLotus team uses an old and well-known technique in one of the Symantec executables. The bottom line is to use the process of loading a legitimate and signed .exe library file by writing a malicious library into the same folder. This will make the malicious behavior look legitimate, since these actions are performed during the operation of the trusted executable file.
As mentioned above, the legitimate
rastlsc.exe
file is reset and executed.
It imports the
rastls.dll
file, which in this case has malicious content.
Figure 7. Digital signature rastlsc.exe from SymantecWe also saw a fill using other legitimate and signed executable files, including
mcoemcpy.exe
from McAfee, which loads
McUtil.dll
. This technique was previously used by PlugX, which attracted the attention of
Vietnam CERT (in Vietnamese).
Stage 1. Filling the library, rastls.dll
The internal name of the dll file is
{7032F494-0562-4422-9C39-14230E095C52}.dll
, but we have seen other versions, for example,
{5248F13C-85F0-42DF-860D-1723EEAA4F90}.dll
. All exported functions lead to the execution of the same function.
Figure 8. All rasltls.dll exports lead to the execution of a single functionThe export tries to read the
SyLog.bin
file located in the same folder. Other versions tried to open the
OUTLFLTR.DAT
file. If the file exists, it will be decrypted using the AES algorithm in CBC mode with a hard-coded 256-bit key, and then the compressed data will be decompressed (LZMA compression).
Option
McUtil.dll
uses a different technique. At first glance, the main function does not perform anything malicious, but in fact it replaces the
.text
section of the legitimate
mcoemcpy.exe
file, a binary file. It generates a shellcode whose task is to call a function to read the encrypted shellcode of the second stage from the
mcscentr.adf
file.
To create a shellcode, use the following pseudocode:
x = False i = 0
buff = genRandom()
opc1 = [0x58,0x59,0x5a,0x5b]
opc2 = [0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57]
opc3 = [0x90,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,
0x49,0x4a,0x4b]
while i < len(buff):
currentChar = buff[i] if currentChar < 0xc8:
buff[i] = opc1[currentChar % len(opc1)]
else:
if x:
buff[i] = opc2[currentChar % len(opc2)]
else:
buff[i] = opc3[currentChar % len(opc3)] x = x == False
i+=1
Below in the picture you can see the listing of the result of the assembly:
Figure 9. Generated shellcodeStages 2–4. Shell Code Launcher and Shell Code Again
Shell code decrypts and loads the library
{E1E4CBED-5690-4749-819D-24FB660DF55F}.dll
. The library loads resources and tries to start the DeviceAssociationService service. The decrypted information also contains the shellcode. The latter decodes the final stage: the backdoor.
Option
{92BA1818-0119-4F79-874E-E3BF79C355B8}.dll
checks if
rastlsc.exe
executed with
krv
as the first parameter. If yes, the task is created, and
rastlsc.exe
is executed again, but without this parameter.
Stage 5. Backdoor
{A96B020F-0000-466F-A96D-A91BBF8EAC96}.dll
First, the malware tries to download its resources and decrypt them using the RC4 algorithm. The resulting resources contain the data used to configure the backdoor. The configuration format is easy to learn. Using the Kaitai struct and its dumper structure, we get the following:
Figure 10. Configuration structureNote : with the exception of the domain_encoding_str string and the httpprov library, data changes from sample to sample. The registry keys are almost the same, but they have a similar scheme:
\HKCU\SOFTWARE\Classes\AppX[a-f0-9]{32}
, nothing remarkable.
The malicious program receives the first 10 bytes of the username (UTF-16), korit them with a three-letter string
mutex_encoding_str
in UTF-16 and encodes in hexadecimal. The result is used as the name of the mutex. For example, for a user whose name begins with
abc
and a key in the form of
vwx
, the mutex will be
\Sessions\1\BaseNamedObjects\170015001b
.
The backdoor includes a PE loader that loads the
HTTPProv.dll
library into memory, calls an entry point, and then calls the
CreateInstance
export function.
Communication
The backdoor uses the standard TCP communication protocol on port
25123
. To obtain the IP address of the server, the backdoor first creates a specific DNS query.
The malware selects one of the three domains from the configuration and adds a special subdomain, which is generated using two values. The first value is the computer name within the length of 16 bytes. The second is a four-byte version ID. The code in Python 2 below is a coding algorithm:
letters=domain_encoding_str # “ghijklmnop” hex_pc_name=pc_name.encode(“UTF-16LE”).encode(“hex”) s=''
for c in hex_pc_name:
if 0x2f < ord(c) < 0x3a:
s+=letters[ord(c) - 0x30]
else:
s+=c
For example, if the computer name is
random-pc
, and the version ID is 0x0a841523, then the following domain is generated:
niggmhggmeggmkggmfggmdggidggngggmjgg.ijhlokga.dwarduong[.]com
For the C & C server label of this backdoor, you can use the following regular expression:
[ghijklmnopabcdef]{4-60}\.[ghijklmnopabcdef]{8}\.[az]+\.[az]+
If the IP address belongs to a specific domain, malware tries to establish a TCP connection through port
25123
. Each sample has three different domain names that are used to search for a C & C server.
The communication process is RC4 encrypted and compressed using LZMA. It is possible to decrypt traffic, as the key is added to the beginning of the packets. The format is as follows:
[ RC4 (4 )][ ]
Each key byte is generated by the
rand
function. After decrypting and unpacking a packet, the data has the following format:
[dw:][dw:][dw: ][dw: ][dw:] [dw:]
The first time the client connects to the server, a UUID is sent, which is used as the session ID. The latter is stored in the registry key as binary data:
HKCU\SOFTWARE\Classes\ AppXc52346ec40fb4061ad96be0e6cb7d16a\DefaultIcon
As we said earlier, the backdoor also contains a library called
HTTPprov
. It is used as an alternative way to communicate with the server. The DLL file sends a POST request via HTTP. It also supports HTTPS and proxy usage of SOCKS5, SOCKS4a and SOCKS4. The library is statically linked with
libcurl
.
After initialization, an entry will be created in the registry - a command for the backdoor to further use HTTP to communicate with the command server:
HKCU\SOFTWARE\Classes\ CLSID{E3517E26-8E93-458D-A6DF-8030BC80528B}
.
A standard client application is used:
Mozilla/4.0 ( ; MSIE 8.0; Windows NT 6.0; Trident/4.0)
.
The main characteristic of this library is a special algorithm for encrypting the universal resource identifier. The resource part of the URI is created using the following pseudocode:
buffEnd = ((DWORD)genRand(4) % 20) + 10 + buff; while (buff < buffEnd){
b=genRand(16);
if (b[0] - 0x50 > 0x50)
t=0;
else
*buf++= UPPER(vowels[b[1] % 5]);
v=consonants[b[1]%21]); if (!t)
v=UPPER(v);
*buff++= v;
if (v!='h' && b[2] - 0x50 < 0x50)
*buff++= 'h';
*buff++= vowels[b[4] % 5];
if (b[5] < 0x60)
*buff++= vowels[b[6] % 5];
*buff++= consonants[b[7] % 21];
if (b[8] < 0x50)
*buff++= vowels[b[9] % 5];
*buff++= '-';
};
*buff='\0';
Note : for clarity, the part responsible for checking the string length has been removed from the code.
To obtain an identifier from the generated string, add two numbers using a special sum check algorithm:
checksum=crc32(buff)
num2=(checksum >> 16) + (checksum & 0xffff) * 2
num1=(num2 ^ 1) & 0xf
URL=GENERATED_DOMAIN+ “/” + num1 + “/” + num2 + “-” + buff
By adding the
HTTPprov
library URI generator, we get the following URL:
hXXp://niggmhggmeggmkggmfggmdggidggngggmjgg.ijhlokga.aisicoin[.]com/ 13/139756-Ses-Ufali-L
Teams
After obtaining the SESSIONID session ID, the backdoor makes a digital fingerprint of the system. The package is built as follows (indent in the package - description):
0x000 - byte: the value changes in each version
0x001 - 0x01: hardcoded byte
0x002 - bool: the presence of elevated privileges
0x003 - dword: version ID
0x007 - string (UTF-16), computer name (max. 0x20)
0x027 - string (UTF-16), username
0x079 - the result of the query on the registry in
HKLM\SOFTWARE\Microsoft\Windows NT\ CurrentVersion
values:
ProductName
,
CSDVersion
,
CurrentVersion
,
ReleaseId
,
CurrentBuildNumber
and the result of the call
IsWow64Process (x86|x64)
0x179 - the subsequent format of the string% s (% s); is replaced by (
GetVolumeInformationW:VolumeNameBuffer
),
VolumePathNames
0x279 - Physical disk, control I / O device PhysicalDrive deviceIOControl 0x2D1400 (IOCTL_STORAGE_QUERY_ PROPERTY) (VolSerialNumber)
0x379 - wmi
SELECT SerialNumber FROM Win32_BaseBoard
0x3f9 - Get the current date and time GetSystemTimeAsFileTime
0x400 - bool: unknown
0x401 - dword: received after decrypting a resource
Here is an example of a digital fingerprint system:
Figure 11. Digital Fingerprint SystemThis is a full-fledged backdoor, which provides its operators with a number of possibilities: manipulating the file, registry and processes, loading additional components, obtaining a digital fingerprint of the system. Below are the numbers and descriptions of supported commands:
0 - digital print
1 - sets the session ID
2 - creating a process and getting a result (using software channels)
3 - sets the count of connection attempts
4 - postpones polling time
5 - reads a file or registry key and counts MD5
6 - process creation
7 - creates a file, registry entry or stream in memory
8 - writes to the registry
9 - polls the registry
10 - looks for files in the system
11 - transfers files to another directory
12 - deletes files from disk
13 - getting a list of disks marked up in the system using the function
GetLogicalDriveStringW
14 - creates a directory
15 - deletes the directory
16 - reads file from offset
17 - calls PE loader (transition to communication via
HTTPprov
)
18 - [Unknown]
19 - 0: polling values in the registry; 1: implementation and execution of the program
20 - sets the environment variable
21 - launches shellcode in new thread
22 - returns the environment variable
+23 in the new version - restarts itself if the APPL environment variable does not exist
Conclusion
OceanLotus remains highly active and continues to update the toolkit.
The group seeks to hide its activities; to do this, attackers carefully select victims, limit the spread of malicious programs, use several servers in order not to draw attention to a single domain or IP address. Deciphering the component being injected and the fill technique (side-loading), despite being widely known, avoids detection, since the work of intruders in this case is disguised as a legitimate application.
Compromise Indicators (IoCs)
Samples
Table 1: dropper

Table 2: Libraries

Network
IP addresses
46.183.220.81
46.183.220.82
46.183.222.82
46.183.222.83
46.183.222.84
46.183.223.106
46.183.223.107
74.121.190.130
74.121.190.150
79.143.87.230