分析字符串在内存中存储

本文会使用x64dbg分析4中字符串在内存中的存储

目录

分析字符串在内存中存储

char数组的存储方式

wchar数组的存储方式

string在内存中的存储方式

字节数小于16

字节数大于16

CString在内存中的存储方式


分析字符串在内存中存储

测试代码

#include 
#include 
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
静态编译,所以分析会比较久,需要提前分析好。

分析字符串在内存中存储_第1张图片

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

char数组的存储方式

IDA中分析核心反汇编代码

分析字符串在内存中存储_第2张图片

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

分析字符串在内存中存储_第3张图片

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

分析字符串在内存中存储_第4张图片

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

分析字符串在内存中存储_第5张图片

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,然后调用构造函数。

把字符串的地址压入堆栈

分析字符串在内存中存储_第6张图片

把这个string类的地址交给ecx

分析字符串在内存中存储_第7张图片

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

分析字符串在内存中存储_第8张图片

分析字符串在内存中存储_第9张图片

分析字符串在内存中存储_第10张图片

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

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

分析字符串在内存中存储_第11张图片

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

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

分析字符串在内存中存储_第12张图片

字节数大于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                  |

分析字符串在内存中存储_第13张图片

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

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

分析字符串在内存中存储_第14张图片

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

分析字符串在内存中存储_第15张图片

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

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

分析字符串在内存中存储_第16张图片

string对象总结

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

CString在内存中的存储方式

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

分析字符串在内存中存储_第17张图片

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

分析字符串在内存中存储_第18张图片

查看第二个字符串

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

分析字符串在内存中存储_第19张图片

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

你可能感兴趣的:(C与汇编,c++,汇编)