简体   繁体   English

为什么初始化 C 本地字符 arrays 在内部将字符串存储在不同的堆栈/数据段中?

[英]Why does initializing C local character arrays internally store the strings in different stack/data segments?

While working on some position-independent C injected shellcode, the strings were initially coded using this array initialization在处理一些与位置无关的C 注入 shellcode 时,字符串最初是使用此数组初始化编码的

char winexec[] = "WinExec";

However, this caused the shellcode to fail because the string WinExec was stored in the data segment of the injector but the injectee did not have access to that data.然而,这导致 shellcode 失败,因为字符串WinExec存储在注入器的数据段中,但被注入者无权访问该数据。

To fix, the array initialization was changed to要修复,数组初始化更改为

char winexec[] = { 'W','i','n','E','x','e','c','\0' };

which worked perfectly because the string was stored in the injectee local stack segment.这非常有效,因为该字符串存储在注入者本地堆栈段中。

For example https://godbolt.org/z/v8cqn5E56例如https://godbolt.org/z/v8cqn5E56

#include <stdio.h>

int main()
{
    /* String stored in the stack segment */
    char winexecStack[] = { 'W','i','n','E','x','e','c','\0' };

    /* String stored in the data segment */
    char winexecData[] = "WinExec";
    
    printf("Stack Segment: %s\n", winexecStack);
    printf("Data Segment:  %s\n", winexecData);     
    
    return 0;
}

Question问题

Why does C have multiple ways to initialize local arrays which externally appear the same, but internally the strings are stored very differently?为什么 C 有多种方式初始化本地 arrays 外部看起来一样,但内部字符串存储却大不相同?

Do tidier methods exist to initialize a C character array on the stack?是否存在更整洁的方法来初始化堆栈上的 C 字符数组? Maybe something like也许像

char winexecStack[8];
winexecStack[0] = 'W';
winexecStack[1] = 'i';
winexecStack[2] = 'n';
winexecStack[3] = 'E';
winexecStack[4] = 'x';
winexecStack[5] = 'e';
winexecStack[6] = 'c';
winexecStack[7] = '\0';

or convert strings such as Hello, World!或转换字符串,例如Hello, World! to little endian values in an array数组中的小端值

unsigned long long hello[] = { 0x57202C6F6C6C6548,0x00000021646C726F };
printf("Stack Segment: %s\n", (char*)&hello);

Perhaps for strings <= 8 bytes, they could be represented as a numerical value, stored on the stack but treated as a char* for example "WinExec"也许对于 <= 8 字节的字符串,它们可以表示为数值,存储在堆栈中但被视为 char* 例如“WinExec”

unsigned long long winexec = 0x00636578456e6957;
printf("Stack Segment: %s\n", (char*)&winexec);

Why does C have multiple ways to initialize local arrays which externally appear the same, but internally the strings are stored very differently?为什么 C 有多种方式初始化本地 arrays 外部看起来一样,但内部字符串存储却大不相同?

It doesn't.它没有。 That you observe the source data for the initializers to be stored differently in the two cases is a function of your C implementation.您观察到初始化程序的源数据在这两种情况下以不同方式存储是您的 C 实现的 function。 It is not required by the C language itself. C 语言本身不需要它。 More generally, C has a lot to say about what is stored, but less to say about how it is stored, and almost nothing to say about where it is stored.更一般地说,C 关于存储的内容有很多说法,但关于如何存储的说法较少,而关于存储位置的说法几乎没有。

Do tidier methods exist to initialize a C character array on the stack?是否存在更整洁的方法来初始化堆栈上的 C 字符数组?

A valid character array initializer takes one of the two forms you show.有效的字符数组初始值设定项采用您显示的两个 forms 之一。

Note also that "on the stack" is not a C concept (refer to "almost nothing to say about where ").另请注意,“在堆栈上”不是 C概念(请参阅“几乎无话可说”)。

Turning on optimization with /O2 makes the difference vanish.使用/O2打开优化会使差异消失。 This suggests that, without optimization, the compiler implements C somewhat literally, putting the array induced by a string literal in a data segment (for static storage) while individual character initializers are treated as small constants.这表明,在没有优化的情况下,编译器会按字面意义实现 C,将由字符串文字引起的数组放入数据段(用于 static 存储),同时将单个字符初始值设定项视为小常量。 With optimization turned on, the compiler performs deeper semantic analysis and optimizes the generated code, and in fact the constant proposed in the question, 0x00636578456e6957, is seen in the generated assembly.启用优化后,编译器会执行更深入的语义分析并优化生成的代码,实际上问题中提出的常量 0x00636578456e6957 会出现在生成的程序集中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM