大飞哥自习室 发表于 2022-3-22 12:11

1.4 编程判断主机字符序

编程判断主机字节序是更进一步掌握字节序的方式,本小节给出两种对主机的字节序进行判断的方式。
1.4.1字节序相关函数
在TCP/IP网络编程中会涉及关于字节序的函数,TCP/IP协议中传递数据是以网络字节序进行传输的,网络字节序是指网络传输相关协议所规定的字节传输的顺序,TCP/IP协议所使用的网络字节序与大尾方式相同。而主机字节序包含大尾方式与小尾方式,因此在进行网络传输时会进行相应的判断,如果主机字节序是大尾方式则无需进行转换即可传输,如果主
机字节序是小尾方式则需要转换成网络字节序(也就是转换成大尾方式)然后进行传输。常用的字节序涉及的函数有如下几个:
u_short htons(u_short hostshort);u_long htonl(u_long hostlong);u_short ntohs(u_short netshort);u_long ntohl(u_long netlong);
在这4个函数中,前两个是将主机字节序转换成网络字节序,后两个是将网络字节序转换为主机字节序。关于更多的字节序的函数可参考MSDN。
1.4.2编程判断主机字节序
“编程判断主机字节序”是很多杀毒软件公司或者安全开发职位的一道面试题,因为这个题目比较基础。通过前面的知识,相信读者能够很容易地实现该程序。这里给出笔者自己对于该题目的实现方法。笔者认为,完成该题目有两种方法,第一种方法是“取值比较法”,第二种方法是“直接转换比较法”。
1.取值比较法
所谓取值比较法,是首先定义一个4字节的十六进制数。因为使用调试器查看内存最直观的就是十六进制,所以定义十六进制数是一个操作起来比较直观的方法。而后通过指针方式取出这个十六进制数在“内存”中的某一个字节,最后与实际数值中相对应的数进行比较。由于字节序的原因,内存中的某字节与实际数值中对应的字节可能不相同,这样就可以确定字节序了。
代码如下:





以上代码中,定义了 0x01020304 这个十六进制数,其在小尾方式内存中的存储顺序为
04 03 02 01。取*(BYTE *)&dwSmallNum 内存中的低地址位的值,如果是小尾方式的话,那
么低地址存储的值为 0x04;如果是大尾方式的话,则低地址存储的值为 0x01。
注意: 这段代码的关键就是*(BYTE *)&dwSmallNum 取出来的值。
2.直接转换比较法
所谓直接转换比较法,是利用字节序转换函数将所定义的值进行转换,然后用转换后的
值与原值进行比较。如果原值与转换后的值相同,说明是大尾方式,否则为小尾方式。
代码如下:
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32")
int main(int argc, char *argv[])
{
DWORD dwSmallNum = 0x01020304;
if ( dwSmallNum == htonl(dwSmallNum) )
{
printf("Small Sequence. \r\n");
}
else
{
printf("Big Sequence. \r\n");
}
return 0;
}

这种方式比较直接,其前提是网络字节序是固定的,就是大尾方式。因为是比较,所以就要有一个参照物。如果原值转换后的结果与原值相同,就说明该主机是大尾方式存储,反之则是小尾方式。
1.5总结
本章对内存中存储基础数据的方式进行了阐述,并且在最后部分介绍了如何使用OD调试器来查看内存中的数据。在学习编程时,都会从数据类型开始介绍,不同的数据类型都是以二进制的方式存储在内存中的,只是它们存储的方式不同,或者是存储的宽度不同。在我们学习逆向时,也首先讲解了数据的基础及数据的存储方式。

DGY24736 发表于 2022-3-22 12:11

谢谢分享

vpgPGJRwInb 发表于 2022-3-22 12:12

谢谢前来学习 一下

bTckhDOlMA 发表于 2022-3-22 12:13

太好了,我看看,谢谢!

VXBlSUP138 发表于 2022-3-22 12:13

大佬无敌

KbRDG16 发表于 2022-3-22 12:13

不可多得,支持楼主

lDeJTj 发表于 2022-3-22 12:13

感谢楼主分享,我瞧瞧

NVFpaWQXA 发表于 2022-3-22 12:13

谢谢分享

gEL1730 发表于 2022-3-22 12:21

谢谢分享

hZW13 发表于 2022-3-22 12:29

学习永不停歇
页: [1] 2 3 4 5 6 7
查看完整版本: 1.4 编程判断主机字符序