zoukankan      html  css  js  c++  java
  • 20135321余佳源——信息安全系统设计基础第三周学习总结

    信息安全系统设计基础第三周学习总结

    第四周:学习任务教材第二章

     

    第四周(9.28-10.04):

    学习计时:共10小时

    读书:2

    代码:2

    作业:3

    博客:3

    学习目标

    1. 理解二进制在计算机中的重要地位

    2. 掌握布尔运算在C语言中的应用

    3. 理解有符号整数、无符号整数、浮点数的表示

    4. 理解补码的重要性

    5. 能避免C语言中溢出,数据类型转换中的陷阱和可能会导致的漏洞

     

    学习任务:

     

    公式可以不看,习题不能不做,考核题目和课后习题类似,重点题目:

     

    2.4、2.6、2.8、2.11、2.13、2.14、2.18、2.19、2.21、2.23、

     

    2.24、2.25、2.27、2.29、2.33、2.34、2.39、2.40、2.42、2.43、

     

    2.44、2.45、2.47、2.50、2.52、2.54

     

     

     

    p20: 三种数字:无符号数、有符号数(2进制补码)、浮点数,信息安全系同学从逆向角度考虑为什么会产生漏洞

     

    p22: 进制转换,注意拿二进制作中间结果就好转了

     

    p25: gcc -m32 可以在64位机上(比如实验楼的环境)生成32位的代码

     

    p26: 字节顺序是网络编程的基础,记住小端是"高对高、低对低",大端与之相反就可以了。

     

    p28: 代码执行一下

     

    p32: 能区分逻辑运算(结果是1或0)和位运算(结果是位向量),所有逻辑运算都可以用与、或、非表达(最大式、最小式),而与或非可以用"与非"或"或非"表达,所以,只要一个与非门,就可以完成所有的逻辑运算。

     

    p33: 掩码是位运算的重要应用,对特定位可以置一,可以清零

     

    p38: 要用C99中的"long long"类型,编译是要用 gcc -std=c99

     

    p39: 补码的利用寄存器的长度是固定的特性简化数学运算。想想钟表,12-1 等价于 12 + 11,利用补码可以把数学运算统一成加法,只要一个加法器就可以实现所有的数学运算。

     

    p44: 注意C语言中有符号数和无符号数的转换规则,位向量不变。想想第一章说的 信息就是"位+上下文"

     

    p48: 怎么样让负数等于正数? 信息安全的逆向思维

     

    p49: 0扩展和符号扩展

     

    p52: 深入思考一下代码和结果

     

    p54: 如何让整数运算溢出?如何避免?

     

    p62例子看看

     

    p67: 关于整数运算的最后思考

     

    p67: 浮点数有科学计数法的基础就不难理解,IEEE标准754

     

    p68: 浮点数运算的不精确性与舍入

     

    p70: IEEE浮点标准,float/double类型

     

    p74: 整数与浮点数表示同一个数字的关系

     

    p78: 整数与浮点数转换规则

     

    p80:家庭作业可以选做,协调好每题最多两人一组做,一星题目一人加一分,二星加二分,三星加三分,四星加四分

     

     

    笔记:

    1.三种数字:无符号数、有符号数(2进制补码)、浮点数,信息安全系同学从逆向角度考虑为什么会产生漏洞

    无符号数:基于传统的二进制表示法,表示大于或者等于零的数字。

    补码:表示有符号整数最常见的方法,可以为正可以为负。

    浮点数:表示实数的科学计数法。

    结果太大可能会使得某些运算溢出,大量的计算机安全漏洞是由于计算机算术运算的微妙细节引发的。

     

    2. 进制转换,注意拿二进制作中间结果就好转了

    四位二进制等于一位十六进制,2的n次幂换算十六进制,

    练习题2.4:

    0x503c+0x8=0x5044

    0x503c-0x40=0x4ffc

    0x503c+64=0x507c

    0x50ea-0x503c=0xae

     

    3. gcc -m32 可以在64位机上生成32位的代码

     

    4. 字节顺序是网络编程的基础,记住小端是"高对高、低对低",大端与之相反就可以了。

    小端法:最低有效字节在最前面的方式

    大端法:最高有效字节在最前面的方式

    也有双端法。

    已知,Linux 32、 Windows、Linux 64是小端法机器。Sun是大端法机器。

     

    5. p28的代码,使用强制类型转换来访问和打印不同程序对象的字节表示。

    代码如下:

    执行一下,达到如下结果:

    练习2.6:

    A:0000 0000 0011 0101 1001 0001 0000 0001

    0100 1010 0101 0110 0100 0101 0000 0100

    B:右移两位可最大又21位匹配

    C:除了最高有效位1,整数的所有位都嵌在浮点数中,而浮点数有一些非零的高位不与整数中的高位相匹配

     

    6. 能区分逻辑运算(结果是1或0)和位运算(结果是位向量),所有逻辑运算都可以用与、或、非表达(最大式、最小式),而与或非可以用"与非"或"或非"表达,所以,只要一个与非门,就可以完成所有的逻辑运算。使用掩码,利用位向量来对集合编码。掩码是位运算的重要应用,对特定位可以置一,可以清零。

    练习2.8:

    a 01101001

    b 01010101

    ~a 10010110

    ~b 10101010

    a&b 01000001

    a|b 01111101

    a^b 00111100

     

    7. 要用C99中的"long long"类型,编译是要用 gcc -std=c99,C语言定义了每种数据类型必须能够表示的最小的取值范围。C和C++都支持有符号和无符号数,JAVA只支持有符号数。

    练习2.11:

    1. k
    2. 此时first=last=3,所以a[3]^a[3]=0
    3. 第4行修改成first<last即自己不需要与本身交换

    练习2.13:

    bis(x,y)

    bis(bic(x,y),bic(y,x))

    bis(x,y)其实是保留x的1,加入了y的1,也就是"或"。

    练习2.14:

    x&y 0x20 x&&y 0x01

    x|y 0x7F x||y 0x01

    ~x|~y 0xDF !x||!y 0x00

    X&!y 0x00 x&&~y 0x01

     

    8. 补码的利用寄存器的长度是固定的特性简化数学运算。类似于钟表,12-1 等价于 12 + 11,利用补码可以把数学运算统一成加法,只要一个加法器就可以实现所有的数学运算。对于某些程序来说,用某个确定大小的表示来编码数据类型非常重要,比如Java标准非常明确,采用补码表示,单字节数据类型成为byte而不是char且没有long long数据类型。因此保证了Java程序在无论什么机器上都能表现得一样。

     

    9. 有符号数还有两种标准的表示方法:反码和原码。C语言允许在各种不同的数字数据类型之间做强制类型转换,且支持所有整型数据类型的有符号和无符号运算,通常大多数数字都默认为有符号的。注意C语言中有符号数和无符号数的转换规则,位向量不变。信息就是"位+上下文"。

    练习2.18:

    A:440 B:20 C:-424 D:-396 E:68 F:-312 G:16 H:12 I:-276 J:32

    练习2.19:

    x 

    hex(x) 

    T2U4(x)

    -8 

    0x8 

    8 

    -3 

    0xD 

    13 

    -2 

    0xE 

    14 

    -1 

    0xF 

    15 

    0 

    0x0 

    0 

    5 

    0x5 

    5 

     

     

    10.怎么样让负数等于正数? 信息安全的逆向思维

        利用printf首先将一个字当做一个无符号数输出,然后再把它当做一个有符号数输出。转换的原则是底层的位表示保持不变。就是应用函数U2TW,将无符号数转换为有符号数。

    练习2.21:

    类型

    求值

    无符号数

    1 

    有符号数

    1 

    无符号数

    0 

    有符号数

    1 

    无符号数

    1 

     

     

    11. 0扩展和符号扩展

    0扩展:将一个无符号数转换为一个更大的数据类型,在表示的开头添加0.

    符号扩展:将一个补码数字转换为一个更大的数据类型。

    练习2.23:

    A:fun1是无符号移位,即逻辑移位,fun2则是算数移位

    W

    fun1(w)

    fun2(w) 

    0x00000076 

    0x00000076 

    0x00000076 

    0x87654321 

    0x00000021 

    0x00000021 

    0x000000C9 

    0x000000C9 

    0xFFFFFFFC9 

    0xEDCBA987 

    0x00000087 

    0xFFFFFFF87 

    B:fun1从参数的低8位中提取得到范围0-255之间的整数,fun2也是从低8位提取,但是进行了符号扩展,所以是介于-128~127

     

    12. 深入思考一下代码和结果

        当参数length为0时,程序代码会出错,说明从有符号数到无符号数的隐式强制类型转换很容易引发错误。由于length在代码中是无符号的,0-1将会进行无符号计算,就会等价于MOD算法,相当于得到一个MAX数值,所以所有数都是小于等于MAX值的,于是总是为真。所以代码尝试访问数组a的非法元素。

    练习2.24:

    无符号截断值

    补码截断值

    0 

    0 

    2 

    2 

    1 

    1 

    3 

    3 

    7 

    -1 

    练习2.25:

    出错原因:当参数length为0时,程序代码会出错,说明从有符号数到无符号数的隐式强制类型转换很容易引发错误。由于length在代码中是无符号的,0-1将会进行无符号计算,就会等价于MOD算法,相当于得到一个MAX数值,所以所有数都是小于等于MAX值的,于是总是为真。所以代码尝试访问数组a的非法元素。

    修改办法:将length声明为int类型进行有符号运算,或者将for循环的测试条件改为i<length防止溢出

     

    13. p54: 如何让整数运算溢出?如何避免?

        首先,无符号数运算:所有无符号数运算都是以2的n次方为模,(n是结果中的位数)。所以它不存在运算时的没有那种所谓的"溢出",当它超过范围时,从零开始重新计数!当一个无符号数和有符号数相加的时候,有符号数会自动转化为无符号数参与运算!

        其次,有符号数运算: 是可能发生"溢出"的,而且溢出的结果是未定义的。当一个运算的结果发生溢出时,做出任何假设都是不安全的。

        避免方法:检查 cpu 的状态标志寄存器中的溢出标志位,验算运算是否超出了溢出标志位。

    练习2.27:

    int fun(unsigned x,unsigned y){

        unsigned sum=x+y;

        return sum>=x;

    }

    练习2.29:

    x 

    y 

    x+y 

    x+(t/5)y 

    情况

    [10100] 

    [10001] 

    100101

    00101 

    1 

    [11000] 

    [11000] 

    110000 

    10000 

    2 

    [10111] 

    [01000] 

    111111 

    11111 

    2 

    [00010] 

    [00101] 

    000111 

    00111 

    3 

    [01100] 

    [00100] 

    010000 

    10000 

    4 

    练习2.33:

    x

    -(t/4)x

    十六进制

    十进制

    十进制

    十六进制

    0

    0

    0

    0

    5

    5

    -5

    B

    8

    -8

    -8

    8

    -3 

    -1 

    练习2.34:

    x·y

    截断的x·y

    20[010100]

    12[001100] 

    4[100]

    -4[100] 

    14[001110]

    -2[111110] 

    6[110]

    -2[110] 

    36[100100]

    4[000100] 

    4[100]

    -4[100] 

     

     

    14. p62 XDR库中的安全漏洞

        参数过大,第10行上的乘法运算会溢出,从第16行开始的循环会试图复制所有字节,超出已分配的缓冲区的界限,从而破坏其他的数据结构,导致程序崩溃或者行为异常。可见malloc使用了一个32位无符号数作为参数,因此不可能分配一个大于232个字节的块,所以没必要,应该将其放弃,返回一个NULL。

    练习2.39:

    将表达式变为-(x<<m),设字长w,n=w-1。计算(x<<w)-(x<<m),而将x向左移动w位会得到0。

    练习2.40:

    表达式

    (x<<2)+(x<<1) 

    (x<<5)-x 

    (x<<1)-(x<<3) 

    (x<<6)-(x<<3)-x 

    练习2.42:

    int div16(int x){

        int bias=(x>>31)&0xF;

        return (x+bias)>>4;

    }

    练习2.43:

    M=31,利用(x<<5)-x求x*M

    N=8,y是负数时加上偏置量7,且右移3位

     

    15.关于整数运算的最后思考

        计算机执行的"整数"运算实际上是一种MOD运算形式,表示数字的有限字长限制了可能的值的取值范围,导致运算结果溢出。补码提供了一种既能表示负数又能表示整数的灵活方法。C语言中某些规定可能会产生出乎意料的结果,而且难以察觉,unsigned

    数据类型概念上简单,却可能导致很多意想不到的行为。

    练习2.44:

    A:假。令x=TMin32,x-1=TMax32

    B:真。前式为0则有位x2等于1,左移29位后,x2将会成为符号位

    C:假。令x为0xFFFF,x*x为0xFFFE0001.

    D:真。X非负数,-x是非正。

    E:假。令x=TMin32,那么x与-x都是负数

    F:真。

     

    G:真。~y=-y-1.uy*ux=x*y,所以等价。

     

    16. 浮点数有科学计数法的基础就不难理解,IEEE标准754

     

    17.浮点数运算的不精确性与舍入

        二进制表示法只能表示那些能够被写成x*2y的数,其它的值只能被近似表示。增加二进制的表示长度可以提高表示的精度。

    练习2.45:

    小数值

    二进制表示

    十进制表示

    1/8

    0.001 

    0.125 

    3/4

    0.11 

    0.75

    25/16

    1.1001 

    1.5625 

    43/16

    10.1011 

    2.6875 

    9/8

    1.001 

    1.125 

    47/8

    101.111 

    5.875 

    51/16

    11.0011 

    3.1875 

     

     

    18. IEEE浮点标准,float/double类型

        IEEE浮点标准用V=(-1)S*M*2E的形式来表示一个数:符号s决定正负,对于数值0的符号位解释作为特殊情况处理。尾数M是一个二进制小数。阶码E作用是对浮点数加权,权重是2的E次幂。

        浮点数的位划分三个字段,分别对这些值进行编码:

    一个单独的符号位s直接编码符号s

    K位的阶码字段编码阶段E

    N位小数字段编码尾数M

        两种最常见的格式就是float 和double,区分一下单精度和双精度的具体情况。

    练习2.47:

    见书本。

     

    19.整数与浮点数表示同一个数字的关系:相关的区域对应整数的低位,刚好在等于1的最高有效位之前停止,也就是隐含的开头的位1,与浮点数表示的小数部分的高位时相匹配的。

    练习2.50:

    原始值

    舍入后的值

    10.0102 2+(1/4)

    10.0 2

    10.0112 2+(3/8)

    10.1 2+(1/2)

    10.1102 2+(3/4)

    11.0 3

    11.0012 3+(1/8)

    11.0 3

    练习2.52:

    1011110

    15/2

    1001111

    15/2

    0101001

    25/32

    0110100

    3/4

    1101111

    31/2

    1011000

    16

    0000001

    1/64

    0001000

    1/64

     

     

    20.整数与浮点数转换规则

    • 从int转换成float,数字不会溢出但是可能被舍入。
    • 从int或者float转换成double,能保留足够精确的数值
    • 从double转换成float,可能溢出成正无穷或负无穷,由于精确度较小,还可能被舍入
    • 从float或者double转化成int,值会向零舍入,也就是可能溢出。一个浮点数向整数转换,如果不能为该浮点数找到一个合理的整数近似值,就会产生整数不确定值。

    练习2.54:

    A:真,double比int具有更大的精度和范围

    B:假,令x=TMax即为假

    C:假,令d=le40,右边可得到正无穷

    D:真,double比float具有更大的精度和范围

    E:真,浮点数取非就是对他的符号位取反

    F:真,这是浮点数的除法

    G:真

    H:假,令f为1.0e20而d为1.0,f+d会舍入到1.0e20,左式因此求得0.0而右式为1.0。

     

     

     

    家庭作业:

    2.65 写出代码实现如下函数:

    /*Return 1 when x contains an even number of 1s; 0 otherwise. Assume w=32*/

    int even_ones(unsigned x);

    函数应该遵循位级整数编码规则,不过你可以假设数据类型int有w=32位,你的代码最多只能包含12个算术运算、位运算和逻辑运算。

    解读题目:当无符号数x包含偶数个1时,返回值为1,否则为返回值为0,假设x的数据类型是int 有w=32位。

    解题思路:要求x所包含的1的个数,可以对x的每个位进行异或运算。如果得到的结果是0,那么就说明x包含偶数个1,则返回值为1,;如果得到的结果是1,那么说明x包含奇数个1,则返回值为0。

    代码编写过程:由于x是个32位int类型数,所以①首先采用折半缩小规模的方法进行逐位异或。②最后得到的x值再与1进行与运算就会得到一个32位中前31均为0,尾数是0或者是1(用于判断是原x包含奇数还是偶数个1),③返回这个值就完成了题目需求。

    代码编写:

    int even_ones(unsigned x){

    x ^= (x >> 16);//等同于x=x^(x>>16)

    x ^= (x >> 8); //等同于x=x^(x>>8)

    x ^= (x >> 4); //等同于x=x^(x>>4)

    x ^= (x >> 2); //等同于x=x^(x>>2)

    x ^= (x >> 1); //等同于x=x^(x>>1)

    return !(x&1);

    }

     

     

     

    遇到的问题及解决:

    1. 一开始对算数移位和逻辑移位混淆,不知道在右移的时候应该补1还是0。

      解决:在相似的重复的练习中摸清楚了算数移位是需要补1而逻辑移位需要补0

    2. 在练习2.13中遇到的两个几乎陌生的函数bis和bic,仅用两个陌生的函数就可以做到or和xor的功能让我无所适从。

      解决:我在草稿纸上根据bis和bic的功能假设了两个8位二进制数,通过bis和bic

      的运算来摸清他们之间的规律。

    3. 对于计算机计算"整数"的MOD算法其实是抱有疑惑,不能很好地判断到底是什么时候会溢出,使得数据结构损坏。

      解决:只好通过做几道练习题来稍稍了解。

    4. 家庭作业中,一开始就懵逼了,题目很简单,但是做起来缺没用想象中那么容易,因为我只是隐约记得以前在C语言中好像学过是有通过位运算来判定所包含的1或者0的个数。

      解决:经过搭档符运锦同学给我的题目解析和解题思路,我根据逐位异或的算法把这道家庭作业的代码写了出来。截图:

      结果:

      即当a为10e5+0时,返回值为0

      若a为10e5+1时,返回值为1

  • 相关阅读:
    【零基础】极星9.5套利详解
    【零基础】极星9.3资金字段详解
    【零基础】易盛9.0API入门三:下单并查询订单状态
    【零基础】极星量化扩展一:如何做跨合约的交易
    【零基础】极星9.3止盈止损用法详解
    【零基础】极星9.3几种套利的说明
    【零基础】MT4量化入门三:写一个双均线指标
    概率与似然
    PCA的计算方法
    隐藏节点数的选择
  • 原文地址:https://www.cnblogs.com/brotherlittlefish/p/4854510.html
Copyright © 2011-2022 走看看