理解小端字节序

0x00 前言

本来这篇文章是没有前言的,只不过是文章已经快结尾了,突然断电,发现CSDN上没有自动保存的功能,一大篇字都白码了,所以在第二次起笔的时候吐槽下。之前明明是自动保存,FCK

0x01 问题

  1. 在windbg上dd打印数据的时候跟db的不一样,dd是按照4字节格式输出,在看寄存器的时候,那个值是对的还是错的,或者说用哪种顺序表达才是适合解题的方式?

其实,让人犯晕的主要是
dd出来的数据地址标识的是这一行数据的最小地址,而不是数据第一个字节的地址。

基于对小端字节序的真实使用情况的疑问,LZ写了程序定义了一个4字节整数变量a=0x12345678,
想看下每个字节的保存地址。

0x02 源码

#include 
#include "stdafx.h"

int main()
{
	unsigned int a = 0x12345678;
	unsigned int addr = (unsigned int)&a;
	printf("hex: 0x%x in addr: 0x%x\r\n", a, &a);
	for (int i = 0; i < 4; ++i)
	{
		printf("hex: 0x%x in addr: 0x%x\r\n", *(char *)(addr +i), (addr+i));
	}
		return 0;
}

0x03 执行结果

64bit windows 7 - visual studio x86编译器

理解小端字节序_第1张图片

主机序使用小端字节序,所以内存中的数据都是低地址存低位,在低地址看到0x78是符合预期的。

0x04 分析

查看汇编执行过程
理解小端字节序_第2张图片

还原windbg调试的真实场景,因为我们会随意观察地址数据,寻找有意义的key。但是在这之前具体哪个地址才是数据正确的起始地址,数据结构,数据类型是怎样的完全不知道。当然,在运行时,寄存器会告诉你。

这里,我们用地址偏移一个字节的前后状态作为对比来观察内存。

用dd查看二进制数据

>dd &a
0x0048FE40  12345678 cccccccc c2c474a4 0048fe60  
0x0048FE50  00171fae 00000001 002868f8 00286ec8  
0x0048FE60  0048feb8 00171e10 c2c47450 00000000  
0x0048FE70  00000000 7efde000 00000000 ffffffff 

地址后移1个字节,用dd查看二进制数据

>dd 0x0048FE41
0x0048FE41  cc123456 a4cccccc 60c2c474 ae0048fe  
0x0048FE51  0100171f f8000000 c8002868 b800286e  
0x0048FE61  100048fe 5000171e 00c2c474 00000000  
0x0048FE71  00000000 007efde0 ff000000 ffffffff  

神奇的事情出现了,地址只是偏移了一个字节,显示的数据就变成了cc[123456 a4]cc,鲁莽的LZ有时就会认为这个数据是0x123456a4。


用db查看二进制数据

>db &a
0x0048FE40  78 56 34 12 cc cc cc cc a4 74 c4 c2 60 fe 48 00

地址后移1个字节,用db查看二进制数据

>db 0x0048FE41
0x0048FE41  56 34 12 cc cc cc cc a4 74 c4 c2 60 fe 48 00 ae

可以看到用db观察数据,地址偏移不会影响显示的序列,0x12后面还是0xcc, 不像dd,改变编译后,56后面不再是0x78,也不是0xcc(0x78后面的字节,以为少了0x78就会轮到0xcc)。

重新梳理

地址变化: 0x0048FE40-> 0x0048FE41

数据变化:低地址少了一个字节

dd变化:低地址变为0x0048FE41,保存的是0x56, 高地址变为0x0048FE44,保存的是0xcc, 下一个4字节同理,高地址保存的0x4a拿到高位

因为dd是按4字节分割的,所以地址右移一个字节,对导致很大的变化。当时这种移位是无意义的,因为变量a保存的是0x12345678,不是0xcc123456,在观察时需要找到正确的数据起始位置,数据类型,数据大小去提取正确的数据,才能不会被地址移位导致的数据显示出现大幅度波动的问题而烦心。这才是正确的使用dd的姿势。

0x05 总结

  1. 在用windbg观察内存时需要找到正确的数据起始位置数据类型数据大小去提取正确的数据,才能不会被地址移位导致的数据显示出现大幅度波动的问题而烦心。这才是正确的使用dd的姿势。
  2. &a+1居然不是地址右移一个字节。。。也就是说&a是指针类型,颠覆了我的三观。。。

0x06 题外话

上面代码的可执行文件中0x12345678的保存顺序是大端还是小端?

定位汇编代码
理解小端字节序_第3张图片

查看二进制文件数据
理解小端字节序_第4张图片

二进制文件的存储由编译器决定,编译器与执行器统一按照主机序保存并读取执行。

你可能感兴趣的:(日常小问题)