PE文件之旅(C语言描述) -- 第一篇 Sections
2005-03-26 17:23
316 查看
无论是作为一名或者立志成为一名拥有真正技术的Top Cracker(当然我是属于后者啦,哈),对PE文件格式的熟悉绝对是必须要研究通透和掌握的技术,这一点相信应该没有什么争议吧(当然如果不研究Windows平台下解密那就另说了)?看过网上好多的PE文件教程,理论居多,只是看好象都明白,到了应用的时候,比如脱壳,对于IAT表在脑海中仍然是稀里糊涂一片(呵呵,至少我是这样D,菜啊~), 学习就是这样,只是学习原理,而没有去实践,好象是懂了,到真正去做的时候,却不知道从何下手。尤其是计算机这门实践性很强的学科,必须要辅以实践才能真正把知识学到手。这里要感谢 MengLong[DFCG],他的<>从编程实践的角度剖析PE文件格式,同时也让我有了研究下去的想法。
好了,罗嗦了这么多,忘了说了,纯属菜鸟教程,让高手贻笑大方了。
PE文件之旅(C语言描述) -- 第一篇 Sections
平台 : windows XP SP1
编译器 : VC++6.0
时间 : 2004.12 -- 2005.01
参考资料: 看雪<<加密解密II>>,MengLong[DFCG]<>,<>.
Coded by: prince
E-mail : Cracker_prince@163.com
注意:这篇教程直接从Sections开始讲解,前面的知识和代码请参阅<>.以下列出的仅是核心部分代码,完整代码见后续篇幅。
首先请大家直观地看一下PE文件格局。这也是PE文件存放在磁盘上的格局。
offset 0 -------------------------------
| IMAGE_DOS_HEADER | <-- Dos部首
PE Signature ------------------------------- /
| 'PE',0,0 | <-- PE文件标志 |
------------------------------- |
| IMAGE_FILE_HEADER | <-- 映像文件头 | -- IMAGE_NT_HEADERS
------------------------------- |
| IMAGE_OPTIONAL_HEADER32 | <-- 映像可选头 |
------------------------------- /
------------| Section Table | <-- 节表 -- IMAGE_SECTION_HEADER (Array)
| | | | | -------------------------------
| | | | /-->| .text | <-- 代码区段
| | | | -------------------------------
| | | /---->| .data | <-- 数据区段
| | | -------------------------------
| | /------>| .idata | <-- 输入表
| | -------------------------------
| /-------->| .edata | <-- 输出表
| -------------------------------
/---------->| .reloc | <-- 重定位表区段
-------------------------------
| .... |
-------------------------------
| 调试信息 |
-------------------------------
我们由IMAGE_DOS_HEADER.e_lfanew得到PE文件头在PE文件中的偏移,即IMAGE_NT_HEADERS结构,如下:
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature; **PE文件标识 "PE",0,0
IMAGE_FILE_HEADER FileHeader; **映像文件头 (其中的NumberOfSections成员指定了Sections的个数)
IMAGE_OPTIONAL_HEADER32 OptionalHeader; **映像可选头
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
核心代码:
IMAGE_DOS_HEADER myDosHeader;
LONG e_lfanew;
FILE *pFile;
pFile = fopen("文件路径", r+b);
fread(&myDosHeader, sizeof(IMAGE_DOS_HEADER), 1, pFile); // pFile 为打开的文件指针
e_lfanew = myDosHeader.e_lfanew; // 保存PE文件头偏移
IMAGE_FILE_HEADER myFileHeader;
int nSectionCount;
fseek(pFile, (e_lfanew + sizeof(DWORD)), SEEK_SET);
fread(&myFileHeader, sizeof(IMAGE_FILE_HEADER), 1, pFile);
nSectionCount = myFileHeader.NumberOfSections; // 保存Section个数
// 过了IMAGE_NT_HEADERS结构就是IMAGE_SECTION_HEADER结构数组了,注意是结构数组,有几个Section该结构就有几个元素
// 这里动态开辟NumberOfSections个内存来存储不同的Section信息
IMAGE_SECTION_HEADER *pmySectionHeader = (IMAGE_SECTION_HEADER *)calloc(nSectionCount, sizeof(IMAGE_SECTION_HEADER));
fseek(pFile, (e_lfanew + sizeof(IMAGE_NT_HEADERS)), SEEK_SET);
fread(pmySectionHeader, sizeof(IMAGE_SECTION_HEADER), nSectionCount, pFile);
// 打印Sections信息
for (int i = 0; i < nSectionCount; i++, pmySectionHeader++)
{
printf("Name: %s/n", pmySectionHeader->Name);
printf("union_PhysicalAddress: %08x/n", pmySectionHeader->Misc.PhysicalAddress);
printf("union_VirtualSize: %04x/n", pmySectionHeader->Misc.VirtualSize);
printf("VirtualAddress: %08x/n", pmySectionHeader->VirtualAddress);
printf("SizeOfRawData: %08x/n", pmySectionHeader->SizeOfRawData);
printf("PointerToRawData: %04x/n", pmySectionHeader->PointerToRawData);
printf("PointerToRelocations: %04x/n", pmySectionHeader->PointerToRelocations);
printf("PointerToLinenumbers: %04x/n", pmySectionHeader->PointerToLinenumbers);
printf("NumberOfRelocations: %04x/n", pmySectionHeader->NumberOfRelocations);
printf("NumberOfLinenumbers: %04x/n", pmySectionHeader->NumberOfLinenumbers);
printf("Charateristics: %04x/n", pmySectionHeader->Characteristics);
}
// 恢复指针
pmySectionHeader -= m_nSectionCount;
if (pmySectionHeader != NULL) // 释放内存
{
free(pmySectionHeader);
pmySectionHeader = NULL;
}
// 最后不要忘记关闭文件
fclose(pFile);
我将以上代码改写了一个Win32程序,可以很方便地查看PE文件的Section信息。本人菜鸟,错误及不妥之处难免存在,如果大家发现有什么问题,不要吝啬啊,请告之。那么关于PE文件格式Section的C语言描述到此就结束了,下一篇将继续我们的PE文件研究,DLL的秘密 -- 输出表。
prince 2005.01.06
好了,罗嗦了这么多,忘了说了,纯属菜鸟教程,让高手贻笑大方了。
PE文件之旅(C语言描述) -- 第一篇 Sections
平台 : windows XP SP1
编译器 : VC++6.0
时间 : 2004.12 -- 2005.01
参考资料: 看雪<<加密解密II>>,MengLong[DFCG]<>,<>.
Coded by: prince
E-mail : Cracker_prince@163.com
注意:这篇教程直接从Sections开始讲解,前面的知识和代码请参阅<>.以下列出的仅是核心部分代码,完整代码见后续篇幅。
首先请大家直观地看一下PE文件格局。这也是PE文件存放在磁盘上的格局。
offset 0 -------------------------------
| IMAGE_DOS_HEADER | <-- Dos部首
PE Signature ------------------------------- /
| 'PE',0,0 | <-- PE文件标志 |
------------------------------- |
| IMAGE_FILE_HEADER | <-- 映像文件头 | -- IMAGE_NT_HEADERS
------------------------------- |
| IMAGE_OPTIONAL_HEADER32 | <-- 映像可选头 |
------------------------------- /
------------| Section Table | <-- 节表 -- IMAGE_SECTION_HEADER (Array)
| | | | | -------------------------------
| | | | /-->| .text | <-- 代码区段
| | | | -------------------------------
| | | /---->| .data | <-- 数据区段
| | | -------------------------------
| | /------>| .idata | <-- 输入表
| | -------------------------------
| /-------->| .edata | <-- 输出表
| -------------------------------
/---------->| .reloc | <-- 重定位表区段
-------------------------------
| .... |
-------------------------------
| 调试信息 |
-------------------------------
我们由IMAGE_DOS_HEADER.e_lfanew得到PE文件头在PE文件中的偏移,即IMAGE_NT_HEADERS结构,如下:
typedef struct _IMAGE_NT_HEADERS {
DWORD Signature; **PE文件标识 "PE",0,0
IMAGE_FILE_HEADER FileHeader; **映像文件头 (其中的NumberOfSections成员指定了Sections的个数)
IMAGE_OPTIONAL_HEADER32 OptionalHeader; **映像可选头
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;
核心代码:
IMAGE_DOS_HEADER myDosHeader;
LONG e_lfanew;
FILE *pFile;
pFile = fopen("文件路径", r+b);
fread(&myDosHeader, sizeof(IMAGE_DOS_HEADER), 1, pFile); // pFile 为打开的文件指针
e_lfanew = myDosHeader.e_lfanew; // 保存PE文件头偏移
IMAGE_FILE_HEADER myFileHeader;
int nSectionCount;
fseek(pFile, (e_lfanew + sizeof(DWORD)), SEEK_SET);
fread(&myFileHeader, sizeof(IMAGE_FILE_HEADER), 1, pFile);
nSectionCount = myFileHeader.NumberOfSections; // 保存Section个数
// 过了IMAGE_NT_HEADERS结构就是IMAGE_SECTION_HEADER结构数组了,注意是结构数组,有几个Section该结构就有几个元素
// 这里动态开辟NumberOfSections个内存来存储不同的Section信息
IMAGE_SECTION_HEADER *pmySectionHeader = (IMAGE_SECTION_HEADER *)calloc(nSectionCount, sizeof(IMAGE_SECTION_HEADER));
fseek(pFile, (e_lfanew + sizeof(IMAGE_NT_HEADERS)), SEEK_SET);
fread(pmySectionHeader, sizeof(IMAGE_SECTION_HEADER), nSectionCount, pFile);
// 打印Sections信息
for (int i = 0; i < nSectionCount; i++, pmySectionHeader++)
{
printf("Name: %s/n", pmySectionHeader->Name);
printf("union_PhysicalAddress: %08x/n", pmySectionHeader->Misc.PhysicalAddress);
printf("union_VirtualSize: %04x/n", pmySectionHeader->Misc.VirtualSize);
printf("VirtualAddress: %08x/n", pmySectionHeader->VirtualAddress);
printf("SizeOfRawData: %08x/n", pmySectionHeader->SizeOfRawData);
printf("PointerToRawData: %04x/n", pmySectionHeader->PointerToRawData);
printf("PointerToRelocations: %04x/n", pmySectionHeader->PointerToRelocations);
printf("PointerToLinenumbers: %04x/n", pmySectionHeader->PointerToLinenumbers);
printf("NumberOfRelocations: %04x/n", pmySectionHeader->NumberOfRelocations);
printf("NumberOfLinenumbers: %04x/n", pmySectionHeader->NumberOfLinenumbers);
printf("Charateristics: %04x/n", pmySectionHeader->Characteristics);
}
// 恢复指针
pmySectionHeader -= m_nSectionCount;
if (pmySectionHeader != NULL) // 释放内存
{
free(pmySectionHeader);
pmySectionHeader = NULL;
}
// 最后不要忘记关闭文件
fclose(pFile);
我将以上代码改写了一个Win32程序,可以很方便地查看PE文件的Section信息。本人菜鸟,错误及不妥之处难免存在,如果大家发现有什么问题,不要吝啬啊,请告之。那么关于PE文件格式Section的C语言描述到此就结束了,下一篇将继续我们的PE文件研究,DLL的秘密 -- 输出表。
prince 2005.01.06
相关文章推荐
- PE文件之旅(C语言描述) 第三篇 -- 加壳与脱壳的战场 输出表
- C语言文件的编译与执行的四个阶段并分别描述
- C语言编程获取PE文件导入函数
- C语言编程获取PE文件导出表内容
- PE文件格式 - 节的原始数据 1(Sections' raw data)
- PE文件详解四:PE详解之区块描述、对齐值以及RVA详解
- C语言读取PE文件信息(一)
- 计算PE文件校验和的C语言实现
- 文件排序(C语言描述)(在堆中进行)
- C语言的编码风格-文件描述(1)
- C语言怎么获得进程的PE文件信息
- 自制大文件拆分器和粘合器(C语言描述)
- PE文件详解(三)--区块描述、对齐值以及RVA
- PE文件详解四:PE详解之区块描述、对齐值以及RVA详解
- C语言包含头文件时用引号和尖括号的区别
- 【C语言】【unix c】如何将多个源文件拼接成一个可执行文件?
- 循环队列基本操作(C语言描述)
- C语言读取文件大量数据到数组
- 文件读写——C语言
- C语言里的写文件