Importing A DLL Function Into Notepad

In Part 3, we will explore how to write a DLL with an exportable function, then modify notepad's import table so that the function is imported when notepad is run. As in Part 1, we will simply make notepad beep when it is loaded. Calling a function from a DLL instead of adding all the code directly to the executable has several advantages:

1) You only need enough extra space in the executable to call your function, which as you will see, is only a few bytes.
2) The DLL can be written in a higher level language such as C, making it easier and faster to create, debug, and add your code.
3) Very little assembly knowledge is needed; in fact, we will use less assembly here than we did in Part 1.

Tools/Resources Used

[~] Dev-C++ - Graphical GNU C/C++ compiler used to create the DLL
[~] LordPE - Used to view and modify notepad's PE headers
[~] OllyDbg - Our debugger, same as in the previous tutorial

Creating The DLL

We will begin by writing a DLL with an importable function, i.e., one which can be imported at run time by an executable and later called by the executable's code. I will be using Dev-C++ (GNU compiler), but the code should be basically the same if you are using VC++.

In Dev-C++, create a new project, name the procject 'Project1' and select DLL and 'C Project':

This will produce two files, dllmain.c and dll.h; first take a look at dll.h. The important line to look at in this case is: # define DLLIMPORT __declspec (dllexport). This means that any function proceeded by 'DLLIMPORT' will be importable. If you switch over to dllmain.c, Dev-C++ has provided us with a sample function (you can actually go ahead and remove the DllMain function as we will not be using it):


DLLIMPORT void HelloWorld ()
{
MessageBox (0, "Hello World from DLL!\n", "Hi", MB_ICONINFORMATION);
}

We will change the MessageBox API call to MessageBeep so that when our imported function is called, it will in turn call MessageBeep:


DLLIMPORT void HelloWorld ()
{
MessageBeep(MB_OK);
}

Now compile the project and copy the resulting DLL file (Project1.dll) into the same directory as your copy of notepad.

Adding The Function To The Import Table

Next, we have to tell notepad to import this function from our DLL and determine the address of the function so that we can call it from notepad. Open LordPE, click on 'PE Editor' and open your copy of notepad. Note the Image Base (01000000), and click on 'Directories'. Click on the '...' button next to the "Import Table" line. This brings up an Import Table window which allows you to view all the functions imported into the executable and which DLL's they are imported from. We need to add our DLL to the list, so 'Right Click -> Add Import':

Enter the DLL and function names and click the '+' button:

Click OK and take a second look at the Import Table window. Scroll down to the bottom and select your DLL to view the imported functions for that DLL (note that my DLL and function names differ in this screen shot as it is from a different program):

Note the value of ThunkRVA is 0001409E. This is the offset from the image base at which our function is located, so to get the actual address that we need to call in order to start our function we add the image base value to the FirstThunk value:

 01000000
+ 0001409E
----------
0101409E

Calling The Imported Function

We will use the same procedure we used in Part 1 to add our code to notepad and execute it, so I will not go into details for most of the following code; if you need more explanations, refer back to Part 1.

Open up notepad in Olly and change the 'CALL 01007568' to 'JMP 0100874A', then go to 0100874A and enter the following code (screenshot here):
pushad
pushfd
call dword ptr [0101409E] <--- Call to our HelloWorld function
popfd
popad
call 01007568
jmp 010073a9

Save your changes and run notepad and you will be greeted with another beep.

Conclusion

As in Part 1, adding a beep isn't very useful, but the ability to write a function in a higher-level language cuts down on production time and allows you to add unlimited amounts of code without changing/adding PE header sections. Finally, in Part 4, we will be using this technique to help us add plugin functionality so that it is easy to write and add extensions to notepad.

Copyright 2006 craigheffner.com