-
-
[原创]PE文件之旅 -- 第一篇 Sections
-
发表于:
2005-1-6 13:33
8622
-
[原创]PE文件之旅 -- 第一篇 Sections
无论是作为一名或者立志成为一名拥有真正技术的Top Cracker(当然我是属于后者啦,哈),对PE文件格式的熟悉绝对是必须要研究通透和掌握的技术,这一点相信应该没有什么争议吧(当然如果不研究Windows平台下解密那就另说了)?看过网上好多的PE文件教程,理论居多,只是看好象都明白,到了应用的时候,比如脱壳,对于IAT表在脑海中仍然是稀里糊涂一片(呵呵,至少我是这样D,菜啊~), 学习就是这样,只是学习原理,而没有去实践,好象是懂了,到真正去做的时候,却不知道从何下手。尤其是计算机这门实践性很强的学科,必须要辅以实践才能真正把知识学到手。这里要感谢 MengLong[DFCG],他的<<PE知识学习>>从编程实践的角度剖析PE文件格式,同时也让我有了研究下去的想法。
好了,罗嗦了这么多,忘了说了,纯属菜鸟教程,让高手贻笑大方了。
PE文件之旅(C语言描述) -- 第一篇 Sections
平台 : windows XP SP1
编译器 : VC++6.0
时间 : 2004.12 -- 2005.01
参考资料: 看雪<<加密解密II>>,MengLong[DFCG]<<PE知识学习>>,<<Matt Pietrek's PE Tutorial>>.
Coded by: prince
E-mail : [email]Cracker_prince@163.com[/email]
注意:这篇教程直接从Sections开始讲解,前面的知识和代码请参阅<<PE知识学习>>.以下列出的仅是核心部分代码,完整代码见后续篇幅。
首先请大家直观地看一下PE文件格局。这也是PE文件存放在磁盘上的格局。
F:\MyProduction\成品\PEFormat[/IMG]
我们由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
附件:PESections.rar[IMG]
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!