Meditation, The Art of Exploitation

Thinking? At last I have discovered it--thought; this alone is inseparable from me. I am, I exist--that is certain. But for how long? For as long as I am thinking. For it could be, that were I totally to cease from thinking, I should totally cease to exist....I am, then, in the strict sense only a thing that thinks.

Tuesday, May 16, 2006

Build DLL (dynamic linked library) with microsoft visual studio

This article explains how to work with the default microsoft VC 6.0 IDE to compile DLL output from a given c code. It also shows how to use this dll within another given c code.

Let's say you have 3 files, a_main.c, a_dll.c, and a_comm.h. Both .c files use the .h header files. Let's first generate a_dll.dll from a_dll.c. Double click a_dll.c in windows should automatically open a_dll.c within the VC IDE. If this is not the case, you need to associate .c files with VC ide. Next try to compile a_dll.c, at this point, VC will create a workspace template file for you. Now this is the point where you need to make changes to the default workspace/project settings so that instead of linking and producing a EXE file, a DLL file is generated. First set active configuration to win32 release, then open project/settings diaglog. Click on c/c++, this is the compilation settings. You need to put the following defines in the "preprocessor definitions" textfield, _USRDLL and A_DLL_EXPORTS. _USRDLL tells the compiler-preprocessor that this file is intended to be compiled into a DLL file. A_DLL_EXPORTS tells the compiler that this file as DLL exports symbols. A_DLL_EXPORTS is a instantiate of FILENAME_EXPORTS, because we are working with a_dll.c here, we replace FILENAME with A_DLL. If the file was named b_dll.c, we'd have used B_DLL_EXPORTS.

There is another flag _WINDOWS that needs to be added depending on the nature of the DLL. If the DLL has any USR32.DLL imports, working with GUI components, then we must replace the default _CONSOLE flag to _WINDOWS. The VC default project template settings assumes a win32 console application is being compiled. So use either _WINDOWS or _CONSOLE depending on what kind of DLL you are working with. Save your settings change by click on "Ok" button. At this point, a_dll.c should be compiled and seen to produce a_dll.obj without any problem.

Next we must modify the settings that used during VC linking process. The object code is linked with other libraries to produce either a EXE file or a DLL file. The default template project settings will link to a win32 console EXE file. Open the project/settings dialog again in VC and choose the "link" tab. In "Output filename" text field, change a_dll.exe to a_dll.dll. This change tells the linker we desire a dll output from the source code a_dll.c. If you didn't change this and go ahead compiling/linking your code, VC will complain it cannot find "main" or "winmain" function because as a dll source code, a_dll.c contains the dllmain entry instead of main for a console app or winmain for a windows app. In the "Project Options" textarea, get to the end of the option string and add "/dll", this again tells the linker to produce a dll output instead of a exe output.

The last step again depends on what kind of dll it is, console or windows. You don't have to do anything else if it's a console dll because the default setting assumes it's creating a console dll. Otherwise in "Project Options", find "/subsystem:console" and replace it with "/subsystem:windows". Click "Ok" to save the changes and in "Build" menu, you should see the target output has changed from a_dll.exe to a_dll.dll. You should be able to create the desired a_dll.dll now.

Granted, this seems to be a lot of hassle to get VC to generate DLL output from a source code file. This would have been very easy if we could have started from the project wizard and was using a win32 dll template from day 1. But occasionally one cannot always expect a project build configuration is available with a downloaded or copied source code and we have to build a dll file using what we have at hand. The trick I explained above demonstrates the step by step changes to the default project settings to genreate a dll file.

Now onto the next step building a.exe using the newly generated a_dll.dll. Again load a.c into VC and let VC generate a default project template file to work with. If you would try to build a.exe now, VC would complain missing functions in a_dll.c during link. To fix this, open Project/Settings, and go to link tab. In Object/library modules text, go to the end of the list and type in PATH_TO_A_DLL_LIB\a_dll.lib. Here PATH_TO_A_DLL_LIB is the path to a_dll.lib file. For example, if you have organized your files in c:\myfiles. PATH_TO_A_DLL_LIB would be Release or Debug depending on what build configuration was used when a_dll.dll was built. This is the only change you need to make to link a.obj with a_dll.lib to generate the final product: a.exe.

It's interesting to note that the compiler actually links a.obj with a_dll.lib instead of a_dll.dll to build a.exe. a_dll.dll is only used when a.exe is running in the system, as it's name implied dynamic link library.