In part one of this series we explained the different stages of the malware life-cycle. This post will cover in depth the first stage, exploitation.
Exploits are a way of acting on vulnerabilities that exist within software and hardware. These bits of code, called exploit modules, are built to leverage those vulnerabilities to get other unwanted code into a system. Just as malware is built as a package and has life-cycle stages, an exploit module has its own parts and stages. The exploit attempts to push its code into the running memory of a target system so that it can be executed.
The parts of an exploit module (usually) consist of:
- An attack vector – code that leverages the vulnerability to move data to the system
- A “NOP” sled – dummy data that is used to slide the rest of the exploit module to the appropriate area of memory on the target system in order to get it executed.
- A “Shellcode” – the code that the exploit has pushed into memory. It is named after what exploits were originally designed to do – create a remote “shell” for an attacker to use to manipulate the system.
Additionally there may be extra modules in the shellcode that allow it to perform more advanced intrusions such as
- An unpacker / decryptor – used to unmask the exploit module or parts of the module after it has been pushed into the running memory of the target system. This can be a separate shellcode or built into the initial shellcode. The unpacker and/or decryptor usually make it very difficult for antivirus companies and security researchers to disassemble the malware and determine how it works and how to prevent and/or remove it.
- A detection system – to see if the exploit is hitting a trap (debugger, emulator or “honeypot”). Usually called an “Anti-Debugger”. These modules slow down or prevent anti-virus and security research companies from disassembling the exploit module.
- Anti-Anti-Virus – to blind, disable or cripple existing antivirus software on the target so that the upcoming modules are not detected. These modules were very common for many years, their usage has waned in the last few years due to advances in packers and encryption routines, and in part due to the speed at which malware authors can rewrite their code to evade detection leaving disabling the anti-virus as a
- Patches – some exploits will patch the vulnerability that it came in through in order to prevent not only re-exploitation but also to stop others from exploiting the system and having to share the system with multiple attackers. Sometimes these patch modules cause more harm than the malware. Then again some have been very very good at keeping the system up to date and patched. More on this when we get to part 4, Persistence 🙂
Vulnerabilities are not created equal! Some vulnerabilities allow unfettered access to the running memory of a remote system. Some allow only certain types of data to be passed through it, some only allow that data to be in a specific format. The process of recoding and rewriting the sled and shellcode to fit within the parameters of the vulnerability it will be used on was once a daunting task that would take weeks or months to perfect. Today there are exploit development platforms and kits that automate the process of recoding the exploits to fit in nearly any vulnerable app. These recoders will play tricks with the code to make the target system run it normally but as it is being pushed through the vulnerability it works within the restrictions of the vulnerability.
Memory is divided into “pages”, each memory page is a specific size dictated by the operating system of the system that uses it. These pages normally have attributes to help applications and the operating system use them effectively. modern desktop, mobile and server operating systems such as Windows, Linux, Mac, Android and the various Unix platforms utilize these attributes to determine which areas of memory hold data, temporary space, application code, or the operating system itself. The concept of the NOP sled is to push the shellcode into an area of memory that has been marked as “Executable”, i.e. it will try to execute whatever is stored on that page. So if the vulnerability that is being targeted lands the exploit 100 bytes away from the next executable page of memory that exploit module will need to use a 100 byte sled to plop the shellcode on that next executable page of memory.
Shellcodes as I said earlier were originally designed to give a hacker a shell to run commands on the target system. Modern, more advanced shellcodes are designed to much more devious things. Many shellcodes executed will begin placing parts of the malware package on other areas of memory by running as the operating system or the application that was exploited. Many of these shellcodes will not contain the actual malware but instead will direct the target system to download the malware from an external network, the internet usually, to hide its presence from anti-virus software. By not carrying the malware packages the shellcode can be light and agile, and by downloading the package it can retrieve the latest and greatest version of the malware packages which normally are updated frequently to evade anti-virus and intrusion detection/prevention systems.
A new(er) trend in shellcode development has been to first place an unpacker or decryptor module on the target system so that if the anti-virus or intrusion detection/prevention system on or around the target system has been updated to find the malware package it will not be able to detect it while it is being delivered from the external network. This method is more effective than crippling or disabling existing antivirus applications on the target system since it leaves very little traces of its existence.