与芯片无关,但希望我能从这里得到一些指导。
我有一大段代码,但我不知道它打算用于什么处理器。是否有可用的工具可以帮助我识别代码类型?哪些统计方法可以提供帮助?字节分布?对分布等?马尔可夫链可能吗?
与芯片无关,但希望我能从这里得到一些指导。
我有一大段代码,但我不知道它打算用于什么处理器。是否有可用的工具可以帮助我识别代码类型?哪些统计方法可以提供帮助?字节分布?对分布等?马尔可夫链可能吗?
尝试通过 GNU 文件运行它。如果它有任何标准标题,它会选择它。
例如。
jrt@lin:~/src$ file foo
foo: ELF 32-bit LSB executable, Atmel AVR 8-bit, version 1 (SYSV), statically linked, not stripped
这是一个非常有趣的问题。那里有数以百万计的指令集,但只有少数非常常用的指令集。
我首先要看的是起源和预期用途。例如,如果您怀疑它是在美国设计的,那么您将主要针对具有英文数据表的处理器。如果它是在亚洲设计的,那么他们使用的大量处理器用于美国工程师很少见到的大规模制造设备。甚至欧洲也有一些比其他处理器更常见的处理器。
然后我会看一下代码大小和功能(假设您在某种程度上知道代码的作用)。如果是几兆字节的代码,您几乎可以忽略大多数嵌入式 8 位处理器,并开始寻找具有外部存储器的更大设备。如果它是几千字节或更少,那么您可能希望专注于更小、更便宜的设备。如果功能很简单,它甚至可能是四位处理器的代码。
在这一点上,看看内存结构是值得的。至少可能有一个程序部分和一个数据部分。如果它是二进制文件(相对于英特尔十六进制或摩托罗拉的记录),那么您几乎无法了解某些数据块在内存中的放置位置。十六进制编辑器可能会显示一些模式。如果它确实以十六进制或 s 记录格式出现,您可能会获得有关它所针对的处理器的内存结构的更多信息。一些处理器在程序存储器位置 0 处复位,一些处理器在最高存储器位置处复位。该程序可能在单独的存储位置中包含 EEPROM 初始值。如果它是用于安全处理器(如在银行业中使用的),它甚至可能具有用于奇数内存位置的安全密钥。
根据编程的语言,您可能会有一些额外的线索。如果它是用 C 或类似的过程语言编程的,那么函数几乎总是以一系列指令开始,以将某些寄存器保存到堆栈(大量推送),然后在返回大量弹出窗口以从堆栈中返回原始值之前. 如果您可以进行一些模式识别,您将在整个过程中找到许多这些序列,并且可能能够确定哪些指令最有可能是推送/弹出指令、返回等,这可能会缩小您的选择范围。
如果它是一个带有中断的嵌入式设备,它可能有一个中断向量表,它看起来像一堆跳转到一个大块中的不同内存位置,可能在一个方便的位置(例如地址 0x???0) . 跳转表在其他地方也用于其他用途,但是如果您可以找到看起来相同的指令序列,除了要跳转到的地址之外,您可能能够推断出跳转指令的样子,并再次缩小你的选择下来。
那时,我将从最常见的处理器架构开始,看看是否有任何关联。x86, arm, mips, 8051, avr, pic, powerpc, Z80, 68k, 6502 等等等等。有一些常见的处理器和指令集列表——至少在英语世界中——可能会有所帮助。
我不知道有任何自动化工具可以帮助解决这个问题,但是 MAME 模拟了很多处理器架构,一种可能的方法是通过多个处理器运行代码并观察寄存器以查看是否有任何点击根据什么你知道设计。
想法:你知道源代码的年龄吗,即它是在什么时间/年份创建的?
如果它足够老,它可能会为您提供有关它是为哪个处理器编写的线索。您可以获取它的编写年龄/年份,并确定在该时间段内流行的处理器,并尝试在这些处理器上加载/执行 hex 文件。
再想一想,鉴于处理器在过去 20 年中的大规模扩散,这可能是一种大海捞针的技术,而且不会很有成效。
很多个月前,当周围没有那么多不同的处理器内核时,我通过频率分析多次识别出 Z80 代码。因为 Z80是和是CD
的机器代码(我永远不会忘记),而这些代码通常是出现次数最多的代码。但是,这要求您熟悉机器代码级别的指令集。有手工组装的经验会有所帮助(做了很多,我仍然可以用十六进制倒数来计算偏移量)。call subroutine
C9
return from subroutine