欢迎回来,读了我的关于“在程序中插入对话框”文章后,很多人问我能不能在程序中插入一个启动画面(以下简称为闪屏)。
    是的,这可以做到,你可以对PE文件注入任何东西,只要你的逆向水平够高。
    事实上我正在考虑做这件事情,所以第一步就是考虑需要做些什么,让我们来想想需要做的所有步骤。
    为什么插入一个闪屏就意味着需要做很多工作……
首先,需要创建一个窗口,有三种方法可以实现。
1、你可以增加一个对话框资源,然后呼叫DialogBoxParamA函数,问题是增加一个对话框资源没有那么简单,如果程序没有资源段你还得为它添加资源段,那就更难了。
2、添加代码,那意味着你不得不构造一个WNDCLASSEX结构,呼叫RegisterClassEx和Create WindowEx,并注入对话框循环代码。麻烦的是你必须注入大量的代码,而且需要在输入表中引入要用到的大量的API。
3、我认为最好的办法是在内存中添加对话框窗口(只要构造一个DLGTEMPLATE结构),并且呼叫CreateDialoglndirect。
    另外,你还必须插入一个Windowproc/DialogProc回调函数代码(三个步骤都要),这就意味着需要做更多的工作(想想那些对话框的循环语句)。
    我们的BMP图象又该怎样处理?第一个问题就是它应该存在哪里,这里也有几种方法:
1、将图象资源放入程序的资源段(就象处理对话框资源一样)。
2、不把它放入程序里面,所以你将有两个文件,一个是图象文件,一个PE文件。
3、更好的方法是,复制图象文件的所有字节到一个区段。
    然后在文件中引入图象,并贴在一个窗口中,再设置一个计时器,让闪屏在定义的时间内关闭。
·搜索另一种方法
    我在考虑另一种方法,使我们不用注入这么多代码。
    我在网络上发现了“John Peloquin”写的一个非常好、非常有意思的代码叫做“远程注入补丁”,它是利用CreateProcess远程注入任何一个PE文件的补丁,在目标程序中申请内存空间利用WriteProcessMemory注入你需要的DLL文件,你可以自己看一下源码……
    但是这种方法有两个顾虑:首先,我们现在有三个文件:PE文件、增加闪屏功能的DLL文件,还有个补丁;其次, CreateRemotoThread API函数只能适用于WinNT/2K/XP系统。
    那是不是有不用补丁的方法呢?是的,我们只要写一个DLL文件,它包含闪屏图象,并将代码写入DLLMan函数中的DLL-PROCESS-ATTACH分支,然后在目标文件的输入表中添加这个DLL文件,需要用到DLL的输出功能。
·写DLL文件
    下面是用C语言写的非常简单的一小段DLL代码……
#include <windows.h>   
#include "resource.h"     
#pragma comment(linker,"/ENTRY:DllMain") // 设置DllMain函数入口
extern "C" int Func1(); // 声明输出函数
extern "C" int Func1()  
{
    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)
    {
        case DLL_PROCESS_ATTACH: 
        {
            DialogBoxParamA(hModule, MAKEINTRESOURCE(101), NULL, (DLGPROC)DlgProc, NULL);        }
        break;
        case DLL_PROCESS_DETACH:
        {
         }
        break;
    }
    return TRUE;
}
 
[C用户注意: 不要忘记在源码文件目录下放置.def文件.否则在输出表中将看不到输出函数。代码应该是这样的:
LIBRARY 
EXPORTS 
  Func1 
]
    确实是非常简单的DLL代码,不是吗?图象文件放在对话框窗口中存储到资源中,然后呼叫DialogBoxParam显示对话框窗口,计时器设置为3秒后进入真正的程序,有两点非常重要。
——DialogBoxParamA必须在DLLMain函数中的DLL-PROCESS-ATTACH分支中引用。当程序被加载时,DLL-PROCESS-ATTACH的值发送到DLL。这就是我们所需要的。
——DLL的输出函数我们命名为FuncI,这个函数没什么用,我们从来不去用它,但是它又是必须的因为这个DLL要求必须至少有一个输出函数。
    好了,我希望大家都能清楚每个步骤,如果你不明白再看最后一步。
·最后一步
    现在我们已经做好了我们需要的DLL,让我们看看如何为可执行文件添加闪屏功能,下面是为ProcessView添加闪屏的例子。
    我们都很懒惰,不想手工添加DLL到输入表,所以我们可以用SantMat写的IIDKing来实现,打开IIDKing加载ProcessView,这个实例中,DII的名字是tutsplash.dll,输出函数是FuncI(建议用IIDKing2.01),选中后,按下添加按钮就可以了。
    现在你运行程序就可以看到漂亮的闪屏了,Btw:非常重要的一点,目标文件和DLL文件一定要在同一个目录下。
    我们所做的仅仅是舔加这个DLL到输入表。如果你运行程序,它将会连接输入表中所有的DLL文件。所以ProcessView现在也加载tutsplash.dll并自动发送DLL_PROCESS_ATTACH…
    希望你能够理解相关的联系,知道它的工作原理。所以你现在可以很容易地为程序增加闪屏而不需要复杂的逆向工作。

文:SUNSHINE
译:laomms