Dll Wrapper: Making our own psapi.dll with .DEF

This tutorial is going to teach you how to make a 'DLL wrapper'. Wrappers are own versions of known DLL's. In this case we're going to make a wrapper of a very known DLL known as PSAPI.DLL. If you don't know it then find the information somewhere XD. But it is about a DLL that is very common to find it loaded in some processes.

The technique of building wrappers has at least 2 objectives:

Hooking: Because our own version of the DLL is going to contain our own versions of the original functions, and at the same time we need to call the originals within ours. What we can do is to execute our code before it gets executed the original code.

Loading a DLL: What we are doing when we create our own version of the known DLL is making the target program to be loaded our DLL in place of the original DLL. This loading it's not made by the target program but by the operating system. The OS detects our DLL in the same location than the executable file of the program and it loads the DLL automatically, since there is dependency with the DLL.

In what fits with security, this technique is not really effective to make a hack for a program which has some kind of security. It would be so easy to validate files on disk, meaning the files that are needed by the program. The validation can be made using MD5 for example.

A file path validation could be also implemented, etc etc but if all this is not for hacking, then it is an attractive idea, at least for educational purposes.

Now about how to create something like this.. well, the first step is to know the original DLL that we wanna replace, meaning all its functions or at least the ones who are used by the target process (dependencies).

This means that we ought to know these functions prototypes, including their calling convention and some. Having that in the first place, we're going to get in mind that we also need to use the original DLL, because we depend on the original functions. This is solved by changing the name of the original DLL. In the case of PSAPI.DLL we can change the name to PSAPI2.DLL.

Then we're going to need to load the original renamed DLL and to make a dynamic linking to it, and to get the addresses of the original functions that we are needing. Obviously we do this with LoadLibrary + GetProcAddress.

After that, in our own DLL we place our hooking functions respecting the prototypes and we place the return addresses of the original functions that we dynamically imported with GetProcAddress.

We obviously use pointers to function for the returns in the hooking functions.

The calling convention used in PSAPI.DLL para its functions is __stdcall, for that, we can make that all functions in our project would be __stdcall by default, so won't need to specify it explicitly in each one of them.

Let's see PSAPI.DLL

Let's take a look at its exports

Let's concentrate in one of its functions for now, as an example EnumProcesses

We need a function prototype, let's define a datatype corresponding to this function

Code:

typedef BOOL (* EnumProcesses_t)(DWORD *,DWORD,DWORD *);

We create a pointer to functions that is going to work as the return to the original function inside the hooking function.

Code:

BOOL (* pEnumProcesses)(DWORD *,DWORD,DWORD *);

Create the hooking functions (See the return is with the pointer to the original)

And basically we do the same with the other functions XD. To compile this project it is required the file psapi.h wich contains the data types used in the hooking functions. it is not requered psapi.lib that is a static linking library.

We are going to need a .DEF file that has to be included to the project. There are rules to implement this .DEF file and they are these:

It has to start with saying LIBRARY and the name of the DLL

After that, it has to say EXPORTS

It has to be placed one by one, the names that we desire for each symbol, following that, an equal sign '=' and the real name of the symbol, which is gotten from the disassembly.

After that, it is left a whitespace and it is placed an 'arroba' and the index number corresponding to the export.

But, let's see an image for better understanding:

Let's see the DLL code:

In main.cpp there are the function prototypes and the pointers to function.
We will look at the example of EnumProcesses

Code:

typedef BOOL (* EnumProcesses_t)(DWORD *,DWORD,DWORD *);

Code:

BOOL (* pEnumProcesses)(DWORD *,DWORD,DWORD *);

then we have the hooking functions. These return a pointer to function.

Then it is shown a code which is about a class and the creation of an object of the type of the class, This makes possible the initialization of the function pointers when the program is executed, more precisely when the object is created.

In exports.cpp there are only the exported functions, which are referenced in the .DEF file. These functions return to the hooking functions. This of having 2 instances is not really necesary as it was stated before, but it is if you wish to implement another method that I will expose later.