首页
社区
课程
招聘
[原创]PE节load时的对齐问题
发表于: 2007-5-5 10:22 15135

[原创]PE节load时的对齐问题

2007-5-5 10:22
15135
【  标题  】 PE节load时的对齐问题
【  作者  】 linxer
【  环境  】 xp sp2
【  Q Q   】 3568599
【  声明  】 俺系初级选手,高手略过。失误之处敬请诸位大侠赐教!

本问题的研究源至upack 0.32 load后虚拟脱壳,发现自己写的load程序有很大问题,upack 0.32加壳后程序虚拟机中跑不起来,连入口处反汇编出来的代码都不对......后来,发现是section load不对。经过本人反复改写节表头信息(IMAGE_SECTION_HEADER),然后用OD加载,看其怎么load,发现以下规律,以前曾在论坛上发过一段PE load的代码,当时,对节表对齐属性该怎么效验也不清楚,那个时候,在load FSG1.33时,发现有些节属性是不对齐的,但windows却能让这个程序跑起来,心中甚是不解,后来没有办法,干脆把节对齐属性效验部分给屏蔽了(其实那个时候是自己的程序写的不对,效验太严格了)

前几天,在expressor v1.2虚拟脱壳后dump时,发现dump后程序windows无法load,我用OllyDump插件把OD中脱壳后程序dump出来也有这样的问题,后来发现是:expressor v1.2加壳后程序,其SizeOfImage不为SectionAlignment整数倍,我写的那个dump是在相对PE头SizeOfImage处建新节的(从以前看的OllyDump插件源码学的,不过,目前最新的源码好像修正这个bug了,可能是我用的插件比较老吧,才load不起来),这样就出现了最后一个节没对齐,windows load不起来。

下面结合我用upack v0.32加壳后程序说明之,高手请飘过,内容很简单。

以下示例中对齐属性如下:

00000078    00100000    DD 00001000          ;  SectionAlignment = 1000
0000007C    00020000    DD 00000200          ;  FileAlignment = 200

说下FileAlignment字段吧,这个字段在有些程序可以看到是0x1000等,我通过试验,好像发现这个字段不管是什么值,系统都用0x200,不过它必须大于等于0x200,小于等于0x1000,并为0x200整数倍

为了说明问题,这里定义两个变量:

SectionAlignmentMask = SectionAlignment - 1;
FileAlignmentMask = 0x200 - 1;

如不加说明,以下几个示例均非最后一个节

示例1:

节表信息如下:
00000138    2E 55 70 61>ASCII ".Upack"       ; SECTION
00000140    00800000    DD 00008000          ;  VirtualSize = 8000 (32768.)
00000144    00100000    DD 00001000          ;  VirtualAddress = 1000                //按一般书上说,这个要对齐
00000148    B7000000    DD 000000B7          ;  SizeOfRawData = B7 (183.)         //按一般书上说,这个也要对齐
0000014C    11000000    DD 00000011          ;  PointerToRawData = 11
00000150    00000000    DD 00000000          ;  PointerToRelocations = 0
00000154    00000000    DD 00000000          ;  PointerToLineNumbers = 0
00000158    0000        DW 0000              ;  NumberOfRelocations = 0
0000015A    0000        DW 0000              ;  NumberOfLineNumbers = 0
0000015C    600000E0    DD E0000060          ;  Characteristics = CODE|INITIALIZED_DATA|EXECUTE|READ|WRITE

上面这个节,貌似:将磁盘中偏移0x11,大小0xb7的内容拷到内存中VirtualAddress=0x1000处,当然这个节在内存中大小是0x8000,未填充部分全填0
但,其实不是这样的,windows在load的时候是将磁盘中偏移0x00,大小0x200的内容拷到内存中去了,出乎我这个菜鸟的意料了

示例2:

节表信息如下:
00000138    2E 55 70 61>ASCII ".Upack"       ; SECTION
00000140    00800000    DD 00008000          ;  VirtualSize = 8000 (32768.)
00000144    00100000    DD 00001000          ;  VirtualAddress = 1000
00000148    B7020000    DD 000002B7          ;  SizeOfRawData = 2B7 (695.)
0000014C    f1000000    DD 000000f1          ;  PointerToRawData = f1
00000150    00000000    DD 00000000          ;  PointerToRelocations = 0
00000154    00000000    DD 00000000          ;  PointerToLineNumbers = 0
00000158    0000        DW 0000              ;  NumberOfRelocations = 0
0000015A    0000        DW 0000              ;  NumberOfLineNumbers = 0
0000015C    600000E0    DD E0000060          ;  Characteristics = CODE|INITIALIZED_DATA|EXECUTE|READ|WRITE

看下这个win怎么load到内存的,它将磁盘中偏移0x00,大小0x400的内容拷到内存中去了

好了,看了上面两个例子,你应该知道它是怎么从磁盘中拷数据出去了吧,其思路用代码表示如下:

SizeOfRawData = (SizeOfRawData + FileAlignmentMask) & (0xffffffff ^ FileAlignmentMask);
PointerToRawData = PointerToRawData & (0xffffffff ^ FileAlignmentMask);

示例3:

节表信息如下:
00000138    2E 55 70 61>ASCII ".Upack"       ; SECTION
00000140    00810000    DD 00008100          ;  VirtualSize = 8100 (33024.)
00000144    00100000    DD 00001000          ;  VirtualAddress = 1000
00000148    B7020000    DD 000002B7          ;  SizeOfRawData = 2B7 (695.)
0000014C    f1000000    DD 000000f1          ;  PointerToRawData = f1
00000150    00000000    DD 00000000          ;  PointerToRelocations = 0
00000154    00000000    DD 00000000          ;  PointerToLineNumbers = 0
00000158    0000        DW 0000              ;  NumberOfRelocations = 0
0000015A    0000        DW 0000              ;  NumberOfLineNumbers = 0
0000015C    600000E0    DD E0000060          ;  Characteristics = CODE|INITIALIZED_DATA|EXECUTE|READ|WRITE

上面这个例子把VirtualSize改成没有对齐了,发现程序图标也没了,windows还load不起来了,这个地方为什么不能运行是因为我们把VirtualSize调大了,占了第二个节的地方了,如果调小的话,则可以运行,可以看出这个字段的效验是不跨越其它节地界,这个字段只要不跨越其它节地界,为任何值都可以,0也不例外,这个值除了用来效验,没有其它用

示例4:

节表信息如下:
00000138    2E 55 70 61>ASCII ".Upack"       ; SECTION
00000140    00800000    DD 00008000          ;  VirtualSize = 8000 (32768.)
00000144    00110000    DD 00001100          ;  VirtualAddress = 1100
00000148    B7000000    DD 000000B7          ;  SizeOfRawData = B7 (183.)
0000014C    11000000    DD 00000011          ;  PointerToRawData = 11
00000150    00000000    DD 00000000          ;  PointerToRelocations = 0
00000154    00000000    DD 00000000          ;  PointerToLineNumbers = 0
00000158    0000        DW 0000              ;  NumberOfRelocations = 0
0000015A    0000        DW 0000              ;  NumberOfLineNumbers = 0
0000015C    600000E0    DD E0000060          ;  Characteristics = CODE|INITIALIZED_DATA|EXECUTE|READ|WRITE

这个示例跟示例3一样,图标没了,windows也load不起来了,VirtualAddress这个字段也是要严格效验的

好了,下面来看最后一个节的情况(以下均为最后一个节了)

示例5:

节表信息如下:
00000160    2E 72 73 72>ASCII ".rsrc"        ; SECTION
00000168    00500000    DD 00005000          ;  VirtualSize = 5000 (20480.)
0000016C    00900000    DD 00009000          ;  VirtualAddress = 9000
00000170    48320000    DD 00003248          ;  SizeOfRawData = 3248 (12872.)
00000174    00020000    DD 00000200          ;  PointerToRawData = 200
00000178    00000000    DD 00000000          ;  PointerToRelocations = 0
0000017C    00000000    DD 00000000          ;  PointerToLineNumbers = 0
00000180    0000        DW 0000              ;  NumberOfRelocations = 0
00000182    0000        DW 0000              ;  NumberOfLineNumbers = 0
00000184    600000E0    DD E0000060          ;  Characteristics = CODE|INITIALIZED_DATA|EXECUTE|READ|WRITE
这个节是upack v0.32加壳后程序的最后一个节,是好的,可见SizeOfRawData也没有对齐,这说明最后一个节SizeOfRawData可以不对齐

示例6:这个示例我们让PointerToRawData不对齐看看

节表信息如下:
00000160    2E 72 73 72>ASCII ".rsrc"        ; SECTION
00000168    00500000    DD 00005000          ;  VirtualSize = 5000 (20480.)
0000016C    00900000    DD 00009000          ;  VirtualAddress = 9000
00000170    48320000    DD 00003248          ;  SizeOfRawData = 3248 (12872.)
00000174    10020000    DD 00000210          ;  PointerToRawData = 210
00000178    00000000    DD 00000000          ;  PointerToRelocations = 0
0000017C    00000000    DD 00000000          ;  PointerToLineNumbers = 0
00000180    0000        DW 0000              ;  NumberOfRelocations = 0
00000182    0000        DW 0000              ;  NumberOfLineNumbers = 0
00000184    600000E0    DD E0000060          ;  Characteristics = CODE|INITIALIZED_DATA|EXECUTE|READ|WRITE
这么一改,程序图标又没了,windows也load不起来了,这是因为我们加大了PointerToRawData,导致SizeOfRawData + PointerToRawData > 文件长度了,所以windows不让load了,如果将其改小的话,可以load,但是会出现什么错误视具体程序定

下面还是冗余的改下VirtualSize和VirtualAddress字段吧,看看如何

示例7:

节表信息如下:
00000160    2E 72 73 72>ASCII ".rsrc"        ; SECTION
00000168    00500000    DD 00005000          ;  VirtualSize = 5000 (20480.)
0000016C    00910000    DD 00009100          ;  VirtualAddress = 9100
00000170    48320000    DD 00003248          ;  SizeOfRawData = 3248 (12872.)
00000174    00020000    DD 00000200          ;  PointerToRawData = 200
00000178    00000000    DD 00000000          ;  PointerToRelocations = 0
0000017C    00000000    DD 00000000          ;  PointerToLineNumbers = 0
00000180    0000        DW 0000              ;  NumberOfRelocations = 0
00000182    0000        DW 0000              ;  NumberOfLineNumbers = 0
00000184    600000E0    DD E0000060          ;  Characteristics = CODE|INITIALIZED_DATA|EXECUTE|READ|WRITE
让VirtualAddress不对齐后,程序图标又没了,windows也load不起来了,可见最后一个节的VirtualAddress也有严格的效验

示例8:

节表信息如下:
00000160    2E 72 73 72>ASCII ".rsrc"        ; SECTION
00000168    10500000    DD 00005010          ;  VirtualSize = 5010 (20496.)
0000016C    00900000    DD 00009000          ;  VirtualAddress = 9000
00000170    48320000    DD 00003248          ;  SizeOfRawData = 3248 (12872.)
00000174    00020000    DD 00000200          ;  PointerToRawData = 200
00000178    00000000    DD 00000000          ;  PointerToRelocations = 0
0000017C    00000000    DD 00000000          ;  PointerToLineNumbers = 0
00000180    0000        DW 0000              ;  NumberOfRelocations = 0
00000182    0000        DW 0000              ;  NumberOfLineNumbers = 0
00000184    600000E0    DD E0000060          ;  Characteristics = CODE|INITIALIZED_DATA|EXECUTE|READ|WRITE
让VirtualSize不对齐后,程序图标还有(我们是加大了VirtualSize,如果减小,估计就会没了,555,失算了,把它改成0,还有图标),但是windows load不起来了,如果把它改成0x4500也可以运行,这里调大了,导致最后一个节的VirtualAddress + VirtualSize > SizeOfImage了,因此load不起来,这种情况windows也是要效验的

下面给出这些属性的效验代码:

//pe check函数
//合法返回0,否则-1
//lpExePEBuff是pe文件地址
//nExePELen是pe文件长度
long pe_check(char *lpExePEBuff, unsigned long nExePELen)
{
        unsigned long lSectionNum;
        unsigned long lFileAlign;
        unsigned long lFileAlignMask;
        unsigned long lSectionAlignMask;
        unsigned long nPointerToRawData;
        unsigned long nSizeOfRawData;
        unsigned long nSizeOfImage;
        unsigned long nIndex;

        IMAGE_DOS_HEADER *imDos_Headers;
        IMAGE_NT_HEADERS * pINH;
       
        IMAGE_SECTION_HEADER *pISH;
        IMAGE_SECTION_HEADER * pOldEndISH;

        //MZ PE标志效验省去
        imDos_Headers = (IMAGE_DOS_HEADER *)lpExePEBuff;
        pINH = (IMAGE_NT_HEADERS *)((char *)lpExePEBuff + imDos_Headers->e_lfanew);//NT头指针地址
       
        //取PE文件的节数量
        lSectionNum = pINH->FileHeader.NumberOfSections;
       
        pISH = (IMAGE_SECTION_HEADER *)((char *)pINH + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + pINH->FileHeader.SizeOfOptionalHeader);
        pOldEndISH = pISH + lSectionNum - 1;

        //SizeOfImage按对齐属性向上取整
        nSizeOfImage = pINH->OptionalHeader.SizeOfImage;
        //各节在磁盘中的对齐掩码
        lSectionAlignMask = pINH->OptionalHeader.SectionAlignment - 1;  //各节在load后内存中的对齐掩码
        nSizeOfImage = (nSizeOfImage + lSectionAlignMask) & (0xffffffff ^ lSectionAlignMask);

        //效验最后节VirtualSize是否越界SizeOfImage
        if(pOldEndISH->VirtualAddress + pOldEndISH->Misc.VirtualSize > nSizeOfImage)
        {
                return -1;
        }

        //貌似FileAlignment无用,系统好像是用0x200,只要是0x200整数倍,不大于0x1000,程序都可以运行
        lFileAlign = g_pINH->OptionalHeader.FileAlignment;
        if(lFileAlign < 0x200 && lFileAlign > 0x1000)
        {
                return -1;
        }
        if(lFileAlign % 0x200)
        {
                return -1;
        }
        lFileAlign = 0x200;
       
        lFileAlignMask = lFileAlign - 1;                                                                       
        for(nIndex = 0; nIndex < lSectionNum; nIndex++, pISH++)
        {
                //效验VirtualAddress对齐属性
                if(pISH->VirtualAddress & lSectionAlignMask)
                {
                        //出现非法节
                        return -1;
                }

                //效验要装载磁盘数据是否超出文件大小
                if(pISH->PointerToRawData + pISH->SizeOfRawData > nExePELen)
                {
                        return -1;
                }

                //效验VirtualSize是否跨入下一节地界
                if(pISH != pOldEndISH)
                {
                        if(pISH->VirtualAddress + pISH->Misc.VirtualSize > (pISH + 1)->VirtualAddress)
                        {
                                //出现非法节
                                return -1;
                        }
                }

                //不管对不对齐均重算PE节磁盘地址,磁盘中大小信息
                nPointerToRawData = pISH->PointerToRawData & (0xffffffff ^ lFileAlignMask);
                nSizeOfRawData = (pISH->SizeOfRawData + lFileAlignMask) & (0xffffffff ^ lFileAlignMask);
                //nSizeOfRawData要跟磁盘中剩余长度比较,取小者
                if(nSizeOfRawData > nExePELen - nPointerToRawData)
                {
                        nSizeOfRawData = nExePELen - nPointerToRawData;
                }

                if(pISH != pOldEndISH)
                {

                        //发现这个VirtualSize没有用,用0程序也可以运行,这里效验如下
                        nVirtualSize = (pISH + 1)->VirtualAddress - pISH->VirtualAddress;
                        //nSizeOfRawData大于nVirtualSize也不行
                        if(nSizeOfRawData > nVirtualSize)
                        {
                                return -1;
                        }
                }

                //如果要load的话,是用nSizeOfRawData/nPointerToRawData
        }
       
        return 0;
}

【  总结  】

1.VirtualSize可以不对齐,但是它表示的值不能跨到其它节地界

2.VirtualAddress在任何节中也都要对齐

3.SizeOfRawData没有对齐要求,如不对齐,按这个公式重算:SizeOfRawData = (SizeOfRawData + FileAlignmentMask) & (0xffffffff ^ FileAlignmentMask);

4.PointerToRawData没有对齐要求,如不对齐,按这个公式重算:PointerToRawData = PointerToRawData & (0xffffffff ^ FileAlignmentMask);

[课程]Android-CTF解题方法汇总!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (19)
雪    币: 1746
活跃值: (287)
能力值: (RANK:450 )
在线值:
发帖
回帖
粉丝
2
修正了这个帖子中程序的一处bug,这个bug估计很多向我一样的菜鸟都会犯吧,那就是怎么求节表开始地址:

我以前一直用这个方法求节表开始地址:PE标志地址 + sizeof(IMAGE_NT_HEADERS);

刚才load upack v0.36时,发现不是这样的,跟踪了下PETools,发现是用这个方法求的:PE标志地址 + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + pINH->FileHeader.SizeOfOptionalHeader;

哈哈,看来今天收获不小:)
2007-5-5 16:04
0
雪    币: 236
活跃值: (11)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
3
先顶再说~
2007-5-5 17:34
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
4
以下引用大牛的话------------------------------
1. 如果 FileAlignment 小于 200h,则要求 FileAlignment == SectionAlignment >= 2

2. 如果 FileAlignment 小于 200h,则要求 VirtualAddress == PointerToRawData

3. VirtualSize <= SizeOfRawData

4. SizeOfHeaders < SizeOfImage

5. NumberOfRvaAndSizes >= 2 数据目录结构的数量要求不小于 2

6. 节表和输入表都要求有一个结束的全 0 成员

by 一块三毛钱
2007-5-28 12:20
0
雪    币: 304
活跃值: (82)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
5
根本原因在于,在某些被加壳的程序里,FileHeader.SizeOfOptionalHeader的值并不是标准的0xE0
2007-5-28 13:26
0
雪    币: 1746
活跃值: (287)
能力值: (RANK:450 )
在线值:
发帖
回帖
粉丝
6
4楼  学习了
2007-5-28 21:09
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
学习!!!!!!
2007-6-28 15:05
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
学习中!呵呵!
2007-7-3 10:10
0
雪    币: 193
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
找到好东西了,被PE的各种解释都快搞糊涂了,先研究下楼主的文章,再去一块三毛钱的主页去看看!
2007-8-7 09:29
0
雪    币: 193
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
"说下FileAlignment字段吧,这个字段在有些程序可以看到是0x1000等,我通过试验,好像发现这个字段不管是什么值,系统都用0x200,不过它必须大于等于0x200,小于等于0x1000,并为0x200整数倍"这个好像win2000不是这样的?
2007-8-10 11:22
0
雪    币: 57
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
好好学习,天天向上,谢谢
2007-9-25 17:23
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
貌似有道理,那些制造最小字节PE的程序,不是都用32字节文件对齐吗!
2007-9-26 09:16
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
看来这篇文的迷雾很厚啊

来位大牛来评述一下,要不这个结果就...
2007-9-26 09:19
0
雪    币: 1746
活跃值: (287)
能力值: (RANK:450 )
在线值:
发帖
回帖
粉丝
14
制造最小PE文件,貌似跟文件对齐属性关系不大,文件对齐属性主要用来决定怎么load文件的,刚来修正了下文章,加入了对SizeOfImage的向上取整,也搞了一个小错误,目前这小段程序应该经历了近400个小版本壳的考验,潜在的错误还有待发掘(水平有限,没逆过windows的loader,基本上都是总结的,错误在所难免),目前工作良好,当然这都是在xp sp2上的测试结果,在其它平台上怎么样,没有测试过,尤其是2000系统

下面对4楼给出的文字进行评论下,测试平台xp sp2,其它平台不清楚,没测试

以下引用大牛的话------------------------------
1. 如果 FileAlignment 小于 200h,则要求 FileAlignment == SectionAlignment >= 2

2. 如果 FileAlignment 小于 200h,则要求 VirtualAddress == PointerToRawData

满足以上两个条件,在xp sp2上程序无法运行,提示不是有效win32应用程序

3. VirtualSize <= SizeOfRawData

第三个条件不满足,在xp sp2上程序可以正常运行

4. SizeOfHeaders < SizeOfImage

5. NumberOfRvaAndSizes >= 2 数据目录结构的数量要求不小于 2

6. 节表和输入表都要求有一个结束的全 0 成员

第6个条件,在xp sp2平台上,节表和输入表都可以不以全0成员结束,程序可以正常运行

再次声明,以上只是盗版xp sp2的测试结果,其它平台没有测试过
2007-9-26 21:36
0
雪    币: 1746
活跃值: (287)
能力值: (RANK:450 )
在线值:
发帖
回帖
粉丝
15
在2000下粗测了下,结论和上面一致
2007-9-26 21:45
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
16
好像align4可以
输入表不结束时什么,哪个field是0?
2007-9-27 09:41
0
雪    币: 1746
活跃值: (287)
能力值: (RANK:450 )
在线值:
发帖
回帖
粉丝
17
我目前测试的情况是小于0x200都有问题,程序无法运行

导入表有效项后不以全0结束在dxpack v1.0加壳后程序中可以看到,好象yzpack v1.1中也可以看到,记不太清楚了
2007-9-27 13:17
0
雪    币: 6075
活跃值: (2236)
能力值: (RANK:1060 )
在线值:
发帖
回帖
粉丝
18
一块三毛钱手工造的那个pe好像是4
见过一个老外的好像70~ bytes
2007-9-27 15:10
0
雪    币: 217
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
不同的操作系统是有点不一样的,可能是2000的系统判断没那么严格

看看windows源码里面的imagechk.c就知道大概是怎么回事了
比如

  NumberOfSubsections = NtHeader->FileHeader.NumberOfSections;
  PreferredImageBase = NtHeader->OptionalHeader.ImageBase;
  
  //
  // At this point the object table is read in (if it was not
  // already read in) and may displace the image header.
  //
  
  OffsetToSectionTable = sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER) + NtHeader->FileHeader.SizeOfOptionalHeader;

  SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader + OffsetToSectionTable);
  
  if (ImageAlignment < PageSize)
  {
    // The image header is no longer valid, TempPte is
    // used to indicate that this image alignment is
    // less than a PageSize.
   
    //
    // Loop through all sections and make sure there is no
    // unitialized data.
    //
   
    while (NumberOfSubsections > 0)
    {
      if (SectionTableEntry->Misc.VirtualSize == 0)
      {
        SectionVirtualSize = SectionTableEntry->SizeOfRawData;
      }
      else
      {
        SectionVirtualSize = SectionTableEntry->Misc.VirtualSize;
      }
      
      //
      // If the pointer to raw data is zero and the virtual size
      // is zero, OR, the section goes past the end of file, OR
      // the virtual size does not match the size of raw data, then
      // return an error.
      //
      
      if (((SectionTableEntry->PointerToRawData != SectionTableEntry->VirtualAddress))
        ||
        ((SectionTableEntry->SizeOfRawData + SectionTableEntry->PointerToRawData) >
        FileInfo.nFileSizeLow)
        ||
        (SectionVirtualSize > SectionTableEntry->SizeOfRawData))
      {
        printf("invalid BSS/Trailingzero section/file size\n");
        
        ImageOk = FALSE;
        goto NeImage;
      }
      SectionTableEntry += 1;
      NumberOfSubsections -= 1;
    }
    goto PeReturnSuccess;
  }

其实没什么秘密
2007-9-28 15:20
0
雪    币: 419
活跃值: (188)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
20
你们仔细编程试验了没有?在XP下 FileAlignment 字段可靠!!
2007-11-6 13:12
0
游客
登录 | 注册 方可回帖
返回
//