Exploitation is the process of leveraging a weakness in a system, application or configuration in order to obtain a desired outcome.
Although people often associate exploitation exclusively with software vulnerabilities, exploitation is a much broader concept. Any weakness that can be abused to achieve an objective may be exploited.
Exploitation Example
We are going to utilize a custom service for this example.
The service is trusted, but one of its dependencies is writable by a low-privileged user. Since the service repeatedly loads that dependency and executes an exported function from it, control over the DLL becomes control over code executed inside the service process.
I went along and coded a sample custom service in C++:
#include <windows.h>
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE StatusHandle;
HANDLE StopEvent = NULL;
void WINAPI ServiceCtrlHandler(DWORD CtrlCode)
{
if (CtrlCode == SERVICE_CONTROL_STOP)
{
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
SetServiceStatus(StatusHandle, &ServiceStatus);
SetEvent(StopEvent);
}
}
void WINAPI ServiceMain(DWORD argc, LPSTR* argv)
{
StatusHandle = RegisterServiceCtrlHandlerA("AppMonitor", ServiceCtrlHandler);
if (!StatusHandle)
return;
ZeroMemory(&ServiceStatus, sizeof(ServiceStatus));
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
SetServiceStatus(StatusHandle, &ServiceStatus);
StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(StatusHandle, &ServiceStatus);
// ---
// ACTUAL LOGIC IS HERE:
while (WaitForSingleObject(StopEvent, 10000) == WAIT_TIMEOUT)
{
HMODULE library = LoadLibraryA("library.dll");
if (library)
{
FARPROC func = GetProcAddress(library, "LibraryFunction");
if (func)
((void(*)())func)();
FreeLibrary(library);
}
}
// ---
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(StatusHandle, &ServiceStatus);
}
int main()
{
SERVICE_TABLE_ENTRYA ServiceTable[] =
{
{ (LPSTR)"AppMonitor", (LPSERVICE_MAIN_FUNCTIONA)ServiceMain },
{ NULL, NULL }
};
StartServiceCtrlDispatcherA(ServiceTable);
return 0;
}
It does nothing special really (assuming you ignore the boilerplate and focus on the actual logic block):
- Loop forever
- Try to load the DLL "library.dll"
- Try to find the function "LibraryFunction"
- Call the function
- Free the DLL from memory
- Sleep for 10000 ms / 10 seconds
As for the actual DLL:
#include <fstream>
#include <ctime>
extern "C" __declspec(dllexport)
void LibraryFunction()
{
std::ofstream log(
"C:\\Temp\\heartbeat.log",
std::ios::app
);
time_t now = time(nullptr);
char buffer[64];
ctime_s(buffer, sizeof(buffer), &now);
log << buffer;
}
The target function would just manage a log file in C:\Temp\heartbeat.log
We are going to perform a hijack and make it say "Owned".
I've compiled both pieces of code in separate C++ projects (Console Application for the Service and Dynamic-Link-Library for the DLL). I also always keep precompiled headers disabled, but it's not really important right now and it works both ways. Another thing to mention, I always compile in "Release/x64" but that too doesn't really matter too much right now.
I placed the custom service in C:\AppMonitor\LegitService.exe and started it:

I then went ahead and placed the DLL beside it and began seeing outputs every 10 seconds:

Now, suppose the following misconfiguration:
- The folder AppMonitor is only accessible to Administrators (normal Users can only Read/Execute)
- However,
EveryonehasFull Controloverlibrary.dll. - I am currently executing as the user "lowpriv", who is a regular user (on the right-hand side)

To add a new user, you can execute the following command:
# net user username password /add
net user lowpriv lowpriv /add
My option here is very straightforward - I can delete/overwrite the "library.dll" file with my own malicious DLL.
Suppose just for the example's sake we are not going down rabbit-holes exactly right now (we will do that a lot later) and as the unprivileged user we have leveraged our read rights to exfiltrate the service binary and DLL and reverse engineered them. We spot a very obvious vulnerability:
- A process depends on an object and loads it unconditionally
- We have full control of said object
So, we recreate the DLL, but with a malicious payload:
#include <fstream>
extern "C" __declspec(dllexport)
void LibraryFunction()
{
std::ofstream log(
"C:\\Temp\\heartbeat.log",
std::ios::app
);
log << "Owned\r\n";
}
Compile it and get it over on the target.
Note: NEVER completely destroy any artifact or target - ALWAYS make a backup.
![[Chapter I - Foundation/7. The Killchain/6. Exploitation/Exploit.png]]
As you can see from the screenshot, we successfully:
- Backed up the target library
- Overwrote it with "evil_library.dll"
- Log output verified control was established