随机化寄存器

时间:2015-11-26 12:16:21

标签: c gcc assembly 64-bit inline-assembly

如果某些条件不符合,我想通过跳转到随机位置来破坏我的程序。我还想通过像

这样的语句随机化寄存器
asm("rdtsc \n");
asm ("movq %rax, %r15 \n");
...
asm ("xor %rbp, %r13 \n");
...

有没有更好/更隐蔽的方法来做到这一点?我担心,因为rdtsc不是程序中的常见声明。不断调用它也会产生类似的结果。除此之外,我还能以某种方式清除/随机化堆栈内容吗?

2 个答案:

答案 0 :(得分:3)

如果你只是想要崩溃,你随机选择的目的地可能会跳到合法的地方。只需运行ud2指令(0F 0B),这将保证在每个未来的x86 CPU上导致无效指令异常(导致SIGILL)。即它是保留的,因此未来的指令集扩展将不会在指令开头使用该双字节序列。

如果您关心高质量的随机性来阻止任何潜在的回溯或核心转储,那么请调用随机数生成器来填充随机数据的缓冲区(或者只重复一个32位随机值)。用垃圾数据填充所有寄存器。在32位代码中,您可以使用popa指令用垃圾数据填充所有寄存器。在64位模式下,您必须手动加载它们。

然后使用该数据在堆栈上乱涂乱画,因此当您尝试写入未映射的地址时,您的程序最终会以段错误停止(因为您已经超出了堆栈区域)。

你可以用rep stosd或其他东西来涂鸦。

就“隐形”而言,你需要更详细地说明你的威胁模型是什么,以及你试图阻止任何人学习/做什么。即为某人修改你的二进制文件以防止这种方式崩溃?

答案 1 :(得分:1)

除了Peter Cordes的建议之外,我还要补充一点,OP希望编码负责这种混淆,以避免超出范围(隐身)。导致崩溃的指令需要在其他地方,否则混淆代码将从崩溃转储中显而易见,并且代码将很容易修补以移除炸弹。

一个相当简单的解决方案是通过推送堆栈上的地址并执行RET语句,从公共库函数(如RETread和JUMP中找到strlen操作码。此解决方案并不完美:存在高级调试器,用于存储执行跟踪,并且能够从崩溃位置回溯到混淆器。为了打败它,您可能更喜欢进入无限循环而不是崩溃,但可以轻松找到并删除该循环。

您还可以在应用中嵌入一些复杂的代码,通过随机执行许多不同的函数来计算一段时间,然后将其用作蜜罐,从混淆器中跳转。