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

📄 exeimage.pas

📁 你用过ExeScope吗?它是能够将Exe文件中的资源进行查看并修改的工具
💻 PAS
📖 第 1 页 / 共 5 页
字号:
  wValue,wCharLen: WORD;

begin
  tmpStrList := TStringList.Create;
  tmpFixedFileInfoList := TStringList.Create;
  try
    //
    with tmpFixedFileInfoList do
    begin
      Add('CompanyName');
      Add('FileDescription');
      Add('FileVersion');
      Add('InternalName');
      Add('LegalCopyright');
      Add('LegalTrademarks');
      Add('OriginalFilename');
      Add('ProductName');
      Add('ProductVersion');
      Add('Comments');
      Add('PrivateBuild');
      Add('SpecialBuild');
    end;
    //
    AOffset := AOffset + SizeOf(TVSVersionInfoHeader);
    FExeStream.Seek(AOffset,0);
    FExeStream.Read(tmpStringFileInfoHeader,SizeOf(tmpStringFileInfoHeader));
    if tmpStringFileInfoHeader.szKey='StringFileInfo' then
    begin
      FExeStream.Read(tmpStringTableHeader,SizeOf(tmpStringTableHeader));
      tmpStringInfoLen := SizeOf(tmpStringTableHeader);
      //本部分更改了,因为发现tmpStringValueHeader.wLength保存的长度不一定正确
      //所以改用其wType=01来判断,原来的代码片段查看2003-1-28日的.
      while tmpStringInfoLen < tmpStringTableHeader.wLength do
      begin
        //主要去掉'\0',其实可能超过了tmpStringVAlueHeader.wLength,所以放弃用tmpStringVAlueHeader.
        repeat
          FExeStream.Read(wValue,SizeOf(wValue));
          tmpStringInfoLen := tmpStringInfoLen + SizeOf(wValue);
        until wValue<>0;
        //刚才那个是长度,需要再跳两个
        wCharLen := wValue div SizeOf(wValue) - 3;
        FExeStream.Read(wValue,SizeOf(wValue)); //相当于wValueLength
        FExeStream.Read(wValue,SizeOf(wValue)); //相当于wType
        tmpStringInfoLen := tmpStringInfoLen + 2* SizeOf(wValue);
        tmpStr := '';
        for wValue:=0 to wCharLen-1 do
        begin
          FExeStream.Read(tmpWChar,SizeOf(tmpWChar));
          tmpStringInfoLen := tmpStringInfoLen + SizeOf(tmpWChar);
          tmpStr := tmpStr + tmpWChar;
        end;
        tmpStr := trim(tmpStr);
        if tmpStr <>'' then
        begin
          if Pos(#0,tmpStr)=0 then
          begin
            tmpComp := tmpStr;
            tmpStr := '';
          end
          else begin
            tmpComp := Copy(tmpStr,0,Pos(#0,tmpStr)-1);
            tmpStr :=  Copy(tmpStr,Length(tmpComp)+1,Length(tmpStr));
            tmpStr := trim(tmpStr);
          end;
          if tmpFixedFileInfoList.IndexOf(tmpComp)<>-1 then
          begin
            tmpStrList.Add(tmpComp);
            tmpStrList.Add(tmpStr);
          end;
        end;
      end;
    end;
  finally
    tmpFixedFileInfoList.Free;
  end;
  result := tmpStrList;
end;

 { 取得版本信息 -  文件其它信息 }
function TExeImage.GetVSVerFileInfo(AOffset:Integer):TStringList;
var
  tmpStrList : TStringList;
  tmpStringFileInfoHeader: TStringFileInfoHeader;
  tmpVerFileInfoHeader:TVerFileInfoHeader;
  tmpVerSimpleHeader: TVerSimpleHeader;
  tmpVerFileInfoHeaderLen,tmpVerSimpleHeaderLen: Integer;
  tmpStr:String;
  tmpWChar: WChar;
  tmpWd: WORD;
begin
  tmpStrList := TStringList.Create;

  // -> TStringFileInfo
  AOffset := AOffset + SizeOf(TVSVersionInfoHeader);
  FExeStream.Seek(AOffset,0);
  FExeStream.Read(tmpStringFileInfoHeader,SizeOf(tmpStringFileInfoHeader));
  // -> TVerFileInfo
  AOffset := AOffset + tmpStringFileInfoHeader.wLength; //重新定位.
  FExeStream.Seek(AOffset,0);
  FExeStream.Read(tmpVerFileInfoHeader,SizeOf(tmpVerFileInfoHeader));
  
  tmpVerFileInfoHeaderLen := SizeOf(tmpVerFileInfoHeader);
  while tmpVerFileInfoHeaderLen < tmpVerFileInfoHeader.wLength do
  begin
    FExeStream.Read(tmpVerSimpleHeader,SizeOf(tmpVerSimpleHeader));
    tmpVerSimpleHeaderLen := SizeOf(tmpVerSimpleHeader);
    tmpVerFileInfoHeaderLen := tmpVerFileInfoHeaderLen + SizeOf(tmpVerSimpleHeader);
    //取"\0"结尾的字符串
    tmpStr:='';
    repeat
      FExeStream.Read(tmpWChar,SizeOf(tmpWChar));
      tmpVerSimpleHeaderLen := tmpVerSimpleHeaderLen+SizeOf(WChar);
      tmpVerFileInfoHeaderLen :=tmpVerFileInfoHeaderLen+SizeOf(WChar);
      tmpStr := tmpStr + tmpWChar;
    until tmpWChar=Chr(0);
    tmpStrList.Add(trim(tmpStr));
    //一个padding
    FExeStream.Read(tmpWd,SizeOf(tmpWd));
    tmpVerSimpleHeaderLen := tmpVerSimpleHeaderLen+SizeOf(tmpWd);
    tmpVerFileInfoHeaderLen :=tmpVerFileInfoHeaderLen+SizeOf(tmpWd);
    tmpStr:='';
    //之后的
    while tmpVerSimpleHeaderLen < tmpVerSimpleHeader.wLength do
    begin
      FExeStream.Read(tmpWd,SizeOf(tmpWd));
      tmpVerSimpleHeaderLen := tmpVerSimpleHeaderLen+SizeOf(tmpWd);
      tmpVerFileInfoHeaderLen :=tmpVerFileInfoHeaderLen+SizeOf(tmpWd);
      tmpStr:=tmpStr+Format('%.4x',[tmpWd]);
    end;
    tmpStrList.Add(tmpStr);
  end;
  result:=tmpStrList;
end;

 { 取得版本信息中的软件语言特性 }
function TExeImage.GetVSLanguageID(AOffset,ASize:Integer):DWORD;
var
  tmpWd1,tmpWd2: WORD;
begin
  //直接取最后两个Word; 这个办法不太行.
  FExeStream.Seek(AOffset+ASize-2*SizeOf(tmpWd1),0);
  FExeStream.Read(tmpWd1,SizeOf(tmpWd1));
  FExeStream.Read(tmpWd2,SizeOf(tmpWd2));
  result := MakeLong(tmpWd2,tmpWd1);

{
  方法二
var
  tmpStringFileInfoHeader: TStringFileInfoHeader;
  tmpVerFileInfoHeader:TVerFileInfoHeader;
  tmpVerSimpleHeader: TVerSimpleHeader;
  tmpVerFileInfoHeaderLen,tmpVerSimpleHeaderLen: Integer;
  tmpStr:String;
  tmpWChar: WChar;
  tmpWd1,tmpWd2: WORD;
  tmpdWd: DWORD;
begin
  tmpdWd := $FFFFFFFF;
  // -> TStringFileInfo
  AOffset := AOffset + SizeOf(TVSVersionInfoHeader);
  FExeStream.Seek(AOffset,0);
  FExeStream.Read(tmpStringFileInfoHeader,SizeOf(tmpStringFileInfoHeader));
  // -> TVerFileInfo
  AOffset := AOffset + tmpStringFileInfoHeader.wLength; //重新定位.
  FExeStream.Seek(AOffset,0);
  FExeStream.Read(tmpVerFileInfoHeader,SizeOf(tmpVerFileInfoHeader));

  tmpVerFileInfoHeaderLen := SizeOf(tmpVerFileInfoHeader);
  while tmpVerFileInfoHeaderLen < tmpVerFileInfoHeader.wLength do
  begin
    FExeStream.Read(tmpVerSimpleHeader,SizeOf(tmpVerSimpleHeader));
    tmpVerSimpleHeaderLen := SizeOf(tmpVerSimpleHeader);
    tmpVerFileInfoHeaderLen := tmpVerFileInfoHeaderLen + SizeOf(tmpVerSimpleHeader);
    //取"\0"结尾的字符串
    tmpStr:='';
    repeat
      FExeStream.Read(tmpWChar,SizeOf(tmpWChar));
      tmpVerSimpleHeaderLen := tmpVerSimpleHeaderLen+SizeOf(WChar);
      tmpVerFileInfoHeaderLen :=tmpVerFileInfoHeaderLen+SizeOf(WChar);
      tmpStr := tmpStr + tmpWChar;
    until tmpWChar=Chr(0); //这部分会有问题
    if trim(tmpStr) = 'Translation' then
    begin
      FExeStream.Read(tmpWd1,SizeOf(tmpWd1));//为的是跳一个Word

      FExeStream.Read(tmpWd1,SizeOf(tmpWd1));
      FExeStream.Read(tmpWd2,SizeOf(tmpWd2));
      tmpdWd := MakeLong(tmpWd2,tmpWd1);
      break;
    end;
    tmpVerFileInfoHeaderLen:=tmpVerFileInfoHeaderLen+(tmpVerSimpleHeader.wLength-tmpVerSimpleHeaderLen);
  end;
  result := tmpdWd;
}
end;

function TExeImage.ExportDirAddr: Integer;
var
  i,CurIndex:integer;
  tmpCurRVA,tmpSectionRVA: DWORD;
begin
  tmpCurRVA := FPENTHead.OptionalHeader.DataDirectory[0].VirtualAddress;
  tmpSectionRVA := 0;
  CurIndex := -1;
  for i:=0 to FSectionNum-1 do
    if (FPESectionHead[i].VirtualAddress>tmpSectionRVA)and(FPESectionHead[i].VirtualAddress<=tmpCurRVA) then
    begin
      tmpSectionRVA := FPESectionHead[i].VirtualAddress;
      CurIndex := i;
    end;
  result := FPESectionHead[CurIndex].PointerToRawData + (tmpCurRVA-tmpSectionRVA);
end;

function TExeImage.ExportDirSize: Integer;
begin
  result := FPENTHead.OptionalHeader.DataDirectory[0].Size;
end;

function TExeImage.ImportDirAddr: Integer;
var
  i,CurIndex:integer;
  tmpCurRVA,tmpSectionRVA: DWORD;
begin
  //由RVA找出文件偏移位置.
  //如果导入为 $7FA0, 然而有节表为 $7000,$9000,则此导入区在节表$7000,
  //而对于$7000,实际指向的位置为$5C00,则$7FA0实际指向为 $7FA0-$7000+$5C00=$6BA0
  tmpCurRVA := FPENTHead.OptionalHeader.DataDirectory[1].VirtualAddress;
  tmpSectionRVA := 0;
  CurIndex := -1;
  //求出最接近当前tmpDirRVA的块表,(最小于等于tmpDirRVA)
  for i:=0 to FSectionNum-1 do
    if (FPESectionHead[i].VirtualAddress>tmpSectionRVA)and(FPESectionHead[i].VirtualAddress<=tmpCurRVA) then
    begin
      tmpSectionRVA := FPESectionHead[i].VirtualAddress;
      CurIndex := i;
    end;
  result := FPESectionHead[CurIndex].PointerToRawData + (tmpCurRVA-tmpSectionRVA);
end;

function TExeImage.ImportDirSize: Integer;
begin
  result := FPENTHead.OptionalHeader.DataDirectory[1].Size;
end;

{ 导出的名称 }
function TExeImage.ExportName: String;
var
  tmpExportDir:TExportDirectory;
  tmpName: Char;
  tmpStr: String;
  tmpOffset: DWORD;
begin
  with FExeStream do
  begin
    tmpOffset := FPENTHead.OptionalHeader.DataDirectory[0].VirtualAddress - ExportDirAddr;

    Seek(ExportDirAddr,0);
    Read(tmpExportDir,SizeOf(tmpExportDir));
    //将RVA转换成文件偏移值
    Seek(tmpExportDir.Name - tmpOffset,0);
    tmpStr :='';
    repeat
      Read(tmpName,SizeOf(tmpName));
      tmpStr := tmpStr + tmpName;
    until tmpName=Chr(0);
  end;
  result := trim(tmpStr);
end;

 { 导入的名称列表 }
function TExeImage.GetImportName:TStringList;
var
  tmpStrList:TStringList;
  tmpImportDesc: TIMAGE_IMPORT_DESCRIPTOR;
  tmpRealAddr,tmpOffset: Integer;
  CurPosition: DWORD;
  tmpChar:Char;
  tmpStr: String;
begin
  tmpStrList := TStringList.Create;
  CurPosition := ImportDirAddr;
  tmpOffset := FPENTHead.OptionalHeader.DataDirectory[1].VirtualAddress - CurPosition;

  FExeStream.Seek(CurPosition,0);
  FExestream.Read(tmpImportDesc,SizeOf(tmpImportDesc));
  CurPosition := CurPosition + SizeOf(tmpImportDesc);

  while tmpImportDesc.Name<>0 do
  begin
    tmpRealAddr := tmpImportDesc.Name - tmpOffset;
    tmpStr := '';
    FExeStream.Seek(tmpRealAddr,0);
    repeat
      FExeStream.Read(tmpChar,SizeOf(tmpChar));
      tmpStr := tmpStr + tmpChar;
    until tmpChar=Chr(0);
    tmpStr := trim(tmpStr);
    tmpStrList.Add(tmpStr);
    FExeStream.Seek(CurPosition,0);
    FExeStream.Read(tmpImportDesc,SizeOf(tmpImportDesc));
    CurPosition := CurPosition + SizeOf(tmpImportDesc);
  end;
  result := tmpStrList;
end;

{ 导入的函数列表 }
function TExeImage.GetImportFunction(AIndexOfName:WORD):TStringList;
var
  tmpStrList:TStringList;
  tmpImportDesc: TIMAGE_IMPORT_DESCRIPTOR;
  tmpRealAddr,tmpOffset: DWORD;
  CurPosition: DWORD;
  tmpChar:Char;
  tmpStr: String;
  FuncNameAddr:DWORD;
  FuncID: WORD;
begin
  tmpStrList := TStringList.Create;
  CurPosition := ImportDirAddr;
  tmpOffset := FPENTHead.OptionalHeader.DataDirectory[1].VirtualAddress - CurPosition;

  CurPosition := CurPosition + AIndexOfName*SizeOf(tmpImportDesc);
  FExeStream.Seek(Curposition,0);
  FExeStream.Read(tmpImportDesc,SizeOf(tmpImportDesc));

  //读取函数名称的地址.
  CurPosition := tmpImportDesc.FirstThunk-tmpOffset;
  FExeStream.Seek(CurPosition,0);
  FExeStream.Read(FuncNameAddr,SizeOf(FuncNameAddr));
  CurPosition := CurPosition + SizeOf(FuncNameAddr);
  while FuncNameAddr<>0 do
  begin
    tmpRealAddr := FuncNameAddr - tmpOffset;
    if tmpRealAddr <= FExeStream.Size then
    begin
      FExeStream.Seek(tmpRealAddr,0);
      FExeStream.Read(FuncID,SizeOf(FuncID));
      tmpStr := '';
      repeat
        FExeStream.Read(tmpChar,SizeOf(tmpChar));
        tmpStr := tmpStr + tmpChar;
      until tmpChar=Chr(0);
      tmpStr := trim(tmpStr);
      if tmpStr='' then tmpStr := '()';
     end
     else begin
       //在处理空的函数时FuncID不正确.好像没有读到.
       FuncID := tmpRealAddr and $7FFFFFFF;
       tmpStr := '()';
     end;

    tmpStrList.Add(Format('%.4x,%s',[FuncID,tmpStr]));

    FExeStream.Seek(CurPosition,0);
    FExeStream.Read(FuncNameAddr,SizeOf(FuncNameAddr));
    CurPosition := CurPosition + SizeOf(FuncNameAddr);
  end;
  result := tmpStrList;
end;

end.

⌨️ 快捷键说明

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