作为我项目的一部分,我必须在一个名为校验和保护的C程序中插入小代码。这些警卫所做的是他们使用对指令操作码进行操作的函数(add,xor等)来计算代码的一部分的校验和值。因此,如果有人篡改了该代码区域中的指令(添加,修改,删除),则校验和值将发生变化,并且将检测到入侵。
以下是讨论这项技术的研究论文:
https://www.cerias.purdue.edu/assets/pdf/bibtex_archive/2001-49.pdf
这是警卫模板:
guard:
add ebp, -checksum
mov eax, client_addr
for:
cmp eax, client_end
jg end
mov ebx, dword[eax]
add ebp, ebx
add eax, 4
jmp for
end:
现在,我有两个问题。
将防护装置放入装配中会比将其放入源程序更好吗?
假设我把它们放在组件中(在适当的地方)我应该使用什么样的混淆来防止防护模板容易看到? (因为当我有超过1个守卫时,攻击者不应该轻易找到所有守卫模板并禁用所有守卫,因为这会使代码没有安全性)
提前谢谢你。
答案 0 :(得分:1)
从攻击者(无源)的角度来看,第一个问题并不重要;他篡改了最终的二进制机器代码,无论是从.c还是.s生成,都会产生零差异。所以我主要担心如何使用适当的校验和生成正确的二进制文件。我不知道如何在C源内获得正确的校验和。但是我可以想象在将.s文件编译成.o之前,有一些外部工具在一些后处理方式上运行由C编译器创建的汇编程序文件。 但是 ...请记住,有些调用和地址只是相对偏移量,加载到内存中的二进制文件由OS加载程序根据链接器表进行修补,以实现这些要点到真实的内存地址。因此数据字节将改变(操作码将保持不变)。
你的防护模板并没有考虑到这一点,并且校验和整个操作码也包含数据字节(一些高级防护装置有操作码定义,校验和/加密/解密只有操作码本身没有操作数字节)。 / p>
否则它很整洁,结果是损坏了ebp值,破坏了使用堆栈变量的任何C代码(*)。但它仍然是人工测试,你可以简单地注释掉添加ebp,-checksum和添加ebp,ebx使得守卫无害。
(*)请注意,您必须在某些经典C代码之间加入保护,以便从无效的ebp值中获得一些真正的运行时问题。如果你把它放在子程序结束时,以pop ebp结束,一切都会好起来的。
所以第二个问题:
你肯定想要更多的恶意方法来保护正确的价值,而不仅仅是ebp损害。通常最难(删除)的方法是使校验和值成为某些计算的一部分,最终稍微倾斜结果,因此不可能严重使用SW,但用户需要时间注意。
你也可以使用一些真正的代码循环来为它添加校验和,所以简单地跳过整个循环也会跳过有效代码(但是我可以想象这个只是手工添加到C生成的程序集中,所以你必须在每次新编译特定C源代码后重做它。)
然后可以通过任何可以想象的突变(使用的不同寄存器,指令的修改顺序,指令变体)对特定的保护模板进行模糊处理,尝试搜索具有突变编码的病毒以获得一些想法。
我没有看过那篇论文,但从图中可以看出,主要的一点是要让那些防护区域重叠,所以修补其中一个会影响另一个,这对我来说听起来像那样额外的糖使它有点功能(虽然这仍然看起来像8bit游戏破解者的正常挑战;),甚至没有"硬"水平)。但这也意味着您需要非常狡猾的外部工具来计算依赖关系的循环树,并以正确的顺序插入防护模板,或者完全手动完成。
当然,在进行手动操作时,您必须在每次新的C编译之后执行此操作,因此只需花费非常宝贵和昂贵的东西,或者坚固稳定,您将不会生成其他修订版本接下来的10年左右...:D