Wednesday, February 4, 2026

LAB 3: Basic Persistence Mechanism Using the Windows API

    In Cybersecurity persistence refers to techniques used by threat actors to hold onto access to a system, even after disruptions that would normally terminate malicious activity. The main goal of this project was to develop a lightweight native persistence program using only the Windows Win32 APIs, while writing in C language. Our program achieves persistence by adding itself to the HKEY_CURRENT_USER run key, which ensures that it executes automatically everytime the user logs in.

Learning process

As for every other lab, the first step to solving this lab was to research on how to things. Firstly, I wanted te refamiliarize myself with writing in C language. I did so by going through w3schools (https://www.w3schools.com/c/), which refreshed my memory. Another source I went to was freeCodeCamp.org in Youtube (https://www.youtube.com/watch?v=KJgsSFOSQv0).

After getting accustomed to writing some simple things in C again, I decided to look into APIs I could use in order to create a simple persistence program. Initially, I went to the Microsoft learn website and found what I needed (https://learn.microsoft.com/en-us/windows/win32/api/winbase/). Logically, I needed a function that could retrieve the full path of the exe file (GetModuleFileNameA), a function that would open a handle the registry key where startup items are stored (RegOpenKeyExA), a function that create new values inside the open key (RegSetValueExA, this is where the persistence comes from), have a pop up from the terminal showing that everything is working (lstrcpyA and lstrcatA) and lastly something to close the handle so there would not be any resource leaks (RegCloseKey). We will be covering each of these API’s in more detail further down the lab.

After finding the APIs I encountered the most difficult part of the lab, actually running the code in the VM. Before I even started writing any code, I firstly wanted to install a IDE that could run and compile C files. Normally I would do this with Visual Studio, however this IDE has an online installation technique which would not work in our VM since we do not have access to internet. After some digging i came across this reddit post (https://www.reddit.com/r/C_Programming/comments/123ly5q/c_on_windows_without_visual_studio_basically/) which suggested using minge64 as a compiler, which in my case worked perfectly. I downloaded it through this link (https://github.com/niXman/mingw-builds-binaries/releases/download/15.2.0-rt_v13-rev0/x86_64-15.2.0-release-posix-seh-ucrt-rt_v13-rev0.7z), and then I input the zip file as in ISO directly into the VM, where I extracted it in the :C\ folder straight away so that we could have access to it from any other destination. I also downloaded Notepad++ as a code editor so that I can program easier. I made sure to put thorough comments through each command and explain the logic behind them, as can be seen below.







After writing the code, it was time to execute it, and to execute it we have to first turn the .c file into a .exe file. In order to do so we had to go into cmd and give it the path to the directory we stored the .c file. Afterwards, we had to run this command: gcc -o PersMal3.exe PersMal3.c -ladvapi32 

Gcc stands for the GNU C compiler, which is the translator that converts our high-level code into machine code that the processor understands. -o PersMal3.exe stands for the output and tells the compiler to name the .exe file as PersMal3. PersMal3.c is the source C code, or the original file we wanted to turn into a .exe file. -l stands for link library while advapi32 refers to the advapi32.dll, the compiler looks inside this dll to understand on how to talk to the registry.

After doing all of this we have this result:

To See if the virus truly worked we need to run it and see if it executes. After double clicking it, we got the immediate pop up screen, which gives us a sign of immediate success.

However, in order to truly make sure that this “malware” is true working we need to first head into the task manager, and see if the app is running in the startup apps section. As we can see down below, it is running there just as expected.



To truly confirm that the persistence part of the program is working correctly, we need to go to the registry editor, and reach this address: Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run

After doing so, we need to see our file there, which is the exact case in our scenario as well. 

I also restarted the VM, and we had the same results, which sets the lab as a success.

API Analysis

GetModuleFileNameA è This API essentially asks the Windows OS to identify the full path of the program currently running. In our code, the first parameter is set to Null, which essentially tells windows to give it the path for the current process. It then stores the results in the exePath buffer we created before hand. This is really important since if we can tell the registry what to run at startup we first need to know where the program is found within the disk.

RegOpenKeyExA èThis API goes to the Windows Registry and opens the run folder. Then it uses the HKEY_CURRENT_USER, (since it doesn’t require admin priviledges, and it only affets the user that is logged in). HKEY’s are usually called as hives, and they can be found in the root level of the windows hierarchy.In order to add an entry so that the program runs every time the user logs in, we need to go to Software\Microsoft\Windows\CurrentVersion\Run. Here, the KEY_SET_VALUE gives access to set a new value so that we can add our program in this folder.

RegSetValueExA è This API performs the actual persistence in our code by writing a new entry into the key we just opened. In our code, we name this entry PersMal3, which is also the name which will appear in the Task Manager Startup tab and in the Registry Editor. We also specify REG_SZ to tell the Registry that the data we are writing is a standard string of text. In the end, we pass exePath, which we cas as byte*, as the data. This then creates a permanent link, when windows starts it looks at this entry, it reads the path stored and automatically launces our .exe file.

            IstrcpyA è This API is simply a string manipulation function that we used to begin constructing the “success message”. First I wanted to use stdio.h as another library, but then I remembered that part of this assignment was to strictly stick only with windows APIs. Compared to stdio.h, IstrcpyA takes our empty messageBuffer and copies the initial text string “Bravo Boss” into it. This prepares the buffer so we can add extra info in the following steps.

            IstrcatA è This API glues the two strings together. In our code, we use it twice, first to take the the messageBuffer, and append the exePath variable to the end of it. Then, we use it again to append the instruction “\n\Check Task manager è Startup” to the end. This allows us to built a complete status sentence using native windows functions (essentially it’s a pop-up gimmick but I thought it was an interesting addition to the lab).

            RegCloseKey è To put it simply, this API is used for cleanup. It takes the hKey we created with RegOpenKeyExA and closes it since we do not want to cause any resource leaks or prevent other system processes from accessing that part of the registry properly, since this could alert a defender or crash apps.

Technique Analysis

The persistence mechanism we implemented in PersMal3.exe usese the Registry Run Keys MITRE ATT&CK technique. By changing the HKCU\Software\Microsoft\Windows\CurrentVersion\Run key, our program ensures that explorer.exe executes a payload automatically during the user login.

Some positives of our code would be the stealth user-mode execution method. Since were targeting HKEY_CURRENT_USER, we do not need admin privileges, allowing our program to stay silent without triggering a User Account Control prompt. Our program is also good since it has low dependencies, since it purely uses Win32 API calls.

However, our code is far from perfect. Even though it may not be visible to the UAC, it can easily be seen through the Task Manager or the Registry Editor. The program also has a really high dependency on only a specific current user, and is really fragile since you can just move or delete the PersMal3.exe file and it simply wouldn’t work again.

Detection and Prevention

            As mentioned, defenders can access our persistence method using simple methods such as manual inspection through the Task Manager, or the Registry Analysis. Another tool that we did not mention so far is the Autoruns Tol. This tool is essentially the golden standard for the industry, where it scans all known registry run keys and highlights unverified or unsigned .exe’s set to launch at the startup.

            However, prevention is better than detection. In order to prevent, we can use first registry permissions. This would mean that admins can modify ACLs for the Run keys to be read only for standard users. This prevents any software from adding new startup items without elevating privileges. Additionally, Admins can also use application whitelisting with apps such as Applocker which only allows signed .exes or programs located in protected dirs to run. Finally the 3rd prevention method would be through Endpoint Detection and Response systems, which can be configuted to alert or block processes that A

No comments:

Post a Comment

LAB 10: APK Security Scanner - Multi-Agent Static Analysis pt.2

Taking Android Apps Apart: Building an AI-Powered Security Scanner Part 2: The Analysis, Execution and Findings In Part 1 we defined our obj...