小端序标记法
<p>[TOC]</p>
<h1>🌓字节序</h1>
<p>字节序是多字节数据在计算机内存中或者网络传输中的各个字节顺序。什么是多字节数据?比如long long int类型本质上是QWORD 8字节数据,int类型本质上是DWORD 4字节数据,short类型本质上是WORD 2字节数据,char类型本质上是BYTE 1字节数据。字节顺序主要分为两大类:</p>
<ul>
<li>大端序 高字节存储在低位,低字节存储在高位</li>
<li>小端序 高字节存储在高位,低字节存储在低位</li>
</ul>
<p>举个例子</p>
<table>
<thead>
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>type</td>
<td>size</td>
<td>大端序</td>
<td>小端序</td>
</tr>
<tr>
<td>BYTE</td>
<td>1</td>
<td>\x12</td>
<td>\x12</td>
</tr>
<tr>
<td>WORD</td>
<td>2</td>
<td>\x12\x34</td>
<td>\x34\x12</td>
</tr>
<tr>
<td>DWORD</td>
<td>4</td>
<td>\x12\x34\x56\x78</td>
<td>\x78\x56\x34\x12</td>
</tr>
<tr>
<td>QWORD</td>
<td>8</td>
<td>\x12\x34\x56\x78\x90\xab\xcd\xef</td>
<td>\xef\xcd\xab\x90\x78\x56\x34\x12</td>
</tr>
</tbody>
</table>
<p>数据类型为BYTE的时候,大端序和小端序是没有区别的,只要超过1个字节,数据存储就有了区别,大端序是看起来最直观的,我们一般认为左低右高,例如坐标轴,而数字来说排在右边的是低,左边的是高,比如0x1234,4是最低位,而1是最高位,按照大端序的排法,和平时读法一样;而小端序最符合逻辑思维的存储方式,看起来就像逆向排列 </p>
<h1>🌓逆向分析字节序</h1>
<p>我们在编程的时候会经常强制类型转换,比如DWORD转4个BYTE,或者4个BYTE转DWORD,写一个demo</p>
<pre><code class="language-cpp">#include<stdio.h>
#include<string.h>
char p[] = "hello world\x00";
int main() {
for(int i = 0; i < strlen(p); i += 4) {
printf("%x\n", *(int *)(p + i));
}
}
</code></pre>
<p>正常的char也就是BYTE看起来完全没有问题,就是正常字符串顺序</p>
<p><img src="https://pic1.imgdb.cn/item/636fa59516f2c2beb1494d42.png" alt="" /> </p>
<p>当转换为DWORD后变为</p>
<p><img src="https://pic1.imgdb.cn/item/636fa52016f2c2beb1483778.png" alt="" /> </p>
<p>顺序看起来变为了『lleh』、『ow o』、『dlr』,本质上就是字节序的变化,本质上没有变</p>
<p>再举个例子</p>
<pre><code class="language-cpp">#include<stdio.h>
#include<unistd.h>
int main() {
char buf[4];
read(0, buf, 4);
if(*(int *)buf == 0x12345678) {
printf("win\n");
}
return 0;
}</code></pre>
<p>我们如果要进入win的路径,需要输入的字节顺序为 『\x78\x56\x34\x12』,和0x12345678在内存中的顺序是一样的</p>