Inserting a splash screen into an Exe file (through a dll) - "The easy (lame?) way" - by Sunshine

Download whole package here! (includes original & reversed file and this tut)

Introduction:

Welcome back! A lot of people asked me after they've read my article about inserting a message box at program start of an exe file if it's possible/how to add a splash screen to a PE.
Well, yes it is possible! You can inject (theoretically) everything you want to an exe file, it just depends of your reverse engineering skills! (of your time and of your perseverance :-).
Actually I thought about doing this, so my first step was to think about what is necessary. So let's just think about all the steps...

Why inserting a splash screen means too much work...

Well at first you need a window, so there are 3 possibilities how to create one:
1. You can add a dialog resource and later call it with DialogBoxParamA.
Problem is that it's not that easy to add a dialog to a resource section without messing up the file; it's even harder if the file has no resource section and you have to create one from scratch.
2. You create it with code, that means you have to fill a WNDCLASSEX structure, call RegisterClassEx, call CreateWindowEx and inject a message loop.

Here is the problem that you have to inject a lot of code. Also you need many api functions which are probably not all imported.
3. I think the best way would be to create dialog box template in memory (just fill in a DLGTEMPLATE structure) and call CreateDialogIndirect.

Additionally you have to insert a WindowProc/DialogProc callback function (for all three ways) which also means much work (think about that case-loop for all messages you need to process!)

But what is with our bitmap? First of all where to store it: there are also several ways:
1. Either in the resource section as a bitmap resource (-> same problem as with the dialog box).
2. Just don't put it in the file. So you would have 2 files, the bitmap and the PE file.
3. I would prefer just copying all bytes of the bitmap file into a section.

Then create a bitmap from this file and paint it into the window. A timer will be set up which will close the splash screen after a defined duration.

Searching for another method...

Well I though about another way where we don't have that much code to inject.
I found a very nice and interesting code snippet by John Peloquin called "Remote Library Loader" on the net. It's a loader which executes any target file with CreateProcess, then allocates memory in the address space of this target and copies (or "injects") a dll of your choice (most probably your self-coded one :-) with WriteProcessMemory in it. But have a look yourself at the source code...
But this method has 2 disadvantages for us: First we have now 3 files; our PE file, the dll file where our splash screen resides and the loader. Second this method just runs under WinNT/2K/XP cause of the use of CreateRemoteThread API function.

So is there a method without using a loader? Yes it is :-). We just code a dll containing our splash screen and put the necessary code in the DLL_PROCESS_ATTACH branch at the DllMain function (we come to this later). Then add this dll to the Import Table of our target file. To achieve this, we need a function exported by our dll.
Ok let's go to work...

Coding the dll file

Here now the easy little source code of our dll in C...

#include <windows.h>   // most important include file
#include "resource.h"  // include for our resource     
#pragma comment(linker,"/ENTRY:DllMain") // set entrypoint to DllMain function
extern "C" int Func1(); // forward declaration of export function
extern "C" int Func1()  // our export function
{
    return 0;
}
BOOL DlgProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    DWORD TimerID;

    switch(msg)
    {
        case WM_CLOSE:
        {
            KillTimer(hwnd, TimerID);
            EndDialog(hwnd, 0);
        }
        break;
        case WM_INITDIALOG:
        {
            TimerID = SetTimer(hwnd, 466, 3000, NULL);
        }
        break;
        case WM_TIMER:
        {
            SendMessage(hwnd, WM_CLOSE,0,0);
        }
        break;
        default:break;
}
    return FALSE;
}

      
// :: Dll EntryPoint
BOOL APIENTRY DllMain( HANDLE hModule, DWORD fdwReason,LPVOID lpReserved)
{
switch(fdwReason) { // dll reveives DLL_PROCESS_ATTACH when it's loaded into process address space case DLL_PROCESS_ATTACH: { DialogBoxParamA(hModule, MAKEINTRESOURCE(101), NULL, (DLGPROC)DlgProc, NULL);
} break;
        case DLL_PROCESS_DETACH:
        {

        }
        break;
    }
    return TRUE;
}

[Note for C users: don't forget the .def file in the directory of your source code. Otherwise the export function will not be in the export table of the dll. It should look like:
LIBRARY
EXPORTS
  Func1

]

Well, it's a really simple dll, isn't it? Our dialog window with our bitmap is stored as resource, so a simple DialogBoxParam call does show our window. A timer closes the window after 3 seconds so that the real application starts. The two important points are:
- The DialogBoxParamA call must be in the DLL_PROCESS_ATTACH branch of the DllMain function. The DLL_PROCESS_ATTACH value is sent to the dll when it's loaded into the address space of a process. And that's exactly what we want :-)
- The dummy export function I called Func1. This function does nothing and we never use it! But it's necessary cause our dll must export at least one function.

Well I hope it's clear why we all do this... if not the last step should make it clear :)

The last step

Ok now we have our dll so let's take an exe where we wanna add our nice splash screen. As an example, I use my ProcessView application (Version 1.0).
Cause we are lazy and don't want to add the import to the Import Table by hand, we use IIDKing by SantMat. So fire it up and load ProcessView.exe. Here in our case, the dll name is tutsplash.dll and our dummy export function was Func1. Push the add button and we are finished!
If you know run ProcessView.exe you have a nice Beyonce-Splashscreen. Btw it's important that the exe and the dll file are in the same directory.

What we simply have done is to add the dll to the Import Table. If you run an exe file, it loads all static linked dlls (those in the ImportTable) in its address space. So processview.exe now also loads our tutsplash.dll and automatically sends a DLL_PROCESS_ATTACH to it...

Hope you see know the relation and how it works. So you can easily add splash screens (or whatever) to exe files without "hardcore reversing" :-)

C U soon again!
Questions, criticism? Mail me!

Sunshine, November 2003


This site is part of Sunshine's Homepage