15

回答了另一个关于用非 Objective-C 语言为 iPhone 开发的问题,并且我断言使用 C# 为 iPhone 编写代码会让 Apple 审稿人犯错。我主要是在谈论所讨论的 ObjC 和 C# 库之间的 UI 元素不同,但评论者提出了一个有趣的观点,让我想到了这个问题:

是否可以仅从其二进制文件中确定程序的编写语言?如果有这样的方法,它们是什么?

让我们出于问题的目的假设:

  • 从交互的角度来看(控制台行为、任何 GUI 外观等),两者是相同的。
  • 这种性能并不是语言的可靠指标(没有比较,比如 Java 和 C)。
  • 您和语言之间没有解释器或其他东西 - 只是原始的可执行二进制文件。

如果您尽可能与语言无关,则可以加分。

4

8 回答 8

16

简短的回答:是的

长答案:

如果您查看二进制文件,您可以找到已链接的库的名称。在 TextPad 中打开 cmd.exe 很容易在十六进制偏移量 0x270 处找到以下内容:msvcrt.dll、KERNEL32.dll、NTDLL.DLL、USER32。 dll 等 msvcrt 是 Microsoft 'C' 运行时支持函数。KERNEL32、NTDLL 和 USER32.dll 是特定于操作系统的库,它们可以告诉您目标平台或构建它的平台,具体取决于跨平台开发环境将两者隔离的程度。

撇开这些线索不谈,大多数 c/c++ 编译器都必须将函数的名称插入到二进制文件中,所有函数(或入口点)的列表都存储在表中。C++ 'mangles' 函数名称以对参数及其类型进行编码以支持重载方法。可以混淆函数名称,但它们仍然存在。函数签名将包括可用于跟踪系统或程序中使用的内部调用的参数的数量和类型。在偏移量 0x4190 处是“SetThreadUILanguage”,可以搜索它以了解有关开发环境的很多信息。我在偏移量 0x1ED8A 处找到了入口点表。我可以很容易地看到 printf、exit 和 scanf 等名称;连同 __p__fmode、__p__commode 和 __initenv

x86 处理器的任何可执行文件都会有一个数据段,其中包含程序中包含的任何静态文本。回到 cmd.exe(偏移量 0x42C8)是文本“Software.Policies.Microsoft.Windows.System”。该字符串占用的字符数是通常所需的两倍,因为它是使用双宽字符存储的,可能是为了国际化。错误代码或消息是这里的主要来源。

在偏移量 B1B0 处是“pushd”,后跟 mkdir、rmdir、chdir、md、rd 和 cd;为了便于阅读,我省略了不可打印的字符。这些都是 cmd.exe 的命令参数。

对于其他程序,我有时能够找到编译程序的路径。

所以,的,可以从二进制文件中确定源语言。

于 2009-11-09T22:41:42.197 回答
10

我不是编译器黑客(我希望有朝一日),但我认为您可能能够在二进制文件中找到明显的迹象,这些迹象表明编译器生成它以及使用的一些编译器选项,例如级别指定的优化。

但是,严格来说,您要问的是不可能的。可能有人拿着笔和纸坐下来,计算出与他们想要编写的程序相对应的二进制代码,然后在十六进制编辑器中输入这些内容。基本上,他们会在没有汇编工具的情况下进行汇编编程。同样,您可能永远无法确定本机二进制文件是用直接汇编程序编写的,还是用 C 语言和内联汇编编写的。

至于 JVM 和 .NET 等虚拟机环境,我希望您应该能够通过二进制可执行文件中的字节码来识别 VM。但是,您可能无法分辨源语言是什么,例如 C# 与 Visual Basic,除非有特定的编译器怪癖提示您。

于 2009-11-09T22:10:07.517 回答
2

这些工具呢:

体育侦探

PEID

两者都是 PE 标识符。好的,它们都是用于窗户的,但这就是我降落在这里时的样子

于 2013-03-15T05:43:13.713 回答
1

我希望你可以,如果你反汇编源代码,或者至少你可能知道编译器,因为并非所有编译器都会使用相同的代码printf,所以 Objective-C 和 gnu C 在这里应该不同。

您已经排除了所有字节码语言,所以这个问题比预期的要少。

于 2009-11-09T22:09:56.910 回答
1

首先,what在一些二进制文件上运行并查看输出。CVS(和 SVN)标识符分散在整个二进制映像中。其中大部分来自图书馆。

此外,各种库函数通常都有一个“映射”。这也是一个很大的暗示。

当库链接到可执行文件时,通常会在二进制文件中包含一个映射,其中包含名称和偏移量。这是创建“位置无关代码”的一部分。您不能简单地将各种目标文件“硬链接”在一起。您需要一个地图,并且在将二进制文件加载到内存时必须进行一些查找。

最后,C、C++(我想是 C#)的启动模块是该编译器的默认库集所独有的。

于 2009-11-09T22:10:33.000 回答
0

好吧,C 最初是转换为 ASM,因此您可以在 ASM 中编写所有 C 代码。

于 2009-11-09T22:09:54.477 回答
0

不,字节码与语言无关。不同的编译器甚至可以采用相同的代码源并生成不同的二进制文件。这就是为什么您看不到适用于二进制文件的通用反编译器的原因。

于 2009-11-09T22:11:07.633 回答
0

命令“字符串”可用于获取有关使用哪种语言的提示(例如,我只是在我编写的 C 应用程序的剥离二进制文件上运行它,它找到的第一个条目是可执行文件链接的库) .

于 2009-11-09T22:29:04.623 回答