【问题标题】:How can I determine which libraries are used in a Delphi program I don't have the source for?如何确定在我没有源代码的 Delphi 程序中使用了哪些库?
【发布时间】:2011-02-18 14:38:49
【问题描述】:

我有一个 Windows .exe 文件,但缺少它的源代码。开发商不负责任,离开了我们公司。我认为这是一个德尔福/帕斯卡程序。开发人员使用了许多库,但我不确定哪些库。有没有工具可以告诉我使用了哪些库来制作这个 exe?

【问题讨论】:

  • @Andreas Rejbrand:他没有问使用了哪些库,而是询问是否有工具可以发现使用了哪些库。所以可以回答这个问题。不幸的是,答案是afaik no..
  • Delphi 可执行文件/库中的“packageinfo”资源包含所有链接的单元名称。这可能(或可能不会)提示可能使用的库。
  • 另外,如果它是一个 vcl 表单应用程序,使用 Spy++ 或类似工具查看可视控件的类名,可能(也可能不会)显示该控件的原始库。
  • 没错。 PACKAGEINFO 资源中有使用单位的名称。而且,Delphi 的打包系统要求什么单位名称必须是唯一的。瞧,收集了宝贵的信息。此外,检查表单资源会产生组件类名称(同样,唯一的)。所以,这个问题并不是那么无望。工具很可能是 DeDe
  • 此处的评论表明该问题并非无法回答。尽管追求可能会徒劳无功,但这仍然是一个有效的问题。投票决定重新开放。

标签: delphi libraries exe pascal


【解决方案1】:

XN Resource Editor 是一个以 delphi 二进制文件(类似于RRUZ's demonstration)列出使用单位的应用程序。最新版本是hereAFAIK。例如,下面的示例屏幕截图(幸运 :))指向特定的 3rd 方库:

正如 cmets 对问题所建议的“Worm Regards”,该应用程序还显示“dfm”内容,因此可以看到所用组件的类名。但为此,我建议DFM Editor,因为这个应用程序以树形结构显示使用的组件,很像 Delphi IDE 中的“结构窗格”:

XN 或任何其他资源编辑器可用于将 dfm 资源导出到文件中,以便使用 DFM 编辑器进行检查。

【讨论】:

    【解决方案2】:

    如何推荐一些用户,您可以使用存储在PACKAGEINFO 资源中的信息,该资源包含在delphi 生成的每个exe、dll 或bpl 中。

    您可以使用GetPackageInfo函数获取包信息表中的数据。

    查看此示例代码以了解如何使用此功能。

    program ResPACKAGEINFO;
    
    {$APPTYPE CONSOLE}
    
    uses
      Windows,
      Classes,
      SysUtils;
    
    
    function GetUnitFlagInfo(Flags: Byte):string;
    begin
    
      { PackageUnitFlags:
        bit      meaning
        -----------------------------------------------------------------------------------------
        0      | main unit
        1      | package unit (dpk source)
        2      | $WEAKPACKAGEUNIT unit
        3      | original containment of $WEAKPACKAGEUNIT (package into which it was compiled)
        4      | implicitly imported
        5..7   | reserved
      }
    
      Result:='';
      if (Flags and ufMainUnit<>0) then
      Result:='[Main Unit] ';
    
      if (Flags and ufPackageUnit<>0) then
      Result:=Result+'[Package Unit] ';
    
      if (Flags and ufWeakUnit<>0) then
      Result:=Result+'[Weak Unit] ';
    
      if (Flags and ufImplicitUnit<>0) then
      Result:=Result+'[implicitly imported] ';
    
      if (Flags and ufWeakPackageUnit<>0) then
      Result:=Result+'[$WEAKPACKAGEUNIT unit] ';
    
      if (Flags and ufOrgWeakUnit<>0) then
      Result:=Result+'[original containment of $WEAKPACKAGEUNIT]';
    end;
    
    
    procedure GetInfoPackageFlags(Flags:Cardinal);
    begin
    
            { Package flags:
              bit     meaning
              -----------------------------------------------------------------------------------------
              0     | 1: never-build                  0: always build
              1     | 1: design-time only             0: not design-time only      on => bit 2 = off
              2     | 1: run-time only                0: not run-time only         on => bit 1 = off
              3     | 1: do not check for dup units   0: perform normal dup unit check
              4..25 | reserved
              26..27| (producer) 0: pre-V4, 1: undefined, 2: c++, 3: Pascal
              28..29| reserved
              30..31| 0: EXE, 1: Package DLL, 2: Library DLL, 3: undefined
            }
    
    
            if  (Flags and pfModuleTypeMask = pfExeModule) then
             Writeln('Type Exe')
            else
            if  (Flags and pfModuleTypeMask = pfPackageModule) then
             Writeln('Type Package')
            else
            if  (Flags and pfModuleTypeMask = pfLibraryModule) then
             Writeln('Type Library');
    
            if  (Flags and pfNeverBuild = 0) then
             Writeln('Build with runtime packages')
            else
             Writeln('Build without runtime packages');
    
            if  (Flags and pfIgnoreDupUnits = 0) then
             Writeln('perform normal dup unit check')
            else
             Writeln('Ignore Dup Units');
    
            if  (Flags and pfProducerMask = pfDelphi4Produced) then
             Writeln('Producer Pascal');
    
            if  (Flags and pfProducerMask = pfV3Produced) then
             Writeln('Producer pre-V4');
    
            if  (Flags and pfProducerMask = pfProducerUndefined) then
             Writeln('Producer undefined');
    
            if  (Flags and pfProducerMask = pfBCB4Produced) then
             Writeln('Producer c++');
    
            if  (Flags and pfConsumerMask = pfConsumerCompat) then
             Writeln('Consumer Compatible')
            else
            if  (Flags and pfConsumerMask = pfConsumerDelphi) then
             Writeln('Consumer Delphi')
            else
            if  (Flags and pfConsumerMask = pfConsumerBCB) then
             Writeln('Consumer BCB');
    end;
    
    procedure PackageInfoCallback(const Name: string; NameType: TNameType; Flags: Byte; Param: Pointer);
    begin
        case NameType of
          ntContainsUnit   :  Writeln(Format('Contains %s  %s',[Name+#13#10,GetUnitFlagInfo(Flags)]));
          ntRequiresPackage:  Writeln(Format('Requires %s  %s',[Name+#13#10,GetUnitFlagInfo(Flags)]));
        end;
    end;
    
    
    procedure GetPackageResInfo(const FileName:string);
    const
     ResPACKAGEINFO='PACKAGEINFO';
    var
      FModule    : Cardinal;
      Flags      : Integer;
    begin
      FModule := LoadLibraryEx(PChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE);
      try
        SysUtils.GetPackageInfo(FModule, nil, Flags, PackageInfoCallback);
        GetInfoPackageFlags(Flags);
        Writeln(GetPackageDescription(PChar(FileName)));
      finally
        FreeLibrary(FModule);
      end;
    end;
    
    begin
      try
         GetPackageResInfo('yourApp.exe');
         Readln;
      except
        on E:Exception do
          Writeln(E.Classname, ': ', E.Message);
      end;
    end.
    

    【讨论】:

      【解决方案3】:

      您提到您“认为”它是用 Delphi 编写的。如果不确定,可以使用this small utility。它只是一个命令行工具——用法是“IsDelphi.exe”。

      如果确实是用 Delphi 编写的,那么the Interactive Delphi Reconstructor 可以做出惊人的事情。以下是使用它的分步说明:

      1. 转到该链接

      2. 下载三个文件:

        a) 可执行文件

        b) 支持 dll

        c) 你以前的同事使用的 Delphi 版本的“字典”

      3. 提取所有三个

        (如果您还没有 rar 文件提取器,请使用 7-zip

      4. 打开 IDK.exe
      5. 选择文件->加载->自动检测版本
      6. 在对话框中选择您的 EXE
      7. 开始探索代码查看器和类查看器。

      最后,您可以找到一些更通用的指南以及指向其他工具的链接at this page

      祝你好运!

      【讨论】:

        【解决方案4】:

        不,实际上不可能对 Delphi 应用程序进行逆向工程。如果你这样做,你只有一堆组装。几乎不可能重构调用了哪些 VCL 函数,更不用说使用了哪些库。

        除非这个程序包含一些非常巧妙且不可重现的逻辑,否则最好从头开始并重新编写。

        【讨论】:

        • 为什么不应该有人对此投反对票?问题询问如何使用库。你回答了一些关于逆向工程的问题,这是一项完全不同的任务。即便如此,您实际上也没有提到任何人可以用来完成任务的工具或技术;你只是说它“几乎不可能”,即使它真的不会。这不是一个有用的答案。
        • 很公平,但至少要这么说,而不是匿名投票。我谈论逆向工程,因为检查使用的库只能通过检查代码和(不太可靠)应用程序中的资源来实现。但既然你似乎比我了解更多,请告诉我们你可以使用哪些工具来检查使用了哪些库。
        • @Rob 我认为 Golez 不一定反对否决票,他只是想附上一些评论。当有人告诉我我错了,我总是很感激,可悲的是,这比它应该发生的要多!
        • 确实如此。我是对的而不是错的,但如果我错了,我想知道为什么。 :)
        • 请注意,原始问题提到了库,但有些答案似乎将其解读为设计时组件。如果你不迈出这一步,这样的答案更合乎逻辑。
        猜你喜欢
        • 1970-01-01
        • 2010-10-03
        • 1970-01-01
        • 1970-01-01
        • 2014-05-27
        • 2014-11-26
        • 2010-12-21
        • 2020-02-29
        • 1970-01-01
        相关资源
        最近更新 更多