我找到了这段代码:
goto*&L"\xfeeb";
它导致程序永远挂起,显然是通过调用x64指令0xEB
和0xFE
(按顺序,由于x64的little-endianness)。根据0xEB
,x86 Opcode and Instruction Reference是JMP。
我理解代码的作用,并且它等同于运行0xEB 0xFE
指令的函数,所以它也可以写成int (*foo)() = L"\xfeeb"; foo();
,或者如果我们想要真正混淆,((int(*)())L"\xfeeb")();
。这是因为在Linux上默认情况下字符串被标记为可执行文件。
但是,goto
非常严格。我不明白为什么goto*&L"\xfeeb";
工作,或疯狂的指针魔术*&
正在做什么,或为什么宽标记L
是必要的。谁能解释一下?
如果我冒险猜测,编写代码的人滥用GCC's Labels as Values extension。此功能旨在制作跳转表或便携式JIT编译器或其他switch...case
太慢的东西。
C让你goto
一个标签。
label1:
...
goto label1;
GCC允许您使用&&
运算符获取标签的地址。要跳到地址foo
,你可以只是goto *foo;
。
label1:
void *ptr = &&label1;
...
goto *ptr;
回顾一下,C标准指定goto
语句后面的参数是类型标签的标记。 GCC添加了一个扩展,其中goto
语句后面的参数也可以是指向可执行代码的指针。
因此,你可以goto
你有一个指针的任何内存。在Linux上,这包括字符串文字。
goto *&"\xe8\r\0\0\0Hello, World!Yj\1[j\rZj\4X\xcd\x80,\f\xcd\x80";
L"\xfeeb"
是一个宽字符串文字,由wchar_t
类型的字符组成,而不是char
。写作一个老式的字符串文字,它将是"\xeb\xfe"
。我怀疑你的字符串文字中的L
正在服务于MacGuffin的目的。