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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在C(GCC)中的宽字符串上调用goto相关的知识,希望对你有一定的参考价值。

我找到了这段代码:

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是必要的。谁能解释一下?

答案

如果我冒险猜测,编写代码的人滥用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
Hello, World!Yj1[j
Zj4Xxcdx80,fxcdx80";

Try it online!

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

以上是关于在C(GCC)中的宽字符串上调用goto的主要内容,如果未能解决你的问题,请参考以下文章

调用 mbtowc() 时 gcc 如何决定宽字符集?

C语言的傻瓜式随笔:全局变量预编译goto

C程序存储结构

C 中的宽字符输入/输出是不是总是从正确的(系统默认)编码读取/写入?

Linux 上 __FUNCTION__ 的宽版本

[linux][c/c++]代码片段02