在 C (GCC) 中的宽字符字符串上调用 goto



我找到了这段代码:

goto*&L"xfeeb";

它导致程序永远挂起,显然是通过调用 x64 指令0xEB0xFE(按该顺序,由于 x64 的小端序)。0xEB是根据 x86 操作码和指令参考的 JMP。

我了解代码的作用,并且它相当于运行指令0xEB 0xFE的函数,因此也可以将其编写为int (*foo)() = L"xfeeb"; foo();,或者如果我们想真正混淆,((int(*)())L"xfeeb")();。这是因为字符串在 Linux 上默认标记为可执行文件。

但是,goto真的很严格。我不明白为什么goto*&L"xfeeb";起作用,或者疯狂的指针魔法*&在做什么,或者为什么需要宽标记L。有人可以解释一下吗?

如果我冒昧地猜测,编写代码的人正在滥用GCC的标签作为值扩展。此功能旨在制作跳转表或可移植 JIT 编译器或其他switch...case太慢的东西。

C 允许您goto标签。

label1:
...
goto label1;

GCC 允许您使用&&运算符获取标签的地址。要跳转到地址foo您只需goto *foo;

label1:
void *ptr = &&label1;
...
goto *ptr;

回顾一下,C 标准指定goto语句后面的参数是label类型的标记。GCC 添加一个扩展,其中goto语句后面的参数也可能是指向可执行代码的指针

因此,您可以goto任何具有指针的内存。在 Linux 上,这包括字符串文字。

goto *&"xe8rHello, World!Yj1[jrZj4Xxcdx80,fxcdx80";

在线试用!

L"xfeeb"是由类型wchar_t而不是char的字符组成的宽字符串文本。写成老式的字符串文字,它会"xebxfe".我怀疑您的字符串文字中的L服务于麦格芬的目的。

最新更新