我在 StackOverflow 问题“ C# Theoretical: Write a JMP to a codecave in asm ”中第一次遇到这个词。我看到根据维基词典,代码洞穴是:
一个未使用的内存块,通常是软件破解者,可以用来注入自定义编程代码来修改程序的行为。
我找到正确的定义了吗?如果是这样,代码洞穴是否有任何合法用途?
我在 StackOverflow 问题“ C# Theoretical: Write a JMP to a codecave in asm ”中第一次遇到这个词。我看到根据维基词典,代码洞穴是:
一个未使用的内存块,通常是软件破解者,可以用来注入自定义编程代码来修改程序的行为。
我找到正确的定义了吗?如果是这样,代码洞穴是否有任何合法用途?
有人可能希望有意创建一个代码洞穴作为使用自修改代码的一部分。
当然,假设那个人是疯了。
我用过它们,虽然直到今天我才听说过代码洞穴这个词。维基词典的定义表明,代码洞穴是破解者在他或她试图破解的可执行文件中发现的东西。你引用的问题并没有那样使用它。相反,它建议分配代码洞穴VirtualAllocEx
以在目标进程中创建一个全新的内存块。这消除了在目标中搜索未使用空间的需要,并保证您将有足够的空间来放置所有新代码。
Ultimately, I think a "code cave" is just a place to store run-time-generated code. There doesn't have to be any nefarious purpose to that code. And at that point, the question of what a code cave is becomes entirely uninteresting. The interesting parts are what reasons there are for generating code at run time, and what techniques there are for making sure that new code gets run when you want it.
代码洞穴通常由编译器创建用于对齐,并且通常位于大量函数之间。结构和跳转之间也应该有代码洞穴(在某些架构中),但通常不会有很多。
您也可以搜索一块归零的内存,但不能保证程序不会使用它们。
我想从理论上讲,如果您丢失了源代码,您可以通过使用它们来修补您的错误程序,并且您的程序不会增长。
编辑
对于那些建议代码洞穴仅适用于运行时生成的代码的人:这是一个不完整的定义。很多时候,我在“代码洞穴”中编写了一个数据结构并更新了指向那里的指针,我怀疑我不是唯一这样做的人。
一些合法用途:在不重新启动的情况下修补实时操作系统二进制文件(MS 这样做),为防火墙和防病毒挂钩低级操作系统功能(文件系统,网络),在没有源代码时扩展应用程序(如抓取低级操作系统调用)到 DrawText,这样你就可以为盲人大声朗读它们)
不熟悉这个术语,但热补丁机制可以使用保留空间来存储代码补丁。您挂钩有缺陷的功能并将其重定向到新改进的功能。它可以在不关闭关键设备(大型电信交换机)的情况下即时完成。
它可用于在运行时注入代码。假设操作系统允许您(NX 位未设置等),它可用于以静态语言编写自修改代码。它有很多用途,但这不是您应该在典型的商业应用程序中考虑的事情。
对我来说,这听起来像是正确的定义。
至于合法使用,我要说:除非你只是为了试验而试验,并且愿意承担后果,否则不要这样做。
这种类型的东西不可能进入生产代码:
自修改代码不应该掉以轻心,但有时可以带来很大的性能提升。如果您已经编程了很长时间,您可能已经在不知不觉中使用了它。
在广泛使用 486 及更高版本之前,许多 PC 不包括硬件浮动支持。这让人们在编写涉及浮点的程序时进退两难。如果他们编译他们的程序以使用内联浮点指令,它将在具有浮点处理器的机器上快速运行,而在没有浮点处理器的机器上则根本无法运行。如果他们用软件浮点仿真编译他们的程序,它可以在所有机器上运行,但即使在具有硬件浮点的机器上也很慢。
许多编译器库使用了一个有趣的技巧来自修改代码。默认行为是在需要浮点运算的地方放置一个陷阱指令。陷阱处理程序将在软件中模拟指令,或者如果它检测到它在具有浮点硬件的机器上运行,它将通过用适当的硬件浮点指令替换陷阱指令来修改代码并执行它。结果是软件可以在所有机器上运行,并且在具有浮点硬件的机器上运行速度几乎与代码已被编译为直接使用浮点硬件一样快(因为大多数浮点密集型操作发生在多次执行的循环中)。