您当前的位置:首页 > 计算机 > 精彩资源

分析字符串在内存中存储

时间:10-18来源:作者:点击数:

分析字符串在内存中存储

测试代码

#include <iostream>
#include <afx.h>
int main()
{
char szHello[] = "char2 Hello GuiShou";
wchar_t wszHello[] = L"wchar_t Hello GuiShou";
std::string strHello = "string";
std::string strHello2 = "string Hello GuiShou";
CString csString = "CString";
CString csString2 = "CString Hello GuiShou";
return 0;
}

要把运行库修改为多线程MT,否则会编译不通过。这个代码因为引用了MFC的库,而且是MT

静态编译,所以分析会比较久,需要提前分析好。

这里分析字符串必须要用到动态调试,所以用x64dbg和ida同时打开程序

char数组的存储方式

IDA中分析核心反汇编代码

字符串存储在data段,data段的数据是属于全局数据区,这个字符串的地址是固定不变的,也就是我们说的基地址,任何一个地方都能访问到

而char szHello[] 是局部变量,需要从全局变量拷贝到堆栈,每次复制4个字节

摁下A,可以把二进制数据转化为字符串

wchar数组的存储方式

IDA中分析wchar数据核心代码

.text:00414885                 mov     ecx, 0Bh        ; 用串操作指令一次性将字符串拷贝到栈区,字符串一共44字节,一个四个字节,需要复制11次
.text:0041488A                 mov     esi, offset aWcharTHelloGui ; 将会把标号 aWcharTHelloGui 所代表的地址值赋给寄存器 esi。
.text:0041488F                 lea     edi, [ebp+var_5C]
.text:00414892                 rep movsd

这里用串操作指令的方式,一次拷贝四个字节,用串操作指令一次性将字符串拷贝到栈区

C风格的数组类型的字符串都是放在rdata段中,通过字符串拷贝的方式复制到堆栈内

string在内存中的存储方式

字节数小于16

.text:00414894                 push    offset Str      ; "string"
.text:00414899                 lea     ecx, [ebp+var_80]
.text:0041489C                 call    sub_4110EB

在x64dbg中观察内存结构,因为string实际上是C++的一个类,所以在初始化的时候,会将this指针传递给ecx,然后调用构造函数。

把字符串的地址压入堆栈

把这个string类的地址交给ecx

执行构造函数后,分析这个string类,这个在堆栈中

第一个字段,保存了一个指针,跳转两次以后就回到了原来的string内存结构,说明这个位置

是一个指向自己的指针。

第二个位置保存的是字符串

字符串长度小于16个字节,就保存字符串

+14的位置是字符串长度,+18的位置缓冲区的长度

字节数大于16

00AA48A8           | 68 CCBDAA00        | push 字符串.AABDCC                  | ConsoleApplication1.cpp:8, AABDCC:"string Hello GuiShou"
00AA48AD           | 8D8D 5CFFFFFF      | lea ecx,dword ptr ss:[ebp-0xA4]  |
00AA48B3           | E8 33C8FFFF        | call 字符串.AA10EB                  |

第一个字段,保存了一个指针,跳转两次以后就回到了原来的string内存结构,说明这个位置

是一个指向自己的指针。

第二个位置保存的是一个地址

这个地址指向字符串的地址

字符串长度大于16个字节,就保存字符串的地址

+14的位置是字符串长度,+18的位置缓冲区的长度

string对象总结

struct my_string
{
    my_string* self; // 指向自己的指针
    union {
        char str[0x10]; // 当字符个数少于 16
        char* point; // 当字符个数大于 15
    };
    int length; // 当前的字符个数
    int size; // 缓冲区的大小-1(空字符)
};

CString在内存中的存储方式

CString这里会调用两个构造函数,第一个构造函数将内存初始化

第二个构造函数给字符串赋值

查看第二个字符串

在+0的位置就保存了字符串的指针,不管字符串长度多少都保存了指 针,所以 CString只有一个字段,就是字符串的指针,没有任何结构。

CString类型的字符串本质一个指针,第一个call调用函数做初始化,第二个函数把字符串的地址给传进去。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门