Unity引擎字符串内存布局
Unity引擎的字符串有三种存储方式:
- 堆 : 分配在堆上
- 内嵌 : 一个栈上的内存数据。 默认25字节,可以放长度最多24的字符串。这个长度定义为STACK_LENGTH.
- 外部
重点主要是前两种,这是一种优化方法,对于非常短的字符串,可以直接使用栈数据而不需要再次内存分配。C++伪代码看起来像这样:
union { char stack_buffer[STACK_LENGTH]; struct Data { char* data; // 8Bytes size_t capacity; // 8Bytes size_t length; // 8Bytes // align 8Bytes for Data // or size of stack string length (STACK_LENGTH - length) } // 32Bytes } // 32Bytes uint8_t dataType; // 8Bytes, 指出存储方式,其中7个Bytes用于对齐 { Id : 4Bytes Salt : 4Bytes Index : 4Bytes }MemoryTag; // 12Bytes
所以要逆向一个unity的C++字符串数据,首先定位地址。然后尝试找到dataType,其方式为:*(unit8_t*)(ptr + 0x20)。
- 如果是0,那么字符串就是*(const char**)(ptr);
- 如果是1,那么字符串就是(const char*)(ptr)。
字符串长度也有两种方式存放。
- 如果是1,那么长度以(STACK_LENGTH-length)的形式保存在stack_buffer[STACK_LENGTH]这个位置上,这个值不会超过一个字节。这种情况要获取字符串长度需要通过STACK_LENGTH减去该值得到。
- 如果不是1,那么长度就是Union当中的length。
除此之外,Unity还有一个类似于C++的string_view的东西,它将字符串以视图的形式传递,可以有效避免一些不必要的内存分配与拷贝。
{ const char* data; size_t size; }
对于这种情况,对象地址就是字符串地址,其长度位于 ptr + 0x8的位置上。