首页
社区
课程
招聘
[求助]关于PE添加新节前空间的判断
发表于: 2007-5-10 16:01 7105

[求助]关于PE添加新节前空间的判断

2007-5-10 16:01
7105
......
;***************************************************************
;判断是否有足够空间存储新节
;28h=sizeof IMAGE_SECTION_HEADER ,18h=sizeof IMAGE_FILE_HEADER
;edi将指向新节
;***************************************************************
movzx eax,[ebx].FileHeader.NumberOfSections 节的数目
mov ecx,28h
mul ecx 节的数目*单个节的大小=所有节表的大小
add eax,pe_header_off  所有节表的大小 + PE文件头偏移 = ???(1)
add eax,18h  
movzx esi,[ebx].FileHeader.SizeOfOptionalHeader
add eax,esi
mov edi,eax
add edi,pMapping   ;I forgot this first
add eax,28h
.IF  eax>[ebx].OptionalHeader.SizeOfHeaders
jmp  Exit 上面运算得到的总和如果大于(所有头+节表的 大小)说明空间不够
.ENDIF

......
文章是一个论坛里的,因为先前早就保存在电脑里,故不知道文章的来源。还请原作者见谅!因工作需要拿出来作参考。
注释是我自己加上去的可能不正确!请大侠们加上标准正确的注释。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 214
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
没人知道吗?
版主,快来啊。
2007-5-10 20:13
0
雪    币: 380
活跃值: (101)
能力值: ( LV13,RANK:370 )
在线值:
发帖
回帖
粉丝
3
首先你得明白[ebx].OptionalHeader.SizeOfHeaders 表示什么意思!
[ebx].OptionalHeader.SizeOfHeaders 是(DOS头大小+PE头大小+所有区块表大小)按FileAlignment
对齐后的值,如果你添加一个新节后将改变上式中“所有区块表大小”。若新合成的大小不超过SizeOfHeaders便可以添加,否则区块表不能添加进去。

add eax,pe_header_off 所有节表的大小 + PE文件头偏移 = ???(1)

应该就是原先所有区块表的大小加上DOS头的大小。

感觉上面好像少掉了"PE\0\0"的四字节
2007-5-10 20:36
0
雪    币: 214
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
我把注释全加上

;***************************************************************
;判断是否有足够空间存储新节
;28h=sizeof IMAGE_SECTION_HEADER ,18h=sizeof IMAGE_FILE_HEADER
;edi将指向新节
;***************************************************************
movzx eax,[ebx].FileHeader.NumberOfSections ;节的数目
mov ecx,28h ;为乘法作准备
mul ecx         ;eax=eax*ecx 节的数目*单个节的大小=节的总大小
add eax,pe_header_off  节的总大小+PE文件头偏移=???(1)
add eax,18h                 ;???(1) + IMAGE_FILE_HEADER的大小=???(2)
movzx esi,[ebx].FileHeader.SizeOfOptionalHeader
add eax,esi   ;???(2) + IMAGE_OPTIONAL_HEADER32结构的长度=???(3)
mov edi,eax
add edi,pMapping   ;I forgot this first ???(3)+内存映射文件的指钟  为后面的操作作准备
add eax,28h   ???(3)+ 节表的大小( sizeof IMAGE_SECTION_HEADER)=???(4) (此处节表是新增的)
.IF  eax>[ebx].OptionalHeader.SizeOfHeaders ;上面运算得到的总和如果大于(所有头+节表的 大小)说明空间不够
                                            ;当然SizeOfHeaders肯定包括dos, coff, pe头 和 段表的大小

jmp  Exit                                   ;如果空间不够结束程序
.ENDIF

[QUOTE=llydd]感觉上面好像少掉了"PE\0\0"的四字节[/QUOTE]
不知道你说少了PE文件标识(Signature)这双字节作用在哪,Signature好像只在判断是否为合法的PE才用到,难道在这里也要用
到它??(在代码的第一行开始就承认是合法的PE了)
上面的代码完全能编译通过正常运行。
作者的意思是可能是:
SizeOfHeaders和单步求出表和头的总和相比较,如果后者大说明空间不够不能添加新节。
但是他在单步求表和头的总和表叙令我费解......
2007-5-11 09:12
0
雪    币: 380
活跃值: (101)
能力值: ( LV13,RANK:370 )
在线值:
发帖
回帖
粉丝
5
感觉上面好像少掉了"PE\0\0"的四字节

我不太清楚程序中pe_header_off此时到底是什么值,如果此时pe_header_off指向的是
IMAGE_NT_HEADERS结构那么就少了"PE\0\0"四字节,如果指向的是IMAGE_FILE_HEADER,那我的想法就是多余的了。!!

首先 只要求(DOS头大小+PE头大小+所有区块表大小)<= SizeOfHeaders满足便可
PE头大小包括Signature的四字节,IMAGE_FILE_HEADER的20字节,IMAGE_OPTIONAL_HEADER的224字节(一般是224字节)

add eax,pe_header_off 节的总大小+PE文件头偏移=???(1)

节的总大小+DOS头的大小(PE文件头偏移便是DOS头的大小)

add eax,18h ;???(1) + IMAGE_FILE_HEADER的大小=???(2)

节的总大小+DOS头大小+IMAGE_FILE_HEADER的大小

add eax,esi ;???(2) + IMAGE_OPTIONAL_HEADER32结构的长度=???(3)

节的总大小+DOS头大小+IMAGE_FILE_HEADER的大小+IMAGE_OPTIONAL_HEADER大小

add eax,28h ???(3)+ 节表的大小( sizeof IMAGE_SECTION_HEADER)=???(4)


节的总大小+DOS头大小+IMAGE_FILE_HEADER的大小+IMAGE_OPTIONAL_HEADER大小+新加块表的大小

最后补充一下


typedef struct _IMAGE_NT_HEADERS64 {
DWORD Signature;
IMAGE_FILE_HEADER FileHeader;
IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;

这个结构可能你没有弄清楚
2007-5-11 09:32
0
雪    币: 81
活跃值: (41)
能力值: (RANK:220 )
在线值:
发帖
回帖
粉丝
6
基本上这种情况不会发生,因为Section Header的空间都有 4096 字节,一般一个PE的Section也没几个。

这里判断的是 Section Header 的空间中是否有足够的空间来添加一个Section Header(sizeof(..SEC...HDR...)),而不是Section本身。

要理解这些东西,最好用C/C++代码,ASM变成误导了很多初学者的观念,大大降低了代码工程化效率(运行效率或许有那么一点点提升)。
2007-5-11 11:08
0
雪    币: 81
活跃值: (41)
能力值: (RANK:220 )
在线值:
发帖
回帖
粉丝
7
// Open source file
        CMemFile fSrc(ptzSrc);
        if (!fSrc)
        {
                return FALSE;
        }

        // Verify DOS signature
        PBYTE pbSrc = fSrc;
        if (((PIMAGE_DOS_HEADER) pbSrc)->e_magic != IMAGE_DOS_SIGNATURE)
        {
                return FALSE;
        }

        // Verify PE signature
        PIMAGE_NT_HEADERS pNTHdr = (PIMAGE_NT_HEADERS) (pbSrc + ((PIMAGE_DOS_HEADER) pbSrc)->e_lfanew);
        if (pNTHdr->Signature != IMAGE_NT_SIGNATURE)
        {
                return FALSE;
        }

        // Verify sections header space
        if ((pNTHdr->FileHeader.NumberOfSections + 1) * sizeof(IMAGE_SECTION_HEADER) > pNTHdr->OptionalHeader.SizeOfHeaders)
        {
                return FALSE;
        }

用 C/C++ 表达一下,楼主的代码相当于“Verify sections header space”部分
2007-5-11 11:12
0
雪    币: 214
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
谢谢你!完全搞懂了。
节的总大小+DOS头的大小(PE文件头偏移便是DOS头的大小)

就是这个地方理解误导了我。
e_lfanew            DWORD      ? ;指向PE文件头
它是DOS头的最后一个双字节,它的编移量就是DOS头的大小。呵呵!没有仔细去想它。最后导致整段代码不能理解。

附:PE文件头汇编完整结构定义

IMAGE_NT_HEADERS STRUCT

  Signature          DWORD                       ?       ;PE文件标识

  FileHeader         IMAGE_FILE_HEADER        <>

  OptionalHeader    IMAGE_OPTIONAL_HEADER32 <>

IMAGE_NT_HEADERS ENDS

PE文件头的第一个双字是一个标志,它被定义为00004550h,也就是字符“P”,“E”加上两个0,这也是“PE”这个称呼的由来,大部分的文件属性由标志后面的IMAGE_FILE_HEADER和IMAGE_OPTIONAL_HEADER32结构来定义。
2007-5-11 11:12
0
游客
登录 | 注册 方可回帖
返回
//