我正在寻找一种方法来混淆(在目标代码中)一个测试 - 就像检查许可证密钥是否有效一样。我试图阻止的是有人在图像二进制文件中搜索处理响应的代码。
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位置的指针感兴趣。
答案 0 :(得分:5)
混淆不会阻止,只是劝阻。一个足够熟练和坚定的攻击者总是能够规避你使用的任何混淆,所以你首先需要知道的是:你想在这里挫败什么样的人?
答案 1 :(得分:5)
一种方法是将执行许可证检查的代码放入单独的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
答案 2 :(得分:3)
Secure Programming Cookbook(O'Reilly)有一章关于反篡改(实际的书有章,不知道网站上有什么可用)。整洁的东西。
答案 3 :(得分:3)
你可以把支票全部洒在上面,如:
T* data = (T*) new char[sizeof(T) * (check() ? 1 : 0)]
array[i + 1 * (check() ? 0 : 42)].doStuff();
在Gamasutra有一篇很好的文章关于crack protection in Spyro做类似的事情,然后通过让游戏不崩溃,只是工作越来越糟,进一步。 (你从不打敌人,走得慢,某些关键物体随机消失等等。)
为所有程序员阅读有趣的内容,也许对您有用。