如何在代码中混淆测试以防止篡改响应处理?
我正在寻找一种方法来混淆(在目标代码中)一个测试 - 就像检查许可证密钥是否有效一样。我试图阻止的是有人通过图像二进制文件搜索处理响应的代码。如何在代码中混淆测试以防止篡改响应处理?
bool checkError = foo();
if (checkError) // I'd like to avoid making a simple check like this one.
{
// process response
}
这是一个简单的例子,但不是推荐的方法:
int check = 71 * 13;
check += 35 * isValid(); // will only return 0 or 1
//later (delayed execution of response)
if (check % 71)
{
//process response
}
编辑: 只是为了澄清,实际测试已经完成,我得到一个合格/不合格的回报。我的响应处理将是一个基本的jmp,并且会对如何混淆jmp位置的指针感兴趣。
一种方法是将执行许可检查的代码放入单独的DLL中。在主应用程序中,在运行时加载DLL并计算DLL自身的校验和。应用程序存储用DLL计算出的校验和。如果校验和不匹配,您有几个选项,显示错误版本的消息 - 有点显而易见;不要致电许可证检查 - 不那么明显,但当攻击者想知道为什么许可证检查没有被调用时会被注意到;调用与真实许可证检查功能类似的名称的功能。
把它想象成使用公钥加密。使用公钥作为配置的一部分,并在应用中创建私钥。如果他们混淆了公钥,应用程序的数字签名将以可检测的方式受到损害。
我同意@camccann这将有助于了解您所期望的攻击类型。作为最后的手段,将许可证检查分为尽可能多的部分,以便通过更改单个分支点来避开旁路。
[编辑]
另一个想法是使用一个状态机。请参阅this question的顶部答案中的命令结构示例。将许可证检查的评估以散列查找的形式和一组虚拟函数调用与适当的调用一起放入数组中。该评估许可证检查到表/哈希查找了相应的功能决定的代码不会像典型的
if(){ pass;} else { fail; }
结构。
两个好处,
1)没有一个布尔条件绕过并
2)它们不能在不知道该函数的地址/名称来传递控制做一个简单的JMP指令。
SO thread on a state machine turorial。
SO thread on state machine implementations
混淆不会阻止,只是不鼓励。一个足够熟练和坚定的攻击者总是能够绕过你使用的任何混淆,所以你首先需要知道的是:你想在这里挫败什么样的人?
谢谢你的区别。我应该在我的问题中说“不鼓励”。我试图阻挠的人可能是新手攻击者,因为更有经验的人很可能会找到解决某些最棘手方法的方法。 – Dubron 2009-12-11 20:23:37
您可以通过在像所有洒向检查导致崩溃:
T* data = (T*) new char[sizeof(T) * (check() ? 1 : 0)]
array[i + 1 * (check() ? 0 : 42)].doStuff();
有在Gamasutra上一个不错的一篇关于crack protection in Spyro,做类似的事情,然后通过使游戏不会崩溃更进一步,只是工作雪上加霜而且更糟。 (你永远不会撞到敌人,你走得慢一些,某些关键物体随机消失等等等等)
所有程序员都会喜欢读,也许对你有用。
好多了。 :) – GManNickG 2009-12-11 20:11:52
当然,您应该知道这不是一个小问题。像微软这样的大型软件公司花费数百万美元试图阻止人们绕过他们的保护,但人们仍然设法绕开他们的努力。 – 2009-12-11 20:21:08
@Charles Salvia:这是真的。我不是从这个问题寻找保护程度。 ;)然而,这是我第一次尝试这方面的东西,我不得不承认我不知道从哪里开始。 – Dubron 2009-12-11 20:25:17