这个代码是在网上找到,
实现给PE文件增加区段,
对应的参数是   文件路径,新建区段名和新建的区段大小
请帮忙修改一下,修改成不增加区段,而是在最后一个区段的末尾加上0x2000大小的空间。
也就是相当于把新建的区段的空间加到最后一个区段的末尾。源码如下:修改后可发送到 [email protected]
也可以直接回贴。
谢谢了
结贴率100%
procedure AddSection(lFileName,secname,secsize: string; lBackup: boolean); //打开exe文件,是否备份
var
    hFile: THandle; //文件句柄
    ImageDosHeader: IMAGE_DOS_HEADER; //DOS部首
    ImageNtHeaders: IMAGE_NT_HEADERS; //映象头
    ImageSectionHeader: IMAGE_SECTION_HEADER; //块表
    lPointerToRawData: dword; //指向文件中的偏移
    lVirtualAddress: dword; //指向内存中的偏移
    i: integer; //循环变量
    p: integer;//自定义区段的字符串的长
    S: String;//除去自定义区段空格
    BytesRead, ByteSWrite: Cardinal; //读写用参数
    AttachSize: dword; //附加段大小
    AttachData, ChangeData: integer; //附加段填充数据
    OEP: integer; //使用过程中用到的OEP
    lpBuffer: array[0..1024 * 400] of byte; {数据存储缓冲区}
    StartEN, SizeEN, StartCr: dword; //PE修改后的物理地址和大小
    ret: boolean;begin
      //定义附加段填充数据
 AttachData := 0;
 S := Trim(secname);//除去自定义区段空格
 AttachSize := strtoint(secsize);//获取自定义的长度
 p :=Length(S);//得到自定义区段名字长度
 SetLength(arrText, p+2); //动态数组初始化
 SetLength(arrChar,p); arrText[0] :='.';
 for   i:=0   to   p-1  do
    begin
    arrText[i+1] :=secname[i+1] //动态数组下标从0开始,String类数组下标从1开始
    end;
    arrText[p+1] := #0;   //打开文件
    hFile := CreateFile(PChar(lFileName), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);  //校验
  if hFile = INVALID_HANDLE_VALUE then 
    begin
       ShowMessage('打开文件失败');
      exit;
   end;  //确认备份
  if lBackup then CopyFile(PChar(lFileName), PChar(lFileName + '.bak'), False);
    ret := False;
    try //读取DOS部首到ImageDosHeader
    ReadFile(hFile, ImageDosHeader, SizeOf(ImageDosHeader), BytesRead, nil);     //校验
   if ImageDosHeader.e_magic <> IMAGE_DOS_SIGNATURE then
        begin
            ShowMessage('不是有效的PE文件!');
            exit;
        end;    //指向映象头
        SetFilePointer(hFile, ImageDosHeader._lfanew, nil, FILE_BEGIN);    //读取映向头到ImageNtHeaders
        ReadFile(hFile, ImageNtHeaders, SizeOf(ImageNtHeaders), BytesRead, nil);    //校验
   if ImageNtHeaders.Signature <> IMAGE_NT_SIGNATURE then
        begin
           ShowMessage('不是有效的PE文件');
           exit;
        end;
{********************************}
{OEP=基址+原EP}
        OEP := ImageNtHeaders.OptionalHeader.ImageBase + ImageNtHeaders.OptionalHeader.AddressOfEntryPoint; {********************************}
   //初始化文件中偏移和映象中偏移
        lPointerToRawData := 0;
        lVirtualAddress := 0;        for i := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
        begin      //读取块表中信息
            ReadFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), BytesRead, nil);{********************************}
{查找原EP所在区段(原EP所在区段),记录物理偏移(初始地址),物理大小(长度)}
        if ImageNtHeaders.OptionalHeader.AddressOfEntryPoint > ImageSectionHeader.VirtualAddress then;
            begin
                StartEN := ImageSectionHeader.PointerToRawData;
                SecData := StartEN;
                SizeEN := ImageSectionHeader.SizeOfRawData; 
                StartCr := ImageNtHeaders.OptionalHeader.ImageBase + ImageSectionHeader.VirtualAddress;
           end; {********************************}  //计算文件中偏移
            if lPointerToRawData < ImageSectionHeader.PointerToRawData + ImageSectionHeader.SizeOfRawData then
                lPointerToRawData := ImageSectionHeader.PointerToRawData + ImageSectionHeader.SizeOfRawData;      //计算映象中偏移
      if lVirtualAddress < ImageSectionHeader.VirtualAddress + ImageSectionHeader.Misc.VirtualSize
 then                lVirtualAddress := ImageSectionHeader.VirtualAddress + ImageSectionHeader.Misc.VirtualSize;
        end;{增加块,定义块各项属性}
        Move(arrText[0], ImageSectionHeader.Name, p+2);  //设置初始属性
        ImageSectionHeader.Misc.VirtualSize := AttachSize;
        ImageSectionHeader.VirtualAddress := lVirtualAddress;
        ImageSectionHeader.SizeOfRawData := AttachSize;
        ImageSectionHeader.PointerToRawData := lPointerToRawData;
        ImageSectionHeader.PointerToRelocations := 0;
        ImageSectionHeader.PointerToLinenumbers := 0;
        ImageSectionHeader.NumberOfRelocations := 0;    //校正新节物理偏移(物理区块对齐)
        if ImageSectionHeader.VirtualAddress mod ImageNtHeaders.OptionalHeader.SectionAlignment > 0 then
          ImageSectionHeader.VirtualAddress := (ImageSectionHeader.VirtualAddress div ImageNtHeaders.OptionalHeader.SectionAlignment + 1) * ImageNtHeaders.OptionalHeader.SectionAlignment;    //校正新节映象偏移(映象中区块对齐)
        if ImageSectionHeader.Misc.VirtualSize mod ImageNtHeaders.OptionalHeader.SectionAlignment > 0 then
            ImageSectionHeader.Misc.VirtualSize := (ImageSectionHeader.Misc.VirtualSize div ImageNtHeaders.OptionalHeader.SectionAlignment + 1) * ImageNtHeaders.OptionalHeader.SectionAlignment;  //设置区块属性
        ImageSectionHeader.Characteristics := $E00000E0;    //保存区块信息
        WriteFile(hFile, ImageSectionHeader, SizeOf(ImageSectionHeader), ByteSWrite, nil);
 //校正内存映象大小
    ImageNtHeaders.OptionalHeader.SizeOfImage := ImageNtHeaders.OptionalHeader.SizeOfImage + ImageSectionHeader.Misc.VirtualSize;
  //更
    //校正块数目
      Inc(ImageNtHeaders.FileHeader.NumberOfSections);    //定位到映象头
      SetFilePointer(hFile, ImageDosHeader._lfanew, nil, FILE_BEGIN);  //保存校正过的映象头
       WriteFile(hFile, ImageNtHeaders, SizeOf(ImageNtHeaders), ByteSWrite, nil);    //定位到新节开始处
       SetFilePointer(hFile, ImageSectionHeader.PointerToRawData, nil, FILE_BEGIN);    //用00数据填充满新节
        for i := 1 to AttachSize do
        begin 
            WriteFile(hFile, PByte(@AttachData)^, 1, ByteSWrite, nil);
        end;  {填充自定义数据}
    //指向新节开始处
        SetFilePointer(hFile, ImageSectionHeader.PointerToRawData, nil, FILE_BEGIN);    
        WriteFile(hFile, OEP, 4, ByteSWrite, nil); //跳回OEP    //没有异常,显示增加区块成功!
        ShowMessage('增加区块成功!');    finally {8.退出}
   //关闭文件
     CloseHandle(hFile);
   end;end;

解决方案 »

  1.   

    {code by pathletboy}
    type
      SEC_RESULT = (
                    SEC_FILENOTFOUND, //文件未找到
                    SEC_NOTPE, //文件不是有效PE
                    SEC_SUCCESS  //成功
                    );function AddSection(const filename: string; size: Cardinal): SEC_RESULT;
    var
      f: TFileStream;
      dosheader: IMAGE_DOS_HEADER;
      ntheader:  IMAGE_NT_HEADERS;
      imageheader: IMAGE_SECTION_HEADER;
      buff: array of char;
    begin
      if not FileExists(filename) then
      begin
        Result := SEC_FILENOTFOUND;
        Exit;
      end;  f := TFileStream.Create(filename, fmOpenReadWrite);
      try
        f.Seek(0, soBeginning);
        if f.Size < $1000 then
        begin
          Result := SEC_NOTPE;
          Exit;
        end;
        f.Read(dosheader, SizeOf(IMAGE_DOS_HEADER ));
        if dosheader.e_magic <>  IMAGE_DOS_SIGNATURE then
        begin
          Result := SEC_NOTPE;
          Exit;
        end;
        f.Seek(dosheader._lfanew, soBeginning);
        f.Read(ntheader, SizeOf(IMAGE_NT_HEADERS));
        if ntheader.Signature <> IMAGE_NT_SIGNATURE then
        begin
          Result := SEC_NOTPE;
          Exit;
        end;    f.Seek( SizeOf(IMAGE_SECTION_HEADER) * (ntheader.FileHeader.NumberOfSections - 1), soFromCurrent);
        f.Read(imageheader, SizeOf(IMAGE_SECTION_HEADER));
        imageheader.SizeOfRawData := imageheader.SizeOfRawData + size;
        f.Seek(-SizeOf(IMAGE_SECTION_HEADER), soFromCurrent);
        f.Write(imageheader, SizeOf(IMAGE_SECTION_HEADER));
        f.Seek(0, soFromEnd);
        SetLength(buff, size);
        FillChar(buff[0], size, #0);
        f.Write(buff[0], size);
        Result := SEC_SUCCESS;
      finally
        f.Free;
      end;
    end;
    帮你写了下,调用
    AddSection('xxx.exe', $2000);
    参数1文件名、参数2添加的大小,返回值在上面个枚举自己判断处理吧。
      

  2.   

    to: pathletboy代码测试了,RweSize增加了$2000字节,但是Virtual Size 大小没有增加,我试着找imageheader的属性,里面也没有Virtual Size的属性  如下图所示
      

  3.   

    我试着找imageheader的参数。。里面没Virtual Size的属性
      

  4.   

    上面两个图,一个是用你给我的代码添加的$2000字节,其中Virtual Size=7F20第二个图是我用工具添加的Virtual Size=9F20
      

  5.   


    {code by pathletboy}
    type
      SEC_RESULT = (
                    SEC_FILENOTFOUND, //文件未找到
                    SEC_NOTPE, //文件不是有效PE
                    SEC_SUCCESS  //成功
                    );
     
    function AddSection(const filename: string; size: Cardinal): SEC_RESULT;
    var
      f: TFileStream;
      dosheader: IMAGE_DOS_HEADER;
      ntheader:  IMAGE_NT_HEADERS;
      imageheader: IMAGE_SECTION_HEADER;
      buff: array of char;
    begin
      if not FileExists(filename) then
      begin
        Result := SEC_FILENOTFOUND;
        Exit;
      end;
     
      f := TFileStream.Create(filename, fmOpenReadWrite);
      try
        f.Seek(0, soBeginning);
        if f.Size < $1000 then
        begin
          Result := SEC_NOTPE;
          Exit;
        end;
        f.Read(dosheader, SizeOf(IMAGE_DOS_HEADER ));
        if dosheader.e_magic <>  IMAGE_DOS_SIGNATURE then
        begin
          Result := SEC_NOTPE;
          Exit;
        end;
        f.Seek(dosheader._lfanew, soBeginning);
        f.Read(ntheader, SizeOf(IMAGE_NT_HEADERS));
        if ntheader.Signature <> IMAGE_NT_SIGNATURE then
        begin
          Result := SEC_NOTPE;
          Exit;
        end;    f.Seek( SizeOf(IMAGE_SECTION_HEADER) * (ntheader.FileHeader.NumberOfSections - 1), soFromCurrent);
        f.Read(imageheader, SizeOf(IMAGE_SECTION_HEADER));
        imageheader.Misc.VirtualSize := imageheader.Misc.VirtualSize + size;
        imageheader.SizeOfRawData := imageheader.SizeOfRawData + size;
        f.Seek(-SizeOf(IMAGE_SECTION_HEADER), soFromCurrent);
        f.Write(imageheader, SizeOf(IMAGE_SECTION_HEADER));
        f.Seek(0, soFromEnd);
        SetLength(buff, size);
        FillChar(buff[0], size, #0);
        f.Write(buff[0], size);
        Result := SEC_SUCCESS;
      finally
        f.Free;
      end;
    end;
      

  6.   

    还要修改一下镜象大小    f.Seek(dosheader._lfanew, soBeginning);
        f.Read(ntheader, SizeOf(IMAGE_NT_HEADERS));
        if ntheader.Signature <> IMAGE_NT_SIGNATURE then
        begin
          ShowMessage('文件不是有效PE');
          Exit;
        end;
        ntheader.OptionalHeader.SizeOfImage := ntheader.OptionalHeader.SizeOfImage + $2000;
        f.Seek( SizeOf(IMAGE_SECTION_HEADER) * (ntheader.FileHeader.NumberOfSections - 1), soFromCurrent);
        f.Read(imageheader, SizeOf(IMAGE_SECTION_HEADER));
        imageheader.SizeOfRawData := imageheader.SizeOfRawData + size;
        f.Seek(-SizeOf(IMAGE_SECTION_HEADER), soFromCurrent);
        f.Write(imageheader, SizeOf(IMAGE_SECTION_HEADER));
        f.Seek(0, soFromEnd);
        SetLength(buff, size);
        FillChar(buff[0], size, #0);
    ntheader.OptionalHeader.SizeOfImage := ntheader.OptionalHeader.SizeOfImage + $2000;这一句,为什么写了后没有效果呢
      

  7.   

    ntheader.OptionalHeader.SizeOfImage := ntheader.OptionalHeader.SizeOfImage + $2000;这句怎么才能生效?
      

  8.   


    {code by pathletboy}
    type
      SEC_RESULT = (
                    SEC_FILENOTFOUND, //文件未找到
                    SEC_NOTPE, //文件不是有效PE
                    SEC_SUCCESS  //成功
                    );function AddSection(const filename: string; size: Cardinal): SEC_RESULT;
    var
      f: TFileStream;
      dosheader: IMAGE_DOS_HEADER;
      ntheader:  IMAGE_NT_HEADERS;
      imageheader: IMAGE_SECTION_HEADER;
      buff: array of char;
    begin
      if not FileExists(filename) then
      begin
        Result := SEC_FILENOTFOUND;
        Exit;
      end;  f := TFileStream.Create(filename, fmOpenReadWrite);
      try
        f.Seek(0, soBeginning);
        if f.Size < $1000 then
        begin
          Result := SEC_NOTPE;
          Exit;
        end;
        f.Read(dosheader, SizeOf(IMAGE_DOS_HEADER ));
        if dosheader.e_magic <>  IMAGE_DOS_SIGNATURE then
        begin
          Result := SEC_NOTPE;
          Exit;
        end;
        f.Seek(dosheader._lfanew, soBeginning);
        f.Read(ntheader, SizeOf(IMAGE_NT_HEADERS));
        if ntheader.Signature <> IMAGE_NT_SIGNATURE then
        begin
          Result := SEC_NOTPE;
          Exit;
        end;
        ntheader.OptionalHeader.SizeOfImage := ntheader.OptionalHeader.SizeOfImage + $2000;
        f.Seek(-SizeOf(IMAGE_NT_HEADERS), soFromCurrent);
        f.Write(ntheader, SizeOf(IMAGE_NT_HEADERS));    f.Seek( SizeOf(IMAGE_SECTION_HEADER) * (ntheader.FileHeader.NumberOfSections - 1), soFromCurrent);
        f.Read(imageheader, SizeOf(IMAGE_SECTION_HEADER));
        imageheader.Misc.VirtualSize := imageheader.Misc.VirtualSize + size;
        imageheader.SizeOfRawData := imageheader.SizeOfRawData + size;
        f.Seek(-SizeOf(IMAGE_SECTION_HEADER), soFromCurrent);
        f.Write(imageheader, SizeOf(IMAGE_SECTION_HEADER));
        f.Seek(0, soFromEnd);
        SetLength(buff, size);
        FillChar(buff[0], size, #0);
        f.Write(buff[0], size);
        Result := SEC_SUCCESS;
      finally
        f.Free;
      end;
    end;