【发布时间】:2016-07-10 07:02:21
【问题描述】:
我们可以比以下更短(按字符)或更优雅:
*(int*)0=0;
目标是引发访问冲突。首选独立于平台的解决方案。
【问题讨论】:
-
如果在别处隐藏单个字符 typedef(可能是模板参数),则可以省去 2 个字符。
标签: c++ obfuscation
我们可以比以下更短(按字符)或更优雅:
*(int*)0=0;
目标是引发访问冲突。首选独立于平台的解决方案。
【问题讨论】:
标签: c++ obfuscation
假设您的字符数中不包含包含
对于 Linux:
raise(11); //SIGSEGV
对于 Windows:
raise(SIGSEGV); // I don't know the SIGSEGV value for sure so more characters required
【讨论】:
这是我可以使用与 OP 和 MasterID 不同的方法得出的最接近的结果:
asm("ret");
我们的想法是尽可能笨拙地操作堆栈。我相信 gcc 会编译这个。
【讨论】:
没有可移植的方式导致分段违规或其他类似错误。
编译器可以并且确实假设未定义的行为永远不会发生。如果他们在某个代码分支中检测到 UB,他们完全有权优化整个分支以使其不存在。
if (x == 5)
{
std::cout << "Gonna crash";
*(int*)0 = 42;
}
编译器可以将此代码块转换为无操作。
raise(SIGSEGV) 可能会或可能不会导致实际违规,但它是导致程序表现得好像发生违规的唯一可移植方式。
【讨论】:
i*1000000000在i >= 3时溢出,所以编译器假定i永远不是>=3,并删除所有对应的检查和分支。
从 Unix(主要是 Linux)的角度来看:
如果我们将“访问冲突”定义为填写siginfo_t的si_addr字段的“任何信号”,那么根据sigaction(2)即为:SIGILL, SIGFPE, SIGSEGV, SIGBUS, and SIGTRAP。
SIGILL 可以通过执行任何无效指令来生成,包括永久无效指令,例如 x86 上的 ud2(编码为 0x0F 0x0B),但无论如何跳转到随机点通常都会生成这种情况。
SIGFPE可以通过任何整数除以0或最大负整数除以-1生成
SIGSEGV 可以通过读取或写入任何未映射或PROT_NONE'd 页面或写入只读页面来生成。
SIGBUS我一直不知道它是从哪里来的。
SIGTRAP可以由你的arch的断点指令生成,在x86上是int3,也就是单字节0xcc。从一个角度来看,这是最短的代码。如果您坚持使用最可能的 C 代码,则必须根据编译器的想法将其包装在 asm 块中。
还有其他涉及系统调用的示例,例如kill。
【讨论】: