学习这套教程之前,你需要:
本教程默认你已经具备基本的C语言语法知识,具备基本的计算机理论和常识,比如进制、存储的概念等,又透过事物看本质的好奇心。
以上
这一节我们将主要学习整数在C语言中的表现形式,这将奠定大家C语言坚实的基础,并且为大家今后从事逆向分析相关的工作时提供良好的知识铺垫。
C语言中整形按大小可以细分int、short、long,又可以按符号分有符号和无符号等,又因C标准并未明确规定不同数据类型的标准大小,而交由编译器规定。故在不同系统、不同编译器下大小不同,从存储来说,最大的不同即在于有无正负号,为了描述方便,便于理解,我们统一按照最常见的四字节为例(2字节和8字节也通用),按有符号整数和无符号整数两类讲解。
无符号整数(unsigned int)
此类整数最好理解,存储时,它们(unsigned int)的全部位数(比如int四个字节,将占8*4=32个bit位)都用来表示数据,即00000000 00000000 00000000 00000000 ~ 11111111 11111111 11111111 11111111 之间,而在内存中,通常用8个十六进制数表示,即四个二进制数一组,十六进制表示为0x00000000 ~ 0xFFFFFFFF。最大表示范围十进制为0~4294967295。
下面举个例子以加强理解:
譬如十进制数字5,对应二进制数为101,那么对应二进制表示为00000000 00000000 00000000 00000101 与我们最习惯的十进制表示一样,低位再右,向左进位。左边29位全为0。
对应十六进制表示则为0x00000005。
再譬如十进制数字12,对应二进制数为1100,那么对应二进制表示为00000000 00000000 00000000 00001100 ,对应十六进制数为0x0x0000000C
有符号整数(int)
有符号数与无符号数的区别在于,最高一位也就是左边第一位是用来表示符号的,而右边31位表示数据。
左边第一位用1表示负数,用0表示正数
右边31位数据即为0000000 00000000 00000000 00000000 ~ 1111111 11111111 11111111 11111111
对应十六进制数为0x00000000 ~ 0xFFFFFFFF ,其中正数部分为:0x00000000 ~ 0x7FFFFFFF,负数部分为:0x80000000 ~0xFFFFFFFF,其中0x00000000为0,0x80000000为最小负数。
对应十进制数则为-2147483648 ~ 2147483647
(到这里,如果您对数字的二进制存储,包括原码、补码等不明白的话可以参考 int类型在内存中的存储方式。)
实际学习、逆向分析过程中,我们在发现有数据需要解释为有符号整数时,往往看十六进制的最高位,是小于8,还是8及以上,如果8以下则为正数,大于8则为负数。需要大家根据经验结合上下文分析。
另一方面,了解整数的存储结构,对于理解整数算数运算过程中发生的进位、溢出等问题也有很好的帮助。比如程序:
貌似为死循环,但实际上i由于是有符号的,所以当加到上限也就是0x7FFFFFFF时,进位就会变成0x80000000从而结束循环。
为了方便显示结果,也可以加大i的值,运行如下:
大家可以自行上机测试实验,感受整数的存储规律。
以上