DLL Injection with Delphi
Darian Miller - Nov/2019
Darian Miller - Nov/2019
[SHOWTOGROUPS=4,20]
I had recently spent some time playing around with the simple to use DelphiDetours package from Mahdi Safsafi
Для просмотра ссылки Войдиили Зарегистрируйся
One missing feature is the ability to inject a DLL into an external process. This is something that I wanted to do for a project that I am currently working on, so I started doing some reading. To me, the topic always seemed to be a Black Art, and something left for the assembly language developers to use, but it turns out to be much more widely accessible and fairly easy to do.
I added a few routines to my dxLib open source project on GitHub to assist with the DLL injection task:
Для просмотра ссылки Войдиили Зарегистрируйся
I also put a new repository online yesterday, initially containing Delphi projects to create an example custom DLL, a basic victim process, and an example DLL Injector. This repo can be found at:
Для просмотра ссылки Войдиили Зарегистрируйся
The screen shot below demonstrates a successful detour of a simple MessageBox call utilizing the projects from the dxInjectionDetours repo:
Sample Windows API method intercepted
Define which ProcessID to target
First, I wanted to offer a list of running processes, so the user can simply select a DLL injection target from a list. There's a new dxLib_ProcessList unit with a simple TdxProcessEntryList class which can be populated with a call to its SnapShotActiveProcesses method:
The list is generated using the Kernel32.dll API method: Для просмотра ссылки Войдиили Зарегистрируйся and related helper routines. It's a quick snapshot of active processes (along with heaps, modules and threads used...which I may extend later.) You can use the related Для просмотра ссылки Войди или Зарегистрируйся and Для просмотра ссылки Войди или Зарегистрируйся API methods to build a list of Для просмотра ссылки Войди или Зарегистрируйся items that contain interesting entries like ProcessID, ParentProcessID, and ExeFile name. One potential problem is the ExeFile provided is just the file name without the full path.
You actually do not need the full path name to inject a DLL, but I thought it was a nice feature to add to the demo so I added an optional parameter to utilize another Kernel32 API method QueryFullProcessImageName which returns the full path name of a given process. There are two versions of this method available, one Для просмотра ссылки Войдиили Зарегистрируйся and one Для просмотра ссылки Войди или Зарегистрируйся.
Since I'm using this in a loop, to cache the calls to GetModuleHandle/GetProcAddress, there was a utility class created (TdxProcessNameToId) and a simple method to return the full path name for a given ProcessID:
Note that this method calls OpenProcess with the PROCESS_QUERY_LIMITED_INFORMATION access right, which provides a subset of information. This reduced access grants further calls to QueryFullProcessImageName (along with GetExitCodeProcess, GetPriorityClass, and IsProcessInJob.)
Note: OpenProcess will fail on some system processes.
Since some system processes will generate errors, the SnapshotActiveProcesses method simply skips over them. There typically no good reasons to be sniffing into these system processes anyway. (If you need that, then you should get out of User Land and get yourself into Kernel mode.)
We now have a simple routine to easily get a full list of active processes for a user to select from, which will provide a specific ProcessID to target.
Create a custom DLL to inject
The interesting part of this task involves creating the DLL which contains our API hook, intercept, detour, or the terminology of your choice. Using the DelphiDetours package, it's really simple to do.
Remember to 'match your bitness' - create a 32-bit DLL to inject into a 32-bit process, and a 64-bit DLL for a 64-bit process.
There is a long history of DLL support in Delphi. Unfortunately, there's not a lot of documentation provided for some areas. For example, if you look up the DLLProc global variable, you likely won't find much. Fortunately, there is a succinct Для просмотра ссылки Войдиили Зарегистрируйся response by Sertac Akyuz which explains basic usage:
We set this DLLProc system variable and call it ourselves with DLL_PROCESS_ATTACH. This is the .DPR source for an example DLL:
We then need to define CreateIntercepts() and RemoveIntercepts() in our custom implementation unit as in the example below. DelphiDetours does most of the heavy lifting. We just need to define which API calls to intercept and what to replace them with.
In this example, we're going to replace the two variations of MessageBox with our own custom implementation. For this very simple example, we will call the intercepted (original version) MessageBox with our custom message and caption whenever the target process calls MessageBox:
Thanks to DelphiDetours, this isn't a Black Art at all (at least in our code...DelphiDetours is certainly full of magic.) The major caveat is to ensure that the API method definition exactly matches the original. It's best to utilize the Delphi-provided definitions whenever possible (like those found in the Windows.pas file.)
We now have a DLL ready to inject into a target process!
[/SHOWTOGROUPS]
I had recently spent some time playing around with the simple to use DelphiDetours package from Mahdi Safsafi
Для просмотра ссылки Войди
One missing feature is the ability to inject a DLL into an external process. This is something that I wanted to do for a project that I am currently working on, so I started doing some reading. To me, the topic always seemed to be a Black Art, and something left for the assembly language developers to use, but it turns out to be much more widely accessible and fairly easy to do.
I added a few routines to my dxLib open source project on GitHub to assist with the DLL injection task:
Для просмотра ссылки Войди
I also put a new repository online yesterday, initially containing Delphi projects to create an example custom DLL, a basic victim process, and an example DLL Injector. This repo can be found at:
Для просмотра ссылки Войди
The screen shot below demonstrates a successful detour of a simple MessageBox call utilizing the projects from the dxInjectionDetours repo:
Sample Windows API method intercepted
Define which ProcessID to target
First, I wanted to offer a list of running processes, so the user can simply select a DLL injection target from a list. There's a new dxLib_ProcessList unit with a simple TdxProcessEntryList class which can be populated with a call to its SnapShotActiveProcesses method:
The list is generated using the Kernel32.dll API method: Для просмотра ссылки Войди
You actually do not need the full path name to inject a DLL, but I thought it was a nice feature to add to the demo so I added an optional parameter to utilize another Kernel32 API method QueryFullProcessImageName which returns the full path name of a given process. There are two versions of this method available, one Для просмотра ссылки Войди
Since I'm using this in a loop, to cache the calls to GetModuleHandle/GetProcAddress, there was a utility class created (TdxProcessNameToId) and a simple method to return the full path name for a given ProcessID:
Note that this method calls OpenProcess with the PROCESS_QUERY_LIMITED_INFORMATION access right, which provides a subset of information. This reduced access grants further calls to QueryFullProcessImageName (along with GetExitCodeProcess, GetPriorityClass, and IsProcessInJob.)
Note: OpenProcess will fail on some system processes.
Since some system processes will generate errors, the SnapshotActiveProcesses method simply skips over them. There typically no good reasons to be sniffing into these system processes anyway. (If you need that, then you should get out of User Land and get yourself into Kernel mode.)
We now have a simple routine to easily get a full list of active processes for a user to select from, which will provide a specific ProcessID to target.
Create a custom DLL to inject
The interesting part of this task involves creating the DLL which contains our API hook, intercept, detour, or the terminology of your choice. Using the DelphiDetours package, it's really simple to do.
Remember to 'match your bitness' - create a 32-bit DLL to inject into a 32-bit process, and a 64-bit DLL for a 64-bit process.
There is a long history of DLL support in Delphi. Unfortunately, there's not a lot of documentation provided for some areas. For example, if you look up the DLLProc global variable, you likely won't find much. Fortunately, there is a succinct Для просмотра ссылки Войди
We set this DLLProc system variable and call it ourselves with DLL_PROCESS_ATTACH. This is the .DPR source for an example DLL:
We then need to define CreateIntercepts() and RemoveIntercepts() in our custom implementation unit as in the example below. DelphiDetours does most of the heavy lifting. We just need to define which API calls to intercept and what to replace them with.
In this example, we're going to replace the two variations of MessageBox with our own custom implementation. For this very simple example, we will call the intercepted (original version) MessageBox with our custom message and caption whenever the target process calls MessageBox:
Thanks to DelphiDetours, this isn't a Black Art at all (at least in our code...DelphiDetours is certainly full of magic.) The major caveat is to ensure that the API method definition exactly matches the original. It's best to utilize the Delphi-provided definitions whenever possible (like those found in the Windows.pas file.)
We now have a DLL ready to inject into a target process!
[/SHOWTOGROUPS]