远程线程注入(一)编写动态链接库

转自:http://blog.csdn.net/gaoxin1076/article/details/8112767

原文使用Codeblocks编译不通过,好几个类型不兼容

而且DLL导出函数的参数类型在原型 和 实现中不一致:

原型:__declspec(dllexport) DWORD ExportExample(LPSTR sMsg, DWORD dwCode); 

实现:DWORD ExportExample(LPWSTR szMsg, DWORD dwCode){……}

虽然Codeblocks能编译通过,但是使用Depends查看DLL导出函数名时,会被C++编译器添加一些修饰,

导致下面这句根据DLL导出函数名获得导出函数地址的语句返回NULL,无法动态加载DLL导出函数

lpProcAdd = (MY_EXPORT_PROC)GetProcAddress(hinstLib, "ExportExample");

好了,贴上我修改后的代码,在Codeblocks上完美编译

DLL的头文件:

#ifndef __MAIN_H__
#define __MAIN_H__

#include <windows.h>
//#include <psapi.h>
//#pragma comment(lib, "psapi.lib")

#ifdef BUILD_DLL
    #define DLL_EXPORT __declspec(dllexport)
#else
    #define DLL_EXPORT __declspec(dllimport)
#endif


#ifdef __cplusplus
extern "C"
{
#endif

DLL_EXPORT DWORD ExportExample(LPSTR sMsg, DWORD dwCode);

#ifdef __cplusplus
}
#endif

#endif // __MAIN_H__

 

DLL入口函数和导出函数实现:

#include "main.h"

//导出函数,显示消息
DLL_EXPORT
    DWORD ExportExample(LPSTR szMsg, DWORD dwCode)
    {
        LPVOID lpShowOut = HeapAlloc(GetProcessHeap(), HEAP_NO_SERIALIZE, lstrlen((LPCSTR)szMsg) + 100);

        wsprintf((LPSTR)lpShowOut, "%s,%d", szMsg, dwCode);

        MessageBox(NULL, (LPCSTR)lpShowOut, "由导出函数弹出的消息! ", MB_OK);

        HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpShowOut);

        return 0;
    }



extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            // attach to process
            {
                TCHAR lpMainMoudleName[MAX_PATH];
                TCHAR lpMessage[MAX_PATH + 64];

                //获取PID和主模块名,将弹出消息框
                DWORD dwPID = GetCurrentProcessId();

                //GetModuleBaseName(GetCurrentProcess(), NULL, lpMainMoudleName, MAX_PATH);
                GetModuleFileName(NULL, lpMainMoudleName, MAX_PATH);

                wsprintf(lpMessage, "process name: %s, PID: %u ", lpMainMoudleName, dwPID);
                MessageBox(NULL, lpMessage, "msg.dll", MB_OK);
            }
            break;

        case DLL_PROCESS_DETACH:
            // detach from process
            break;

        case DLL_THREAD_ATTACH:
            // attach to thread
            break;

        case DLL_THREAD_DETACH:
            // detach from thread
            break;
    }
    return TRUE; // succesful
}

 

然后我们来分析一下代码:

这是个导出函数的声明,声明了这个函数是从dll中导出的函数

DLL_EXPORT DWORD ExportExample(LPSTR sMsg, DWORD dwCode);

 

接下来是dll的主函数入口,跟main 和WinMain 差不多,它是DllMain

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)

 

fdwReason可以是下面四个值:

DLL_PROCESS_ATTACH  :附加进程

DLL_PROCESS_DETACH  :分离进程

DLL_THREAD_ATTACH    :附加线程

DLL_THREAD_DETACH    :分离线程

 

本例子中的代码是这样的,在DLL_PROCESS_ATTACH的时候执行下面的代码:

case DLL_PROCESS_ATTACH:
            // attach to process
            {
                TCHAR lpMainMoudleName[MAX_PATH];
                TCHAR lpMessage[MAX_PATH + 64];

                //获取PID和主模块名,将弹出消息框
                DWORD dwPID = GetCurrentProcessId();

                //GetModuleBaseName(GetCurrentProcess(), NULL, lpMainMoudleName, MAX_PATH);
                GetModuleFileName(NULL, lpMainMoudleName, MAX_PATH);

                wsprintf(lpMessage, "process name: %s, PID: %u ", lpMainMoudleName, dwPID);
                MessageBox(NULL, lpMessage, "msg.dll", MB_OK);
            }
            break;

代码很简单,获得进程ID并且用对话框的方式显示出来。

 

接下来我们看看导出函数:

//导出函数,显示消息
DLL_EXPORT
    DWORD ExportExample(LPSTR szMsg, DWORD dwCode)
    {
        LPVOID lpShowOut = HeapAlloc(GetProcessHeap(), HEAP_NO_SERIALIZE, lstrlen((LPCSTR)szMsg) + 100);

        wsprintf((LPSTR)lpShowOut, "%s,%d", szMsg, dwCode);

        MessageBox(NULL, (LPCSTR)lpShowOut, "由导出函数弹出的消息! ", MB_OK);

        HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, lpShowOut);

        return 0;
    }

导出函数也很简单,就是弹出一个对话框。这个没什么好说的,加载了动态链接库之后我们就可以直接使用这个dll中的接口函数了。

 

然后我们简单的重新写个代码测试一下这个dll的正确性:

#include <stdio.h>
#include <windows.h>

typedef DWORD (*MY_EXPORT_PROC)(LPSTR, DWORD);

int main(void)
{
    HINSTANCE hinstLib;
    MY_EXPORT_PROC lpProcAdd;
    BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;

    //获得DLL模块句柄
    hinstLib = LoadLibrary(TEXT("msg.dll"));

    //是否加载成功
    if (hinstLib != NULL)
    {
        //获得指定导出函数的地址
        lpProcAdd = (MY_EXPORT_PROC)GetProcAddress(hinstLib, "ExportExample");

        //判断是否成功
        if (lpProcAdd != NULL)
        {
            fRunTimeLinkSuccess = TRUE;
            (lpProcAdd) (TEXT((LPSTR)("hello")), 123);
        }
        //释放dll
        fFreeResult = FreeLibrary(hinstLib);
    }

    if (!fRunTimeLinkSuccess)
        printf("error; %u\n", GetLastError());

    return 0;
}

这里使用的是显示连接调用DLL,只需要一个DLL文件既可,一定要保证用Depends查看的导出函数名没有添加任何修饰。

使用这种方法的话,直接在LoadLibrary之后直接获得了导出函数的地址:

//获得指定导出函数的地址
        lpProcAdd = (MY_EXPORT_PROC)GetProcAddress(hinstLib, "ExportExample");

然后我们测试一下,发现成功弹出了dll中的两个对话框~~~!!

OK,第一步我们先到这里了,接下来就是伟大的远程线程注入了,哈哈。

posted @ 2013-09-27 14:23  瓶哥  Views(359)  Comments(0Edit  收藏  举报