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) { 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