提交 74781f6c 创建 作者: 赵鹏翀's avatar 赵鹏翀

init template

上级
/Debug
/Release
\ No newline at end of file
<?xml version="1.0" encoding="gb2312"?>
<ASMProject Version="1.00" Name="Demo036" TemplatePath="Lab013\Project" ProjectID="f83d8a47-242f-428a-a542-bce2d012d268" IsSubmitWork="0">
<Configurations>
<Configuration Name="Debug" DebuggerFlavor="0">
<Tool Name="PreBuildEventTool"/>
<Tool Name="CustomBuildTool"/>
<Tool Name="GCCCompilerTool" PreprocessorDefinitions="_DEBUG" GenerateDebugInformation="-1" LanguageStandard="c99"/>
<Tool Name="PreLinkEventTool"/>
<Tool Name="GCCLinkerTool"/>
<Tool Name="PostBuildEventTool"/>
</Configuration>
<Configuration Name="Release" DebuggerFlavor="0">
<Tool Name="PreBuildEventTool"/>
<Tool Name="CustomBuildTool"/>
<Tool Name="GCCCompilerTool" PreprocessorDefinitions="NDEBUG" LanguageStandard="c99"/>
<Tool Name="PreLinkEventTool"/>
<Tool Name="GCCLinkerTool" StripDebugInfo="-1"/>
<Tool Name="PostBuildEventTool"/>
</Configuration>
</Configurations>
<Files>
<Filter Name="ͷļ" Filter="h;hpp;hxx">
<File RelativePath=".\console.h">
</File>
</Filter>
<Filter Name="Դļ" Filter="cpp;c;cc;cxx">
<File RelativePath=".\console.c">
</File>
<File RelativePath=".\PEdump.c">
</File>
</Filter>
</Files>
</ASMProject>
添加文件
// PEDUMP.cpp : 定义控制台应用程序的入口点。
//
/*
PE 文件的大致布局
+------------------------------+ File offset 0
| DOS Header |
| PE_IMAGE_DOS_HEADER |
+------------------------------+
| DOS Stub |
---------+------------------------------+
/ | PE Signature (PE\0\0) |
| +------------------------------+
| | PE_IMAGE_FILE_HEADER |
PE_IMAGE_NT_HEADERS +------------------------------+--------\
| | | |
| | | PE_IMAGE_OPTIONAL_HEADER
| +------------------------------+ |
\ | Data Directory | |
---------+------------------------------+--------/
| Section Table |
| PE_IMAGE_SECTION_HEADER array|
+------------------------------+
---------+------------------------------+ File align
/ | .text |
| +------------------------------+
| +------------------------------+
| | .data |
| +------------------------------+
| +------------------------------+
Sections | .edata |
| +------------------------------+
| +------------------------------+
| | .idata |
| +------------------------------+
| +------------------------------+
\ | .reloc |
---------+------------------------------+
......
+------------------------------+
| COFF Line Numbers (Optional) |
+------------------------------+
| COFF Symbols (Optional) |
+------------------------------+
| CodeView Debug Information |
| (Optional) |
+------------------------------+
*/
#include "console.h"
// 全局变量
FILE* g_pFile; // PE 文件
PE_IMAGE_DOS_HEADER g_DosHeader;
PE_IMAGE_NT_HEADERS g_NTHeaders;
PE_IMAGE_SECTION_HEADER* g_pSectionTable = NULL;
PE_IMAGE_EXPORT_DIRECTORY* g_ExportDir = NULL;
PE_IMAGE_IMPORT_DESCRIPTOR* g_ImportDsr = NULL;
// 主函数
int main(int argc, char* argv[])
{
// 打开 PE 文件
g_pFile = fopen("PEdump.exe", "rb");
if(NULL == g_pFile)
{
printf("Open file failed!\n");
return 1;
}
// 读取 DOS 头
ReadDosHeader();
// 读取 NT 头
ReadNTHeader();
// 读取 section table
ReadSectionTable();
// 读取 Import Table
ReadImportTable();
// 关闭 PE 文件
fclose(g_pFile);
return 0;
}
添加文件
#include "console.h"
int SectionCnt; // 保存节的数量
DWORD dwExportVA, dwExPointerToRawData; // 保存导出表,导入表的地址信息
DWORD dwImportVA, dwImPointerToRawData;
// 虚拟地址到文件中的位置转换程序
DWORD OnConvertVAToRawA(DWORD dwTransVA, DWORD dwSectionVA, DWORD dwPointerToRawData)
{
// 将两个虚拟地址做差,求出偏移量,再加上所在节的PointerToRawData即可将虚拟地址转换成文件中的位置
// 将转换好的地址返回
return dwTransVA - dwSectionVA + dwPointerToRawData;
}
void ReadDosHeader()
{
// DOS Header 在文件开始处
fseek(g_pFile, 0, SEEK_SET);
fread(&g_DosHeader, sizeof(g_DosHeader), 1, g_pFile);
// 判断DOS头是否合法
if(g_DosHeader.e_magic != 0x5A4D)
{
printf("DOS头不合法!\n");
exit(1);
}
// 打印
printf("****** DOS Header ******\n");
printf("magic: %.4s\n", (CHAR*)&g_DosHeader.e_magic);
printf("e_lfanew: 0x%X\n\n",g_DosHeader.e_lfanew);
}
void ReadNTHeader()
{
// DOS Header 中的 e_lfanew 存储了 NT Header 相对文件起始的偏移值
fseek(g_pFile, g_DosHeader.e_lfanew, SEEK_SET);
fread(&g_NTHeaders, sizeof(g_NTHeaders), 1, g_pFile);
// 判断是否为有效PE文件
if(g_NTHeaders.Signature != 0x4550)
{
printf("不是有效的PE文件!\n");
exit(1);
}
// 保存节的数量
SectionCnt = g_NTHeaders.FileHeader.NumberOfSections;
// 打印
printf("****** NT Header ******\n");
printf("Signature: %.4s\n", (CHAR*)&g_NTHeaders.Signature);
printf("NumberOfSections: %d\n", g_NTHeaders.FileHeader.NumberOfSections);
printf("SizeOfOptionalHeader: 0x%X\n", g_NTHeaders.FileHeader.SizeOfOptionalHeader);
printf("AddressOfEntryPoint: 0x%X\n", g_NTHeaders.OptionalHeader.AddressOfEntryPoint);
printf("BaseOfCode: 0x%X\n", g_NTHeaders.OptionalHeader.BaseOfCode);
printf("BaseOfData: 0x%X\n", g_NTHeaders.OptionalHeader.BaseOfData);
printf("ImageBase: 0x%X\n", g_NTHeaders.OptionalHeader.ImageBase);
printf("SectionAlignment: 0x%X\n", g_NTHeaders.OptionalHeader.SectionAlignment);
printf("FileAlignment: 0x%X\n\n", g_NTHeaders.OptionalHeader.FileAlignment);
}
void ReadSectionTable()
{
// Section Table 在 NT Header 之后。但是不应该使用 NT Header 的大小
// 直接计算位置,应该使用 File Header 中的 SizeOfOptionalHeader 计算。
// 这样才能在 Optional Header 发生变化的情况下继续使用。
ULONG FileOffset;
ULONG SectionTableSize;
FileOffset = g_DosHeader.e_lfanew + sizeof(g_NTHeaders.Signature)
+ sizeof(g_NTHeaders.FileHeader) + g_NTHeaders.FileHeader.SizeOfOptionalHeader;
SectionTableSize = g_NTHeaders.FileHeader.NumberOfSections * sizeof(PE_IMAGE_SECTION_HEADER);
g_pSectionTable = (PE_IMAGE_SECTION_HEADER*)malloc(SectionTableSize);
// 设置文件指针的位置,从文件头开始,sectiontable的偏移是FileOffset
fseek(g_pFile, FileOffset, SEEK_SET);
// 从文件中读取一个SectionTableSize大小的数据存放到g_pSectionTable指向的缓存地址中。
fread(g_pSectionTable, SectionTableSize, 1, g_pFile);
// 打印
printf("****** Section Table ******\n");
for(int i = 0; i < SectionCnt; i++, g_pSectionTable++)
{
// 取得导出表的地址信息
if(strcmp(g_pSectionTable->Name, ".edata") == 0)
{
dwExportVA = g_pSectionTable->VirtualAddress;
dwExPointerToRawData = g_pSectionTable->PointerToRawData;
}
// 取得导入表的地址信息
if(strcmp(g_pSectionTable->Name, ".idata") == 0)
{
dwImportVA = g_pSectionTable->VirtualAddress;
dwImPointerToRawData = g_pSectionTable->PointerToRawData;
}
printf("Number:%d\n", i+1);
printf("Name:%.8s\n", g_pSectionTable->Name);
printf("VirtualSize:%08x\n", g_pSectionTable->Misc.VirtualSize);
printf("VirtualAddress:0x%08x\n", g_pSectionTable->VirtualAddress);
printf("SizeOfRawData:0x%08x\n", g_pSectionTable->SizeOfRawData);
printf("PointerToRawData:0x%08x\n", g_pSectionTable->PointerToRawData);
printf("PointerToRelocations:0x%08x\n", g_pSectionTable->PointerToRelocations);
printf("PointerToLinenumbers:0x%08x\n", g_pSectionTable->PointerToLinenumbers);
printf("NumberOfRelocations:0x%04x\n", g_pSectionTable->NumberOfRelocations);
printf("NumberOfLinenumbers:0x%04x\n", g_pSectionTable->NumberOfLinenumbers);
printf("Characteristics:0x%08x\n\n", g_pSectionTable->Characteristics);
}
}
// 打印导入表的内容
void ReadImportTable()
{
// 打印
printf("\n****** Import Table ******\n");
// 数据目录表的第二个元素为导入表
printf("导入表的偏移地址:%04x\n", g_NTHeaders.OptionalHeader.DataDirectory[1].VirtualAddress);
printf("导入表的大小:%04x\n\n", g_NTHeaders.OptionalHeader.DataDirectory[1].Size);
DWORD dwFileOffset;
// 导入表内容非空
if (g_NTHeaders.OptionalHeader.DataDirectory[1].VirtualAddress != 0)
{
// 将导入表的VA转换为文件偏移
dwFileOffset = OnConvertVAToRawA(g_NTHeaders.OptionalHeader.DataDirectory[1].VirtualAddress, dwImportVA, dwImPointerToRawData);
printf("导入表的文件偏移为:%08x\n", dwFileOffset);
// 输出DLL个数
g_ImportDsr = (PE_IMAGE_IMPORT_DESCRIPTOR *)malloc(sizeof(PE_IMAGE_IMPORT_DESCRIPTOR));
// 导入表的文件偏移
fseek(g_pFile, dwFileOffset, SEEK_SET);
fread(g_ImportDsr, sizeof(PE_IMAGE_IMPORT_DESCRIPTOR), 1, g_pFile);
// 得到导入的DLL数量
int nDllCount = 0;
while ((0 != g_ImportDsr->FirstThunk) || (0 != g_ImportDsr->ForwarderChain) || (0 != g_ImportDsr->Name)
|| (0 != g_ImportDsr->u.OriginalFirstThunk) || (0 != g_ImportDsr->u.Characteristics) || (0 != g_ImportDsr->TimeDateStamp) )
{
nDllCount++;
fread(g_ImportDsr, sizeof(PE_IMAGE_IMPORT_DESCRIPTOR), 1, g_pFile);
}
printf("\n导入的DLL个数为:%d\n", nDllCount);
// 当导入dll不为0,输出dll名字和调用函数的个数
if(nDllCount != 0)
{
PE_IMAGE_IMPORT_DESCRIPTOR *pg_ImportDsr = (PE_IMAGE_IMPORT_DESCRIPTOR *)calloc(nDllCount, sizeof(PE_IMAGE_IMPORT_DESCRIPTOR)); // prince 01
fseek(g_pFile, dwFileOffset, SEEK_SET);
fread(pg_ImportDsr, sizeof(PE_IMAGE_IMPORT_DESCRIPTOR), nDllCount, g_pFile);
// 读出dll名字
DWORD *pNameFileOffset = (DWORD *)malloc(sizeof(DWORD) * nDllCount); // prince 02
DWORD *pOriginalFirstThunkFileOffset = (ULONG *)malloc(sizeof(ULONG) * nDllCount); // prince 02
// 取出这些Dll的Name的VA转化为pNameFileOffset存在pNamefileOffset中
*pNameFileOffset = OnConvertVAToRawA(pg_ImportDsr->Name, dwImportVA, dwImPointerToRawData);
*pOriginalFirstThunkFileOffset = OnConvertVAToRawA(pg_ImportDsr->FirstThunk, dwImportVA, dwImPointerToRawData);
DWORD *pName = (DWORD *)calloc(nDllCount, sizeof(DWORD));
//每次开辟一个chName[16]用于存放Name
char *pchName = (char *)malloc(sizeof(char) * 16);
// 将本次申请的内存的地址保存到*pName中
*pName = (DWORD)pchName;
// 从文件读取DLL名字
DWORD dwDllName = *pNameFileOffset;
fseek(g_pFile, dwDllName, SEEK_SET);
char chTemp[16] = {0};
fread((void *)*pName, 16, 1, g_pFile);
printf("\n第一个DLL名字:%s\n", *pName);
// 输出DLL中调用函数的个数
int *pnFunctionCountPerDll = (int *)calloc(nDllCount, sizeof(int));
IMAGE_THUNK_DATA *pITD = (IMAGE_THUNK_DATA *)malloc(sizeof(IMAGE_THUNK_DATA));
for (int i = 0; i < nDllCount; i++, pnFunctionCountPerDll++, pOriginalFirstThunkFileOffset++)
{
fseek(g_pFile, *pOriginalFirstThunkFileOffset, SEEK_SET);
fread(pITD, sizeof(IMAGE_THUNK_DATA), 1, g_pFile);
int nFunctionCount = 0;
while ((pITD->u1.ForwarderString != 0) || (pITD->u1.Function != 0) || (pITD->u1.Ordinal != 0) || (pITD->u1.AddressOfData != 0))
{
nFunctionCount++;
fread(pITD, sizeof(IMAGE_THUNK_DATA), 1, g_pFile);
}
*pnFunctionCountPerDll = nFunctionCount;
}
pOriginalFirstThunkFileOffset -= nDllCount;
pnFunctionCountPerDll -= nDllCount;
printf("\n第一个DLL中的函数个数:%d\n", *pnFunctionCountPerDll);
}
}
else
{
printf("此文件无导入表\n");
}
}
#ifndef _PEDUMP_H_
#define _PEDUMP_H_
#include <stdio.h>
/* TODO: 在此处引用程序需要的其他头文件 */
#include <windows.h>
//////////////////////////////////////////////////////////////////////////
typedef struct { // DOS头
WORD e_magic; // 魔术数字
WORD e_cblp; // 文件最后页的字节数
WORD e_cp; // 文件页数
WORD e_crlc; // 重定向元素个数
WORD e_cparhdr; // 头部尺寸,以段落为单位
WORD e_minalloc; // 所需的最小附加段
WORD e_maxalloc; // 所需的最大附加段
WORD e_ss; // 初始的SS值(相对偏移量)
WORD e_sp; // 初始的SP值
WORD e_csum; // 校验和
WORD e_ip; // 初始的IP值
WORD e_cs; // 初始的CS值(相对偏移量)
WORD e_lfarlc; // 重分配表文件地址
WORD e_ovno; // 覆盖号
WORD e_res[4]; // 保留字
WORD e_oemid; // OEM标识符(相对e_oeminfo)
WORD e_oeminfo; // OEM信息
WORD e_res2[10]; // 保留字
LONG e_lfanew; // 新EXE文件的头部地址
} PE_IMAGE_DOS_HEADER;
typedef struct {
WORD Machine; // 能够运行 PE 文件的 CPU 类型
WORD NumberOfSections; // Section 个数
DWORD TimeDateStamp; // 链接器产生此 PE 文件的时间戳
DWORD PointerToSymbolTable; // COFF 符号表偏移位置。调试器使用
DWORD NumberOfSymbols; // COFF 符号表中的符号个数。调试器使用
WORD SizeOfOptionalHeader; // 可选头的大小。EXE 中是 PE_IMAGE_OPTIONAL_HEADER 的大小。OBJ 中是 0
WORD Characteristics; // 描述此 PE 文件的属性。属性信息见后面的宏定义
} PE_IMAGE_FILE_HEADER;
#define PE_IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file.
#define PE_IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references).
#define PE_IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file.
#define PE_IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file.
#define PE_IMAGE_FILE_AGGRESIVE_WS_TRIM 0x0010 // Agressively trim working set
#define PE_IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 // App can handle >2gb addresses
#define PE_IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed.
#define PE_IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine.
#define PE_IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file
#define PE_IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 // If Image is on removable media, copy and run from the swap file.
#define PE_IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 // If Image is on Net, copy and run from the swap file.
#define PE_IMAGE_FILE_SYSTEM 0x1000 // System File.
#define PE_IMAGE_FILE_DLL 0x2000 // File is a DLL.
#define PE_IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 // File should only be run on a UP machine
#define PE_IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed.
typedef struct {
DWORD VirtualAddress;
DWORD Size;
} PE_IMAGE_DATA_DIRECTORY;
#define PE_IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
typedef struct {
//
// Standard fields.
//
WORD Magic; // 标识可执行映像的状态。0x0107 表示一个 ROM 映像,0x010B 表示一个 EXE 映像。
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode; // 所有 code section 合计大小
DWORD SizeOfInitializedData; // 所有已初始化数据 section 合计大小
DWORD SizeOfUninitializedData; // 所有未初始化数据 section 合计大小
DWORD AddressOfEntryPoint; // 入口点的 RVA
DWORD BaseOfCode; // code section 的 RVA。通常为 0x1000
DWORD BaseOfData; // data section 的 RVA。
//
// NT additional fields.
//
DWORD ImageBase; // 将 PE 文件载入内存的基地址
DWORD SectionAlignment; // 将 PE 文件载入内存后,各个 section 起始虚拟地址是此值的整数倍,内存中节对齐的粒度
DWORD FileAlignment; // 在 PE 文件中,各个 section 相对于文件开始的地址是此值的整数倍,文件中节对齐的粒度
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage; // 将 PE 文件载入内存后可执行映像的大小。从 image base 开始,到最后一个 section 结束。最后一个 section 的尾端必须是 SectionAlignment 的整数倍。
DWORD SizeOfHeaders; // PE 表头及 section table 的合计大小。各个 section 就从此后展开。
DWORD CheckSum; // 校验和
WORD Subsystem; // 子系统
WORD DllCharacteristics; // 总是 0
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags; // 被放弃
DWORD NumberOfRvaAndSizes; // 在 DataDirectory 数组中的项目数量。总是 16。
/*
使用这个数组能够迅速在可执行映像中找到特定的 section,而不需要按照顺序遍历 section。
例如使用数组中的第一个项目可以找到所有 exported function 的 RVA 及大小。
*/
PE_IMAGE_DATA_DIRECTORY DataDirectory[PE_IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} PE_IMAGE_OPTIONAL_HEADER;
typedef struct {
DWORD Signature; // 文件类型标志
PE_IMAGE_FILE_HEADER FileHeader; // 文件头
PE_IMAGE_OPTIONAL_HEADER OptionalHeader; // 可选头
} PE_IMAGE_NT_HEADERS;
#define PE_IMAGE_SIZEOF_SHORT_NAME 8
typedef struct {
BYTE Name[PE_IMAGE_SIZEOF_SHORT_NAME]; // section 名称
union {
DWORD PhysicalAddress; // 在 OBJ 中表示 section 的实际位置,第一个 section 为 0。
DWORD VirtualSize; // 在 EXE 中表示 section 的虚拟大小,就是没有进行任何对齐的大小。
} Misc;
DWORD VirtualAddress; // 在 EXE 中表示将 section 映射到内存中的 RVA。
DWORD SizeOfRawData; // 在 EXE 中表示 file align 后的大小。
DWORD PointerToRawData; // 以文件起始为基准的偏移值。
DWORD PointerToRelocations; // 在 EXE 中为 0
DWORD PointerToLinenumbers; // 在 EXE 中为 0
WORD NumberOfRelocations; // 在 EXE 中为 0
WORD NumberOfLinenumbers; // 在 EXE 中为 0
DWORD Characteristics; // section 的属性标志。参见后面的宏定义。
} PE_IMAGE_SECTION_HEADER;
typedef struct {
DWORD Characteristics; // 保留
DWORD TimeDateStamp; // 时间日期记录
WORD MajorVersion; // dll的首版本号
WORD MinorVersion; // dll的次版本号
DWORD Name; // dll的模块名
DWORD Base; // 基数
DWORD NumberOfFunctions; // 函数的总数
DWORD NumberOfNames; // 有名函数的总数
DWORD AddressOfFunctions; // FAT表RVA值
DWORD AddressOfNames; // FNT表RVA值
WORD AddressOfNameOrdinals; // FOT表RVA值
} PE_IMAGE_EXPORT_DIRECTORY;
typedef struct {
union {
ULONG Characteristics; // 0 for terminating null import descriptor
ULONG OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
} u;
DWORD TimeDateStamp; // 时间日期记录
DWORD ForwarderChain; // 正向链接索引
DWORD Name; // DLL名字符串的RVA值
DWORD FirstThunk; // Import ThunkData数组RVA值(IAT)
}PE_IMAGE_IMPORT_DESCRIPTOR;
typedef struct {
WORD Hint;
BYTE Name[1];
}PE_IMAGE_IMPORT_BY_NAME;
typedef struct {
union {
PBYTE ForwarderString;
PDWORD Function;
DWORD Ordinal;
PE_IMAGE_IMPORT_BY_NAME AddressOfData;
}u1;
}PE_IMAGE_THUNK_DATA;
//
// 常用的 section 属性标志。
//
//#define IMAGE_SCN_CNT_CODE 0x00000020 // Section contains code.
//#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 // Section contains initialized data.
//#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 // Section contains uninitialized data.
//#define IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information.
//#define IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image.
//#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 // Section can be discarded.
//#define IMAGE_SCN_MEM_SHARED 0x10000000 // Section is shareable.
//#define IMAGE_SCN_MEM_EXECUTE 0x20000000 // Section is executable.
//#define IMAGE_SCN_MEM_READ 0x40000000 // Section is readable.
//#define IMAGE_SCN_MEM_WRITE 0x80000000 // Section is writeable.
//////////////////////////////////////////////////////////////////////////
// 全局变量声明
extern FILE* g_pFile;
extern PE_IMAGE_DOS_HEADER g_DosHeader;
extern PE_IMAGE_NT_HEADERS g_NTHeaders;
extern PE_IMAGE_SECTION_HEADER* g_pSectionTable;
extern PE_IMAGE_EXPORT_DIRECTORY* g_ExportDir;
extern PE_IMAGE_IMPORT_DESCRIPTOR* g_ImportDsr;
//////////////////////////////////////////////////////////////////////////
// 函数声明
void ReadDosHeader();
void ReadNTHeader();
void ReadSectionTable();
void ReadImportTable();
#endif /* _PEDUMP_H_ */
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论