Assembly 在x86体系结构中更改指令的操作码是否可能,或者有多困难?

Assembly 在x86体系结构中更改指令的操作码是否可能,或者有多困难?,assembly,x86,cpu-architecture,machine-language,Assembly,X86,Cpu Architecture,Machine Language,例如,PUSH imm32具有操作代码68h。是否可以使用另一个数字(例如69h)来“表示”此指令(假设此数字未被其他指令使用) 通过“表示”,我的意思是,只要程序集中有PUSH指令,69h就会出现在二进制可执行文件中。当它最终被CPU获取和执行时,它将被传输回68h 我知道每个操作码都是根据CPU电路专门设计的,但我是否可能只想使用另一个十六进制数作为替代 当然,我不会对CPU进行任何更改,我仍然希望该指令在x86体系结构上执行 更新:我为什么要问这个问题 您可能知道面向返回的攻击,它故意错误

例如,
PUSH imm32
具有操作代码68h。是否可以使用另一个数字(例如69h)来“表示”此指令(假设此数字未被其他指令使用)

通过“表示”,我的意思是,只要程序集中有PUSH指令,69h就会出现在二进制可执行文件中。当它最终被CPU获取和执行时,它将被传输回68h

我知道每个操作码都是根据CPU电路专门设计的,但我是否可能只想使用另一个十六进制数作为替代

当然,我不会对CPU进行任何更改,我仍然希望该指令在x86体系结构上执行

更新:我为什么要问这个问题

您可能知道面向返回的攻击,它故意错误解释机器语言流,并利用标准库中有许多C3(即ret)的优势。我最初的想法是,如果我们能够将return的操作码从C3更改为其他代码,最好是2字节,那么ROA将无法工作。我不是建筑领域的专家,我只是发现我的想法在现实中行不通。谢谢你的回复

理论上是的

在发现备用操作码的情况下,可以使用未定义的操作码异常(尽管空闲点不多)。异常处理程序将使用适当的操作码修改内存位置并重新执行处理

但它会在这个内存位置留下“好”的操作码。 您可以将单步中断处理程序设置为“修复”内存中存储的操作码,在执行“良好”操作码后将其设置为“伪造”,并在执行后将其禁用,以免影响性能

此外,伪操作码的大小必须与正确的操作码相同(或更长),否则您将不得不备份以下指令,以防损坏(被“良好”操作码覆盖)。 如果假指令比真指令长,则可以添加额外的spced

我不必说它很麻烦。对于现代操作系统来说,它在DOS中非常简单,几乎是不可行的解决方案。

理论上是的

在发现备用操作码的情况下,可以使用未定义的操作码异常(尽管空闲点不多)。异常处理程序将使用适当的操作码修改内存位置并重新执行处理

但它会在这个内存位置留下“好”的操作码。 您可以将单步中断处理程序设置为“修复”内存中存储的操作码,在执行“良好”操作码后将其设置为“伪造”,并在执行后将其禁用,以免影响性能

此外,伪操作码的大小必须与正确的操作码相同(或更长),否则您将不得不备份以下指令,以防损坏(被“良好”操作码覆盖)。 如果假指令比真指令长,则可以添加额外的spced

我不必提及它是一个麻烦的AF。对于现代操作系统来说,它在DOS中非常简单,几乎是不可行的解决方案

我最初的想法是,如果我们能够将return的操作码从C3更改为其他代码,最好是2字节,那么ROA将无法工作

不,x86指令编码是固定的,并且大部分是硬连接在CPU内解码器的硅中。(重定向到微码ROM以获取指令定义,但被识别为指令的操作码仍然是硬连线的。)

我认为,即使是英特尔或AMD的微码更新也无法将其现有的CPU更改为不将
C3
解码为
ret
。(虽然他们可能会使其他一些多字节序列也解码为非常慢的微编码
ret
,但可能只能通过接管现有微编码指令的编码。)


不将
C3
解码为
ret
的CPU将不再是x86 CPU。或者我想你可以把它变成一种新的模式,指令编码不同。不过,它将不再与x86兼容

不过,这是一个有趣的想法。x86上的单字节RET使将小工具链接在一起变得非常容易()。(或者意味着有更多的小工具可以链接,给你一个更大的工具箱。)

我不会屏住呼吸等待CPU供应商提供一种新模式,
ret
使用2字节操作码。不过,这是可能的(CPU供应商可以进行新的设计,而不是您对现有的CPU进行黑客攻击)。通过将其设置为单独的模式(如64位内核下的64位长模式与32位兼容模式,以及32位内核下的“遗留模式”),操作系统仍然可以在这样的CPU上工作,并且您可以在同一内核下混合/匹配用户空间进程,有些是为x86编译的,有些是为new86编译的

如果供应商打算引入一种新的不兼容模式,无法运行现有的二进制文件,希望他们能对指令集进行其他清理。e、 g.通过让变量计数移位始终写入标志(即使计数=0),消除对标志的错误依赖。或者完全重做操作码,以避免在1字节
xchg eax、r32
上花费太多的编码空间,并缩短SIMD指令的编码。但是他们不能和普通的x86解码器共享那么多的解码器晶体管。任何像EFLAGS语义的变化都可能需要后端的变化,而不仅仅是解码器的变化

它们还可以使寻址模式缩短1字节,可能使用不同的寄存器,因为即使没有索引,也总是需要SIB字节。(
-fomit frame pointer
现在是典型的,因此相对于堆栈指针的寻址需要额外的字节。)

有关x86指令编码混乱程度的更多详细信息,请参阅Agner Fog的博客文章


CPU电路设计有多大变化