⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exeimage.pas

📁 你用过ExeScope吗?它是能够将Exe文件中的资源进行查看并修改的工具
💻 PAS
📖 第 1 页 / 共 5 页
字号:
  i:=ACount mod Max_Buf;
  if  i>0 then
  begin
     FExeStream.Read(ResBuffer,i);
     tmpSegStream.Write(ResBuffer,i);
  end;
  result:=tmpSegStream;
end;

{ 返回资源中经过处理的光标文件流 }
function  TExeImage.GetCursorStream(AOffset, ACount, HeaderOffset,NameID: Integer): TMemoryStream;
const
  Max_Buf = 1024;
var
  tmpSegStream: TMemoryStream;
  tmpIconFileHeader: TIconFileHeader;
  tmpIconHeader: TIconHeader;
  dBitCount: Word;
  tmpCursorResInfo: TCursorResInfo;
  ResBuffer:array[0..Max_Buf-1] of Byte;
  i:Integer;
begin
  FExeStream.Seek(HeaderOffset,soFromBeginning);
  FExeStream.Read(tmpIconHeader,SizeOf(tmpIconHeader));

  with tmpIconFileHeader do
  begin
    idReserved:=0;
    idType:=1;//实际保存成文件时将此标记为2;
    idCount:=1;
    dwImageOffset:=SizeOf(tmpIconFileHeader);
    bReserved:=0;
  end;
  for i:=0 to tmpIconHeader.wCount-1 do
  begin
    FExeStream.Read(tmpCursorResInfo,SizeOf(tmpCursorResInfo));
    if tmpCursorResInfo.wNameOrdinal=NameID then
    begin
      with tmpIconFileHeader do
      begin
        bWidth := tmpCursorResInfo.wWidth;
        bHeight:= tmpCursorResInfo.wHeight div 2;
        dwBytesInRes:=tmpCursorResInfo.lBytesInRes-2*SizeOf(dBitCount);  //此值应该=ACount-4;
        //wPlanes:=tmpIconResInfo.wPlanes;
        //wBitCount:=tmpIconResInfo.wBitCount;
        //bColorCount:=tmpIconResInfo.bColorCount;
      end;
      break;
    end;
  end;

  FExeStream.Seek(AOffSet,soFromBeginning);
  FExeStream.Read(dBitCount,SizeOf(dBitCount));
  tmpIconFileHeader.wPlanes  := dBitCount;
  FExeStream.Read(dBitCount,SizeOf(dBitCount));
  tmpIconFileHeader.wBitCount:= dBitCount;
  ACount:=tmpCursorResInfo.lBytesInRes-2*SizeOf(dBitCount);// ACount-2*SizeOf(dBitCount);

  tmpSegStream:=TMemoryStream.Create;
  tmpSegStream.SetSize(ACount+SizeOf(tmpIconFileHeader));
  tmpSegStream.Write(tmpIconFileHeader,SizeOf(tmpIconFileHeader));

  if ACount>=Max_Buf then
  for i:=0 to (ACount div Max_Buf)-1 do
  begin
     FExeStream.Read(ResBuffer,Max_Buf);
     tmpSegStream.Write(ResBuffer,Max_Buf);
  end;
  i:=ACount mod Max_Buf;
  if  i>0 then
  begin
     FExeStream.Read(ResBuffer,i);
     tmpSegStream.Write(ResBuffer,i);
  end;

  result:=tmpSegStream;
end;

{ 返回资源中经过处理的图标文件流 }
function  TExeImage.GetIconStream(AOffset, ACount, HeaderOffset,NameID: Integer): TMemoryStream;
Const
  Max_Buf=1024;
var
  tmpSegStream: TMemoryStream;
  tmpIconFileHeader: TIconFileHeader;
  tmpIconHeader: TIconHeader;
  tmpIconResInfo: TIconResInfo;
  ResBuffer:array[0..Max_Buf-1] of Byte;
  i:Integer;
begin
  FExeStream.Seek(HeaderOffset,soFromBeginning);
  FExeStream.Read(tmpIconHeader,SizeOf(tmpIconHeader));

  with tmpIconFileHeader do
  begin
    idReserved:=0;
    idType:=1;
    idCount:=1;
    dwImageOffset:=SizeOf(tmpIconFileHeader);
    bReserved:=0;
  end;
  for i:=0 to tmpIconHeader.wCount-1 do
  begin
    FExeStream.Read(tmpIconResInfo,SizeOf(tmpIconResInfo));
    if tmpIconResInfo.wNameOrdinal=NameID then
    begin
      with tmpIconFileHeader do
      begin
        bWidth := tmpIconResInfo.bWidth;
        bHeight := tmpIconResInfo.bHeight;
        dwBytesInRes:=tmpIconResInfo.lBytesInRes;  //此值应该=ACount;
        wPlanes:=tmpIconResInfo.wPlanes;
        wBitCount:=tmpIconResInfo.wBitCount;
        bColorCount:=tmpIconResInfo.bColorCount;
      end;
      break;
    end;
  end;

  tmpSegStream:=TMemoryStream.Create;
  tmpSegStream.SetSize(ACount+SizeOf(tmpIconFileHeader));
  tmpSegStream.Write(tmpIconFileHeader,SizeOf(tmpIconFileHeader));

  FExeStream.Seek(AOffSet,soFromBeginning);
  if ACount>=Max_Buf then
  for i:=0 to ACount div Max_Buf do
  begin
     FExeStream.Read(ResBuffer,Max_Buf);
     tmpSegStream.Write(ResBuffer,Max_Buf);
  end;
  i:=ACount mod Max_Buf;
  if  i>0 then
  begin
     FExeStream.Read(ResBuffer,i);
     tmpSegStream.Write(ResBuffer,i);
  end;
  result:=tmpSegStream;
end;

{ 判断资源数据是否有 }
function TExeImage.IsResourceExists: Boolean;
var
  i,j:Word;
  tmpStr: String;
  IsResExists:Boolean;
begin
  IsResExists:=false;
  //检测是否有资源节表[简单以名称来判断,此办法对某些文件无效]
  for i:=0 to FPENTHead.FileHeader.NumberOfSections-1 do
  begin
    { section name }
    tmpStr:='';
    for j:=0 to 7 do
        tmpStr:=tmpStr+ Chr(FPESectionHead[i].Name[j]);
    { check resource directory }
    if TmpStr='.rsrc'+#0+#0+#0 then
    begin
      FResourceInSectionIndex:=i;
      IsResExists:=true;
      break;
    end;
  end;

  Result:=IsResExists;
  
end;

{ 遍历资源目录获取资源数据的个数 }
function TExeImage.GetResDataNum: Word;
var
  ResNum :  Word;
  i,iNum,jNum:Integer;
  myOffSet,tmpOffSet:Cardinal; { 资源目录物理地址 }
  ResDir:array of TImageResourceDirectory;
  PEResourceDirectory:TImageResourceDirectory;
begin
  //tmpVirtualAddress := FPESectionHead[FResourceInSectionIndex].VirtualAddress;
  tmpOffset := FPESectionHead[FResourceInSectionIndex].PointerToRawData;
  resNum:=0;
  FExeStream.Seek(tmpOffSet,0);
  FExeStream.Read(PEResourceDirectory,SizeOf(PEResourceDirectory));

  iNum:=PEResourceDirectory.NumberOfNamedEntries +
          PEResourceDirectory.NumberOfIdEntries;

  if iNum>0 then
  begin
    SetLength(ResDir,iNum);

    tmpOffSet:=tmpOffSet+SizeOf(PEResourceDirectory)
               +(iNum)*SizeOf(TImageResourceDirectoryEntry);
    MyOffSet:=0;
    ResNum:=0;
    for i:=0 to iNum-1 do
    begin
      FExeStream.Seek(tmpOffSet+myOffSet,0);
      FExeStream.Read(ResDir[i],SizeOf(ResDir[i]));
      jNum:=ResDir[i].NumberOfNamedEntries+ResDir[i].NumberOfIdEntries;
      ResNum := ResNum + jNum;
      MyOffSet := MyOffSet + SizeOf(ResDir[i])
                + jNum * SizeOf(TImageResourceDirectoryEntry);
    end;
  end;

  result:=resNum;
end;

{****************************************************

 GetResourceDataDir 返回资源数据目录

 在调用之后需要检测一下ResDataNum是否为0,如果为0,则
 变体的值为空。

****************************************************}
function TExeImage.GetResourceDataDir: Variant;
var
  v: Variant;
  iNum,jNum,i,j:Integer;
  TmpPos:LongInt;    { 文件临时位置 }
  TmpStr:String;     { 临时字符串 }
  tmpResName,tmpResType:String;
  CurResDataNum:Word;
  tmpOffSet,tmpSize:DWord;

  PEResourceDirectoryPointerToRawData:Cardinal;{ 资源目录物理地址 }
  PEResourceDirectoryVirtualAddress:Cardinal;  { 资源相对实际地址 }

  PEResourceDirectory:TImageResourceDirectory;
  PEResDataEnt:TImageResourceDataEntry;

  PEResourceDirStringU:TImageResourceDirStringU;
  ResWName:array[0..MAX_PATH] of WChar;
  ResSName:WideString;             { PEResourceDirStringU.Name for String }
  iName:Integer;

  ResDir_1:array of TImageResourceDirectory;
  ResDir_2:TImageResourceDirectory;
  ResdirEnt_1,ResdirEnt_2:array of TImageResourceDirectoryEntry;
  ResdirEnt_3:TImageResourceDirectoryEntry;
begin
  if FResDataNum=0 then
  begin
    result:=null;
    exit;
  end;

  PEResourceDirectoryVirtualAddress:=FPESectionHead[FResourceInSectionIndex].VirtualAddress;
  PEResourceDirectoryPointerToRawData:=FPESectionHead[FResourceInSectionIndex].PointerToRawData;

  v:=VarArrayCreate([0,FResDataNum-1],VarVariant);

  FExeStream.Seek(PEResourceDirectoryPointerToRawData,0);
  FExeStream.Read(PEResourceDirectory,SizeOf(PEResourceDirectory));
  iNum:=PEResourceDirectory.NumberOfNamedEntries+
            PEResourceDirectory.NumberOfIdEntries;

  SetLength(ResDir_1,iNum);
  SetLength(ResDirEnt_1,iNum);
  for i:=0 to iNum-1 do
    FExeStream.Read(ResDirEnt_1[i],SizeOf(ResDirEnt_1[i]));

  CurResDataNum:=0;
  for i:=0 to iNum-1 do
  begin
    FExeStream.Read(ResDir_1[i],SizeOf(ResDir_1[i]));
    //获取资源类型
    if (ResDirEnt_1[i].Name and $80000000)=0 then
    begin       { 最高位为 0 ,剩余的 31 位为一个整数ID }
      tmpResType := CheckResourceType(ResDirEnt_1[i].Name);
    end else    { 最高位为 1 ,剩下 31 位为 IMAGE_RESOURCE_DIR_STRING_U 结构的偏移位置 从 Resource Section 开始 }
    begin
      TmpPos:=FExeStream.Seek(0,1);  { 记忆文件位置 }
      FExeStream.Seek(ResDirEnt_1[i].Name and $7FFFFFFF
                      +PEResourceDirectoryPointerToRawData,
                       soFromBeginning);
      FExeStream.Read(PEResourceDirStringU,SizeOf(PEResourceDirStringU));
      FExeStream.Read(ResWName,(PEResourceDirStringU.Length-1)*2);
      ResSName:=PEResourceDirStringU.NameString;
      for iName:=0 to PEResourceDirStringU.Length-2 do
          ResSName:=ResSName+ResWName[iName];
      FExeStream.Seek(TmpPos,0);     { 恢复文件位置 i 位置 }
      tmpResType := ResSName;
    end;
    jNum:=ResDir_1[i].NumberOfNamedEntries+ResDir_1[i].NumberOfIdEntries;
    SetLength(ResDirEnt_2,jNum);
    for j:=0 to jNum-1 do
    begin
      FExeStream.Read(ResDirEnt_2[j],SizeOf(ResDirEnt_2[j]));
      TmpPos:=FExeStream.Seek(0,1);  { 保存地址 }
      FExeStream.Seek(PEResourceDirectoryPointerToRawData+ResDirEnt_2[j].OffsetToData-$80000000,0);
      FExeStream.Read(ResDir_2,SizeOf(ResDir_2));
      FExeStream.Read(ResDirEnt_3,SizeOf(ResDirEnt_3));
      //获取指定类型的资源名称:
      if (ResDirEnt_2[j].Name and $80000000)=0 then
      begin       { 最高位为 0 ,剩余的 31 位为一个整数ID }
        tmpResName := Format('%u',[ResDirEnt_2[j].Name]);
      end else    { 最高位为 1 ,剩下 31 位为 IMAGE_RESOURCE_DIR_STRING_U 结构的偏移位置 从 Resource Section 开始 }
      begin
        FExeStream.Seek(ResDirEnt_2[j].Name and $7FFFFFFF
                         +PEResourceDirectoryPointerToRawData,
                         soFromBeginning);
        FExeStream.Read(PEResourceDirStringU,SizeOf(PEResourceDirStringU));
        FExeStream.Read(ResWName,(PEResourceDirStringU.Length-1)*2);
        ResSName:=PEResourceDirStringU.NameString;
        for iName:=0 to PEResourceDirStringU.Length-2 do
          ResSName:=ResSName+ResWName[iName];
        tmpResName := ResSName;
      end;

      { 最终的资源位置 }
      FExeStream.Seek(ResDirEnt_3.OffsetToData+PEResourceDirectoryPointerToRawData,0);
      FExeStream.Read(PEResDataEnt,SizeOf(PEResDataEnt));

      {  存在资源,需要一一解析出来存到
        v[x][0]=资源类型,
        v[x][1]=资源名称,
        v[x][2]=偏移量
        v[x][3]=大小
        v[x][4]=父类
        v[x][5]=描述
      }
      tmpOffSet := PEResourceDirectoryPointerToRawData
                    +PEResDataEnt.OffsetToData
                    -PEResourceDirectoryVirtualAddress;
      tmpSize := PEResDataEnt.Size;
      v[CurResDataNum]:=VarArrayOf([tmpResType,tmpResName,tmpOffSet,tmpSize]);
      inc(CurResDataNum);
      FExeStream.Seek(TmpPos,0);
    end;
  end;
  result:=v;
end;

function TExeImage.AnalysisIconOrCursorGroupInfo(
  AOffset: Integer): Variant;
const
  IconFieldCount=8;
  CursorFieldCount=6;
var
  tmpVar: Variant;
  tmpStrType:String;
  tmpAddr: Integer; //地址
  tmpValue: String;//值
  tmpMemo: String;  //含义
  tmpIconHeader: TIconHeader;
  tmpIconResInfo: TIconResInfo;
  tmpCursorResInfo:TCursorResInfo;
  i: Word;
begin
  FExeStream.Seek(AOffset,0);
  FExeStream.Read(tmpIconHeader,SizeOf(tmpIconHeader));
  with tmpIconHeader do
  begin
    if wType=2 then
    begin
      FGroupVarCount:= 3 + wCount*CursorFieldCount;
      tmpStrType := '光标';
    end
    else
    begin
      FGroupVarCount:= 3 + wCount*IconFieldCount;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -