MemoryModule阅读与PE文件解析(五)----导出表

上一篇我们介绍了TLS。

下面来看关于函数入口函数:

 

// get entry point of loaded library

   if(result->headers->OptionalHeader.AddressOfEntryPoint != 0) {

       if (result->isDLL) {

            DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(code +result->headers->OptionalHeader.AddressOfEntryPoint);

            // notify library about attaching to process

            BOOL successfull =(*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0);

            if (!successfull) {

                SetLastError(ERROR_DLL_INIT_FAILED);

                goto error;

            }

            result->initialized = TRUE;

       } else {

            result->exeEntry = (ExeEntryProc)(LPVOID)(code +result->headers->OptionalHeader.AddressOfEntryPoint);

       }

   } else {

       result->exeEntry = NULL;

}

 

得到函数的入口函数并返回。

另外,如果DLL 中没有定义DllMain函数,链接器将自动填充生成一个只是返回TRUE的默认DllMain函数。

到这里,DLL 的加载就结束了,下面来介绍DLL 的使用:

 

导出函数的调用

 

原本程序中并没有考虑到转发函数的情况,我们首先介绍转发DLL 的原理,然后介绍一份自己实现的函数:

ForwardDll

FORWARD     DLL

/*DEF 文件*/

 

LIBRARY

 

EXPORTS

               Forward=NormalDll.NormalFunc

 

/*.h 声明文件*/

#pragma once

#ifdef       FORWARDDLL

 

#else

 

#define FORWARDDLL                       extern "C" __declspec( dllimport)

 

#endif

 

FORWARDDLL   void           Forward();

 

FORWARDDLL   void           ForwardNormal();

  

 

/*.cpp 实现文件*/

// ForwardDll.cpp: 定义 DLL 应用程序的导出函数。

//

 

#include "stdafx.h"

#include <Windows.h>

#define FORWARDDLL        extern "C" __declspec( dllexport)

#include "ForwardDll.h"

#include "NormalDll.h"

#pragma comment (lib, "NormalDll");

void ForwardNormal ()

{

                MessageBoxA(NULL ,"Success", "ForwardDll",MB_OK );

}

 

#include "ForwardDll.h"

#pragma comment (lib, "ForwardDll")

int _tmain (int argc, _TCHAR * argv[])

{

                Forward();

                ForwardNormal();

                return 0;

}

 

  

 

或者:EXE 动态加载

 

#pragma once

#ifdef       FORWARDDLL

 

#else

 

#define FORWARDDLL                       extern "C" __declspec( dllimport)

 

#endif

 

FORWARDDLL   void           Forward();

 

FORWARDDLL   void           ForwardNormal();

  

 

// ForwardDll.cpp: 定义 DLL 应用程序的导出函数。

//

 

#include "stdafx.h"

#include <Windows.h>

#define FORWARDDLL        extern "C" __declspec( dllexport)

#include "ForwardDll.h"

//#include"NormalDll.h"

//#pragma comment(lib,"NormalDll")

#pragma  comment (linker,"/export:Forward=NormalDll.NormalFunc")

void ForwardNormal ()

{

                MessageBoxA(NULL ,"Success", "ForwardDll",MB_OK );

}

 

 

typedef VOID (*pfnDllFuc)( VOID);

int _tmain (int argc, _TCHAR * argv[])

{

                HMODULE hDll = LoadLibraryA( "ForwardDll.dll");

                if(hDll == NULL ) {

                               ErrorShow();

               } else {

                               pfnDllFuc DllFunc = (pfnDllFuc) GetProcAddress(hDll ,("Forward"));

                               if(DllFunc != NULL) {

                                              DllFunc();

                              }

                               FreeLibrary(hDll );

               }

 

                return 0;

}

我们查看ForwardDll.dll的导出表

 

两个函数对应的四个RVA,Forward函数对应的Function RVA和Name RVA相差很小,且与ForwardNormal 函数的Name RVA差不多,而ForwardNormal的Function RVA 却与其它三个有很大不同,通过查看其指向的内容发现:

如图所示的三个区域对应上述的三个相差不大的三个RVA,中间以00 分开,都指向同一块区域,且都指向以00结尾的字符串。

另外:


我们发现导出表存在于.rdata段中,上述三个区域都存在于导出表中。

而那个不同的段


如图所示属于.text段中。

因此,转发导出函数的函数RVA 指向导出表内部的一个字符串,而普通的导出函数对应的函数RVA 指向的是代码段的一个地址。由此我们可以得到如下获取DLL 导出函数地址的函数:

ULONG_PTR MyGetProcAddress(HMODULE hModule, LPCSTR lpProcName)

{

    int i;

    PIMAGE_DOS_HEADER   pImageDos = (PIMAGE_DOS_HEADER)hModule;

    PIMAGE_NT_HEADERS   pImageNt =(PIMAGE_NT_HEADERS)((ULONG_PTR)hModule + pImageDos->e_lfanew);

    PIMAGE_EXPORT_DIRECTORY pImageExportDirectory= (PIMAGE_EXPORT_DIRECTORY)((ULONG_PTR)hModule + pImageNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

 

    DWORD   dwExportRVA =pImageNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;

    DWORD   dwExportSize =pImageNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;

   

    DWORD*  pAddressOfFunc = (DWORD*)(pImageExportDirectory->AddressOfFunctions+ (DWORD)hModule);

    DWORD*  pAddressOfNames = (DWORD*)(pImageExportDirectory->AddressOfNames+ (DWORD)hModule);

    DWORD   dwNumberOfNames = (DWORD)(pImageExportDirectory->NumberOfFunctions);

    DWORD   dwBase = (DWORD)(pImageExportDirectory->Base);

 

    WORD*   pAddressOfNameOrdinals = (WORD*)(pImageExportDirectory->AddressOfNameOrdinals+ (DWORD)hModule);

 

    ULONG_PTR   dwName = (ULONG_PTR)lpProcName;

    char*       strFunc = NULL;

    char*   pRet = NULL;

    if ((dwName &0xffff0000) == 0)

    {

        goto Ordinal;

    }

    for (i = 0; i < (int)dwNumberOfNames;i++)

    {

        strFunc= (char*)((ULONG_PTR)pAddressOfNames[i]+ (ULONG_PTR)hModule);

        if (strcmp(strFunc, lpProcName) == 0)

        {

            pRet= (char*)((ULONG_PTR)(pAddressOfFunc[pAddressOfNameOrdinals[i]]+ (ULONG_PTR)hModule));

            goto Finish;

        }

    }

Ordinal:

    if (dwName < dwBase|| dwName > dwBase + pImageExportDirectory->NumberOfFunctions)

    {

        //不在导出表的内部,因此是通常的函数

        return (ULONG_PTR)0;

    }

    //得到对应的DLL 和 函数名称,然后递归调用本函数

    pRet= (char*)((ULONG_PTR)pAddressOfFunc[dwName- dwBase] + (ULONG_PTR)hModule);

Finish:

   

    if ((ULONG_PTR)pRet <dwExportRVA + (ULONG_PTR)hModule || (ULONG_PTR)pRet > dwExportRVA + (ULONG_PTR)hModule + dwExportSize)

    {

        return (ULONG_PTR)pRet;

    }

    if ((LONG_PTR)strFunc +(strlen(strFunc) + 1) * sizeof(char) == (LONG_PTR)pRet)

    {

        char* Temp =strchr(pRet, '.');

        if (Temp == NULL)

        {

            //printf("forward 却找不到'.' ");

        }

        char    szNewDll[100];

        //*Temp = 0; 不可写

        for (i = 0; pRet + i< Temp; i++)

        {

            szNewDll[i]= *(pRet + i);

        }

        szNewDll[i]= 0;

        strcat_s(szNewDll,".dll");

        //*Temp = '.';

        HMODULE     h = LoadLibraryA(szNewDll);

        if (h == NULL)

        {

            return (ULONG_PTR)pRet;

        }

        return MyGetProcAddress(h,Temp + 1);

    }

    else

    {

        return (ULONG_PTR)pRet;

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
内存加载动态库 MemoryLoadLibrary 有例子。 /* * Memory DLL loading code * Version 0.0.3 * * Copyright (c) 2004-2013 by Joachim Bauch / mail@joachim-bauch.de * http://www.joachim-bauch.de * * The contents of this file are subject to the Mozilla Public License Version * 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is MemoryModule.h * * The Initial Developer of the Original Code is Joachim Bauch. * * Portions created by Joachim Bauch are Copyright (C) 2004-2013 * Joachim Bauch. All Rights Reserved. * */ #ifndef __MEMORY_MODULE_HEADER #define __MEMORY_MODULE_HEADER #include typedef void *HMEMORYMODULE; typedef void *HMEMORYRSRC; typedef void *HCUSTOMMODULE; #ifdef __cplusplus extern "C" { #endif typedef HCUSTOMMODULE (*CustomLoadLibraryFunc)(LPCSTR, void *); typedef FARPROC (*CustomGetProcAddressFunc)(HCUSTOMMODULE, LPCSTR, void *); typedef void (*CustomFreeLibraryFunc)(HCUSTOMMODULE, void *); /** * Load DLL from memory location. * * All dependencies are resolved using default LoadLibrary/GetProcAddress * calls through the Windows API. */ HMEMORYMODULE MemoryLoadLibrary(const void *); /** * Load DLL from memory location using custom dependency resolvers. * * Dependencies will be resolved using passed callback methods. */ HMEMORYMODULE MemoryLoadLibraryEx(const void *, CustomLoadLibraryFunc, CustomGetProcAddressFunc, CustomFreeLibraryFunc, void *); /** * Get address of exported method. */ FARPROC MemoryGetProcAddress(HMEMORYMODULE, LPCSTR); /** * Free previously loaded DLL. */ void MemoryFreeLibrary(HMEMORYMODULE); /** * Find the location of

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值