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

问题描述 投票:2回答:1

我找到了这段代码:

goto*&L"\xfeeb";

它导致程序永远挂起,显然是通过调用x64指令0xEB0xFE(按顺序,由于x64的little-endianness)。根据0xEBx86 Opcode and Instruction Reference是JMP。

我理解代码的作用,并且它等同于运行0xEB 0xFE指令的函数,所以它也可以写成int (*foo)() = L"\xfeeb"; foo();,或者如果我们想要真正混淆,((int(*)())L"\xfeeb")();。这是因为在Linux上默认情况下字符串被标记为可执行文件。

但是,goto非常严格。我不明白为什么goto*&L"\xfeeb";工作,或疯狂的指针魔术*&正在做什么,或为什么宽标记L是必要的。谁能解释一下?

c gcc binary goto opcode
1个回答
3
投票

如果我冒险猜测,编写代码的人滥用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";

Try it online!

L"\xfeeb"是一个宽字符串文字,由wchar_t类型的字符组成,而不是char。写作一个老式的字符串文字,它将是"\xeb\xfe"。我怀疑你的字符串文字中的L正在服务于MacGuffin的目的。

© www.soinside.com 2019 - 2024. All rights reserved.