吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1172|回复: 12
收起左侧

[C&C++ 原创] 导出表

  [复制链接]
lnterpreter 发表于 2024-3-15 22:42
#include "stdafx.h"
#include <windows.h>
#include "stdlib.h" 

#define FILEPATH_IN "C:/testdll.dll"

DWORD ReadPEFile(IN LPSTR lpszFile,OUT LPVOID* pFileBuffer )
{
    FILE    *pFile      =   NULL;           
    DWORD   fileSize    =   0;          //文件大小
    LPVOID  pTempFileBuffer =   NULL;   //缓冲区首地址

    pFile = fopen(lpszFile,"rb");   //打开文件
    if(!pFile)
    {
        printf("打开文件失败");
        return NULL;
    }

    //读取文件大小
    fseek(pFile,0,SEEK_END);        //将指针从开始的位置移动到末尾
    fileSize = ftell(pFile);        //获取数据大小

    //分配缓冲区(申请内存)
    pTempFileBuffer = malloc(fileSize);
    if(!pTempFileBuffer)
    {
        printf("分配空间失败");
        fclose(pFile);
        return NULL;
    }

    //将文件数据读取到缓冲区
    fseek(pFile,0,SEEK_SET);    //将指针指向开始
    size_t n = fread(pTempFileBuffer,fileSize,1,pFile); //将数据读取到缓冲区中
    if(!n)
    {
        printf("读取数据失败");
        free(pTempFileBuffer);      //释放内存
        fclose(pFile);          //关闭文件
        return NULL;
    }

    //关闭文件
    *pFileBuffer = pTempFileBuffer;
    pTempFileBuffer = NULL;
    fclose(pFile);              //关闭文件
    return fileSize;        
}

//**********************************************************************
DWORD RvaToFoa(IN LPVOID pFileBuffer, IN DWORD dwRva)
{

    PIMAGE_DOS_HEADER           pDosHeader      =   NULL;
    PIMAGE_NT_HEADERS           pNTHeader       =   NULL;
    PIMAGE_FILE_HEADER          pPEHeader       =   NULL;
    PIMAGE_OPTIONAL_HEADER32    pOptionHeader   =   NULL;
    PIMAGE_SECTION_HEADER       pSectionHeader  =   NULL;

    //DOS头
    pDosHeader  =   (PIMAGE_DOS_HEADER)pFileBuffer;
    //NT头地址
    pNTHeader       =   (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer  +   pDosHeader->e_lfanew);
    //标准PE头地址
    pPEHeader       =   (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 0x4);
    //可选PE头地址
    pOptionHeader   =   (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader +   IMAGE_SIZEOF_FILE_HEADER);  
    //第一个节表地址
    pSectionHeader  =   (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader    +   pPEHeader->SizeOfOptionalHeader);

    for(int i=0 ; i < pPEHeader->NumberOfSections ; i++)
    {
        //节在内存中的位置RVA
        DWORD dwSectionBeginRva = pSectionHeader[i].VirtualAddress;
        //节在内存中相对于文件中结束的位置RVA
        DWORD dwSectionEndRva = pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData;
        //判断RVA是否在当前节中
        if(dwRva >= dwSectionBeginRva && dwRva <= dwSectionEndRva)
        {
            //FOA = RVA - 节在内存中的位置 + 节在文件中的偏移
            DWORD dwFoa = dwRva - dwSectionBeginRva + pSectionHeader[i].PointerToRawData;
            return dwFoa;
        }
    }
}

//**********************************************************************
VOID TestPrintExPort()
{
    LPVOID  pFileBuffer     =   NULL;

    DWORD   Size = 0;

    PIMAGE_DOS_HEADER           pDosHeader      =   NULL;
    PIMAGE_NT_HEADERS           pNTHeader       =   NULL;
    PIMAGE_OPTIONAL_HEADER32    pOptionHeader   =   NULL;

    //File-> FileBuffer
    Size = ReadPEFile(FILEPATH_IN,&pFileBuffer);    //调用函数读取文件数据
    if(!pFileBuffer || !Size)
    {
        printf("File-> FileBuffer失败");
        return;
    }

    //获取头信息
    pDosHeader  =   (PIMAGE_DOS_HEADER)pFileBuffer;
    pNTHeader   =   (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
    pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFileBuffer + pDosHeader->e_lfanew + 0x4 + IMAGE_SIZEOF_FILE_HEADER);

    //指向数组
    PIMAGE_DATA_DIRECTORY   pDataDirectory = pOptionHeader->DataDirectory;

    //导出表的地址Rva
    DWORD dwExProtTableRva = pDataDirectory[0].VirtualAddress;
    //导出表的地址Foa
    DWORD dwExProtTableFoa = RvaToFoa(pFileBuffer,dwExProtTableRva);
    //导出表在文件中的地址
    PIMAGE_EXPORT_DIRECTORY PExProtTable = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pFileBuffer + dwExProtTableFoa);

    printf("导出表name:0x%08X\n",PExProtTable->Name);
    printf("导出表Base:0x%08X\n",PExProtTable->Base);
    printf("导出表NumberOfFunctions:0x%08X\n",PExProtTable->NumberOfFunctions);
    printf("导出表NumberOfNames:0x%08X\n",PExProtTable->NumberOfNames);
    printf("导出表AddressOfFunctions:0x%08X\n",PExProtTable->AddressOfFunctions);
    printf("导出表AddressOfNames:0x%08X\n",PExProtTable->AddressOfNames);
    printf("导出表AddressOfNameOrdinals:0x%08X\n",PExProtTable->AddressOfNameOrdinals);

    //将导出表Name、AddressOfNames、AddressOfFunctions、AddressOfNameOrdinals的Rva转换成Foa
    DWORD dwNameFoa                     = RvaToFoa(pFileBuffer,PExProtTable->Name);
    DWORD dwAddressOfNamesFoa           = RvaToFoa(pFileBuffer,PExProtTable->AddressOfNames);
    DWORD dwAddressOfFunctionsFoa       = RvaToFoa(pFileBuffer,PExProtTable->AddressOfFunctions);
    DWORD dwAddressOfNameOrdinalsFoa    = RvaToFoa(pFileBuffer,PExProtTable->AddressOfNameOrdinals);

    //导出表的名字
    PBYTE pDllName = (PBYTE)((DWORD)pFileBuffer + dwNameFoa);
    printf("导出表名%s\n",pDllName);

    //导出函数地址表文件中的位置
    PDWORD pAddressTable = (PDWORD)((DWORD)pFileBuffer + dwAddressOfFunctionsFoa);
    //导出函数序号表文件中的位置
    PWORD pOrdinaTable = (PWORD)((DWORD)pFileBuffer + dwAddressOfNameOrdinalsFoa);
    //导出函数名称表文件中的位置
    PDWORD pNameTable = (PDWORD)((DWORD)pFileBuffer + dwAddressOfNamesFoa);

    //判断是以序号导出还是以名字导出
    BOOL bIndexIsExIst = FALSE;
    for(DWORD i=0 ; i<PExProtTable->NumberOfFunctions ; i++)
    {
        //获取导出函数地址
        printf("RVA的地址:%08X",pAddressTable[i]);
        bIndexIsExIst = FALSE;

        //以导出函数名称表的个数的数量循环
        for(DWORD nNameIndex = 0 ; nNameIndex < PExProtTable->NumberOfNames ; ++nNameIndex)
        {
            //根据导出函数地址的下标,去序号表中找是否存在
            if(i == pOrdinaTable[nNameIndex])
            {
                bIndexIsExIst = TRUE;
                break;
            }   
        }   

        if(bIndexIsExIst == TRUE)
        {
            //序号表中存在,根据序号表的索引,去名称表中找函数名称,获得函数名称表RVA
            DWORD dwNameRva = pNameTable[nNameIndex];

            //将函数名称表RVA转换成存有真实函数名称的文件偏移
            PBYTE pFunName  = (PBYTE)((DWORD)pFileBuffer + RvaToFoa(pFileBuffer,dwNameRva));
            printf(" 函数名[%s]\t",pFunName);
            //获取导出序号
            printf(" 序号[%d]",i + PExProtTable->Base);
        }
        else
        {
            //序号表中不存在,判断是否存在这个函数
            if(pAddressTable[i] != 0)
            {
                //隐藏函数名
                printf(" 函数名:[-]\t");
                printf(" 序号[%d]",i + PExProtTable->Base);
            }
        }
        printf("\n");
    }   
    return;
}

//**********************************************************************
int main(int argc, char* argv[])
{
    TestPrintExPort();
    getchar();
    return 0;
}

免费评分

参与人数 4吾爱币 +5 热心值 +3 收起 理由
wojiushiliu + 1 + 1 热心回复!
lrhdabb + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
prosperity + 1 我很赞同!
wushaominkk + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

caojian1624 发表于 2024-3-16 07:54
谢谢分享
silly123 发表于 2024-3-16 08:13
yaphoo 发表于 2024-3-16 08:26
wl3321589 发表于 2024-3-16 08:51
感谢分享!
turmasi1234 发表于 2024-3-16 09:54
学到了一手
zhufuan 发表于 2024-3-16 10:17
这是C语言的代码吗?
pojielover945 发表于 2024-3-16 10:20
学到了,感谢分享
LeCpp 发表于 2024-3-16 15:26
感谢楼主分享
vulkanhty 发表于 2024-3-16 18:53
谢谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 19:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表