上一篇文章解析了PE的前两个部分DOS头和NT头,这篇文章继续解析NT头的下一个部分 节表
首先我们需要算出第一个节表的地址,可以从PE标志开始算,
1.节表地址:PE标记[4字节]+标准PE头[20字节]+可选PE头[p_sizeofoptionalheader]
其中PE标记是固定的4字节,标准PE头是固定的20字节,可选PE头的大小不确定,但是在标准PE头中sizeofoptionalheader可以取到,所以最后还要加上sizeofoptionalheader的值
2.节表的个数:在标准PE头中numberofsections记录着
3.每个节表的大小:根据PE结构图可以看到,一个节表是40个字节
有了节表个数就可以确定循环次数了,每次循环结束后,节表的地址要增加40 到下一个节表地址
#include#include #include //获取文件大小 int get_file_size(char* filename) { FILE* fp = fopen(filename,"r"); int size; if( fp == NULL ) { printf("open fail n"); return -1; } fseek(fp,0,SEEK_END); size=ftell(fp); fclose(fp); return size; } int main() { char* filename="D:\T\zx.exe"; int file_size=get_file_size(filename); //申请空间 char* ptr; ptr = (char*) malloc(file_size); if( ptr == NULL) { printf("空间不足n"); return 0; } memset(ptr,0,file_size); printf("ptr:%x n",ptr); //将文件内容 读取到内存 FILE* fp = fopen(filename,"rb+"); fread(ptr,file_size,1,fp); fclose(fp); //找到PE偏移 int* p_e_lfanew=(int*)ptr+15; printf("PE偏移:ttt%x n",*p_e_lfanew); //PE标志 char* p_signature = ptr+(*p_e_lfanew); //标准PE头中的 节数量 short* p_numberofsections=(short*)(p_signature+6); printf("节数量:ttt%x n",*p_numberofsections); //可选PE头大小 short* p_sizeofoptionalheader=(short*)(p_signature+20); printf("可选PE头大小:tt%x -> %d n",*p_sizeofoptionalheader,*p_sizeofoptionalheader); //内存镜像基址 int* p_imagebase=(int*)(p_signature+52); printf("内存镜像基址:tt%x n",*p_imagebase); //内存对齐字节数 int* p_sectionalignment=(int*)(p_signature+56); printf("内存对齐字节数:tt%x n",*p_sectionalignment); //文件对齐字节数 int* p_filealignment=(int*)(p_signature+60); printf("文件对齐字节数:tt%x n",*p_filealignment); //节表地址:DOS头[64字节]+PE标记[4字节]+标准PE头[20字节]+可选PE头[p_sizeofoptionalheader] =312=0x138 int varsize=*p_sizeofoptionalheader; //char* image_section_header_base=ptr+64+4+20+(*p_sizeofoptionalheader); char* image_section_header_base=p_signature+4+20+(*p_sizeofoptionalheader); printf("节表地址:tt%x n",image_section_header_base); int i=1; for(i;i<=*p_numberofsections;i++) { printf("第 %d 个节:n",i); //printf("image_section_header_base:%x n",image_section_header_base); char name[9]; memcpy(name,image_section_header_base,8); name[8]=' '; int *pmisc=(int*)(image_section_header_base+8); int *pvirtualaddress=(int*)(image_section_header_base+12); int *psizeofrawdata=(int*)(image_section_header_base+16); int *ppointertorawdata=(int*)(image_section_header_base+20); int *ppointertorelocations=(int*)(image_section_header_base+24); int *ppointertolinenumbers=(int*)(image_section_header_base+28); short *pnumberofrelocations=(short*)(image_section_header_base+32); short *pnumberoflinenumbers=(short*)(image_section_header_base+34); int *pcharacteristics=(int*)(image_section_header_base+36); printf("t name:%s n",name); printf("t misc:%x n",*pmisc); printf("t virtualaddress:%x n",*pvirtualaddress); printf("t sizeofrawdata:%x n",*psizeofrawdata); printf("t pointertorawdata:%x n",*ppointertorawdata); printf("t pointertorelocations:%x n",*ppointertorelocations); printf("t pointertolinenumbers:%x n",*ppointertolinenumbers); printf("t numberofrelocations:%x n",*pnumberofrelocations); printf("t numberoflinenumbers:%x n",*pnumberoflinenumbers); printf("t characteristics:%x n",*pcharacteristics); image_section_header_base=image_section_header_base+40; } //释放内存 free(ptr); ptr=NULL; return 0; }
执行结果如图
拿PE程序解析一下 结果没有差异



