首页 > 代码库 > 反病毒攻防研究第009篇:DLL注入(上)——DLL文件的编写

反病毒攻防研究第009篇:DLL注入(上)——DLL文件的编写

一、前言

        我之前所编写的用于模拟计算机病毒的对话框程序都是exe文件,所以运行时必将会产生一个进程,产生进程就非常容易被发现。而为了不被发现,可以选择将对话框程序创建为DLL文件。这种文件会加载到已有进程的地址空间中,这样就不会再次创建出进程,隐蔽性相对较好,DLL注入也是恶意程序总会使用的手段。这次我带算用几篇文章的篇幅来论述DLL注入的问题,而这篇文章就首先来讨论一下如何把我之前的对话框程序改写为DLL文件。

 

二、编写对话框DLL程序

        这里我依旧使用VC++6.0,创建一个简单的Win32 Dynamic Link Library项目,之后系统就会自动为我们生成如下代码:

// HackedDll.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"

BOOL APIENTRY DllMain( HANDLE hModule,              //模块句柄 
                       DWORD  ul_reason_for_call,   //DllMain函数被调用的原因
                       LPVOID lpReserved            //Windows保留参数
                     )
{
        return TRUE;
}

        这里的DllMain函数中的第二个参数表明该DLL被调用的原因。为了针对不同的情况进行处理(比如当进程加载DLL时,进行资源申请的操作,而在卸载该DLL时,进行资源的释放操作),可以按照以下模板所示编写程序:

BOOL APIENTRY DllMain( HANDLE hModule,            //模块句柄 
                       DWORD  ul_reason_for_call, //DllMain函数被调用的原因
                       LPVOID lpReserved          //Windows保留参数
                     )
{
        switch( ul_reason_for_call )
        {
                case DLL_PROCESS_ATTACH:  //当DLL被某进程加载时DllMain被调用
                {
                        break;
                }
                case DLL_PROCESS_DETACH:  //当DLL被某进程卸载时DllMain被调用
                {
                        break;
                }
                case DLL_THREAD_ATTACH:   //进程中有线程被创建时DllMain被调用
                {
                        break;	
                }
                case DLL_THREAD_DETACH:   //进程中有线程结束时DllMain被调用
                {
                        break;
                }
        }
        return TRUE;
}
        根据这个模板,结合我们的目的,创建一个MsgBox函数用于对话框的显示:

void MsgBox()
{
        MessageBox(0,"You have been hacked! (by J.Y.)","Warning",0); 
        return;
}
        然后在主函数的DLL_PROCESS_ATTACH下添加:

case DLL_PROCESS_ATTACH:  //当DLL被某进程加载时DllMain被调用
{
        MsgBox();
        break;
}
        最后在DllMain上方添加一个导出函数:
extern "C" _declspec(dllexport) void MsgBox();

        编译以上的代码,能够生成两个重要的文件,一个是HackedDll.dll,另一个是HackedDll.lib。前者是DLL文件,后者是库文件,库文件中包含着导出函数的相关信息。

 

三、DLL的调用

        对于一个DLL文件,可以选择使用静态调用和动态调用。个人觉得动态调用更加有用,所以这里只讨论动态调用的方法。动态调用的程序如下:
#include <windows.h>

int main()
{
        HINSTANCE hInst;	
        //动态加载DLL
        hInst = LoadLibrary("HackedDll.dll");  
        if (hInst == NULL)
        {
                MessageBox(0, "HackedDll.dll文件不存在", "DLL加载失败", 0);
                return 0;
        }
        typedef void (*PFUNMSG)(); 
        //获取DLL的导出函数
        PFUNMSG pFunMsg = (PFUNMSG)GetProcAddress(hInst, "MsgBox");
        if (pFunMsg == NULL)
        {
                MessageBox(0,"获取函数地址失败", "DLL加载失败", 0);
                return 0;
        }
//      pFunMsg();    
        return 0;
}
        编译生成可执行文件,然后将之前编写好的HackedDll.dll文件与该exe文件放在同一目录下,执行,就可以调用DLL文件中的对话框函数了:

图1 调用DLL

        这里需要说明的是,上述程序中“return0”上面的“pFunMsg()”被我注释起来了,原因是由于我在DLL中的设置是只要DLL被加载,那么MsgBox()函数就会自动被执行,如果“pFunMsg()”不被注释,程序运行中就会执行两次MsgBox()函数。如果我在DLL文件中没有设定加载时启动,那么就应该去掉上述程序中的注释。

 

四、用PEiD查看DLL文件

        在逆向工程中,PEiD这款软件经常会被使用到,因为运用它可以查看PE文件的结构。而DLL文件也属于PE文件。这里我把HackedDll.dll文件拖拽到PEiD的界面上,它就会自动解析出该DLL文件的PE结构,如图所示:


图2 用PEiD查看DLL文件结构

        在这里可以看到该文件是由VC6开发的,属于DLL文件。单击“Subsystem”右边的“>”按钮,打开“PE Details”界面,在“Directory Information”中单击“ExportTable” 右边的“>”按钮,就可以打开“Exports Viewer”。由于我所编写的DLL文件中只有一个导出函数MsgBox(),那么该导出表中就只有一个导出项。如下图所示:


图3 查看导出项

        当以后编写比较复杂的DLL文件时,用PEiD这款软件就能够很清晰地看出整个程序的内部元素。在整个《反病毒攻防研究》系列中,会多次使用到这个程序。而在以后的《安全类软件编写》系列中,也会尝试编写一个类似的程序。 

 

五、DLL注入的查杀方法

        由于DLL是要依托于其它进程才能够“存活”的,所以是不能够用正常手段(比如在cmd下)进行查杀的。所以这里我打算采用Icesword(冰刃)这款软件。

        首先运行TestMain.exe程序用于加载HackedDll.dll,此时弹出对话框(如图1所示),然后打开冰刃,选择“进程”,就能够列出目前系统中的所有进程项。找到TestMain.exe,在它上面单击右键,在弹出的菜单中选择“模块信息”,就能够查看与该进程相关的所有模块,如图所示:


图4 利用冰刃查看模块信息

        这里可以在选中“HackedDll.dll”后,选择“卸载”或者“强制卸载”,那么这个DLL文件就会从“模块信息”中消失。此时之前弹出的对话框并没有变化,但是当单击对话框中的“确定”按钮后,就会弹出“DLL加载失败”对话框:


图5 DLL成功卸载

        这正是我之前的程序中用于错误处理的程序,这也就说明了,该DLL文件的确已经成功卸载。之后就可以依据图4中显示出的该DLL的路径,删掉该DLL文件就可以了。

 

六、小结

        这次编写了一个DLL版的模拟病毒程序,在以后的研究中会多次用到。可见DLL程序并不难编写,重要的还是一套流程,按照“模板”编写就可以了。可以说,随着DLL研究的开展,我们的技术研究也渐渐步入了中级阶段。

反病毒攻防研究第009篇:DLL注入(上)——DLL文件的编写