郝博雅

导航

2017-2018-1 20155205 《信息安全系统设计基础》第十四周学习总结

2017-2018-1 20155205 《信息安全系统设计基础》第十四周学习总结

一、第三章《程序的机器极表示》基础知识学习

IA32指令的细节

1)区分字节与字

  • Intel使用术语“字”表示16位数据类型而“字节”代表的是8个位的数据。

2)访问信息

传送指令:move 源--> 目的地(两个操作数不能同时指向存储器,需要寄存器周转)

指针:就是地址,间接引用指针就是将指针放入一个寄存器中,然后在存储器中使用这个寄存器

3)算数和逻辑操作

  • 其实讲的就是加减乘除、与或非这一系列的指令:

加载有效地址指令:leal S, D ==> (&S-->D) 将有效地址写入到目的操作数中去

4)改变执行顺序

a.机器机制
  • 条件码寄存器,常见的有:

b.翻译条件分支
  • 通过将C代码翻译成goto语句可以方便我们理解汇编代码的执行方式。汇编程序通过条件测试和跳转来实现循环,我们常见的循环语句其实都是翻译成了do-while形式的:

  • while循环会先转成do-while形式:

c.条件传送指令
  • 先计算出可能的多种不同结果。如条件语句:x < y ? y-x : x-y ; 就会先计算两种结果y-x和x-y的值,然后再判断x,y的大小

如何调用函数

  • 单个过程分配一个栈帧结构:

  • 假设函数A调用函数B,我们称A函数为"调用者",B函数为“被调用者”则函数调用过程可以这么描述:

    (1)先将调用者(A)的堆栈的基址(ebp)入栈,以保存之前任务的信息。

    (2)然后将调用者(A)的栈顶指针(esp)的值赋给ebp,作为新的基址(即被调用者B的栈底)。

    (3)然后在这个基址(被调用者B的栈底)上开辟(一般用sub指令)相应的空间用作被调用者B的栈空间。

    (4)函数B返回后,从当前栈帧的ebp即恢复为调用者A的栈顶(esp),使栈顶恢复函数B被调用前的位置;然后调用者A再从恢复后的栈顶可弹出之前的ebp值(可以这么做是因为这个值在函数调用前一步被压入堆栈)。这样,ebp和esp就都恢复了调用函数B前的位置,也就是栈恢复函数B调用前的状态。

  • 这个过程在AT&T汇编中通过两条指令完成,即:

leave
ret
  • 这两条指令更直白点就相当于:
mov   %ebp , %esp
pop    %ebp

存储器越界引用和缓冲区溢出

  • 由于C对于数组不进行边界检查,在栈帧结构中局部变量和状态信息,特别是返回地址也是在栈中存放的,对越界数据的访问和修改将破坏掉这些数据,当ret试图返回的时候,错误的地址(甚至是被修改的恶意目的地地址)会带来严重的安全隐患。

  • 上图两段代码展示了一个get函数在只有8个字节的空间中,存入了太多的数据,使得栈数据不断被破坏的过程。

对抗方式:

① 栈随机化:在程序开始时,随机分配一段0-n的空间,使得栈的位置每次运行都不同。栈地址随机化,即使在一台机器上运行同样的程序,地址都是不同的。

② 栈破坏检测:插入栈保护者,俗称金丝雀的一段随机大小。

如:在数组buf和保存状态之间放入一个特殊的金丝雀,代码检查该值,确定栈状态是否被改变

③ 限制可执行代码区域。

二、学习中遇到的问题和解决方案

『问题一』:如何理解栈?

  • push指令相当于:sub $4, %esp 然后move %ebp, (%esp)

  • pop指令相当于:move (%esp), %eax 然后 add $4, %esp

  • 栈的数据结构是向低地址方向增长的,无论如何esp都是指向栈顶

『问题二』:现在已经知道while循环汇编语句是如何产生的,那么for循环和switch是怎么写的呢?

  • for循环也是一样的道理,先转成do-while形式:

  • switch语句:使用一个数组作为跳转表

『问题三』:数组是如何进行分配与访问的?

1)基本原则

  • 声明过后数组的具体位置:

  • 汇编代码使用move指令来简化访问:
movl (%edx , %ecx, 4), %eax

假设E是一个int类型的数组,我们要计算E[i]的值,在此,E的地址放于edx中,而i放于ecx中,我们通过上面的指令就完成了Xe + 4i来读取其中的值,放在了eax中去。

2)指针运算:对指针的运算其实际是按照相应的数据大小进行了伸缩

point + i = Xp + (数据大小)L * i
  • 对于二维数组,我们定义一个int D[5][3]的数组,形如:

如果我们要计算D[4,2]的地址,就可以使用 D[i][j] = Xd + L(C * i + j) = D[0,0] + 4 * (3 * 4 + 2),由于每组有3个数据,所以跳过一组就要乘以3,跳过4组就12个,再加上偏移的2,就是最后一个数据的地址了。

3)理解指针:数组与指针关系密切

①指针用&符号创造、用*符号间接引用

②指针从一个类型 转为另外一个类型,只是伸缩因子变化,不改变它的值

③指针可以指向函数:int (*f)(int *)从f开始由内往外阅读,首先f代表的是一个指向函数的指针,这个函数的参数是int * 返回值是int

三、反馈

  • 同伴(20155218 徐志瀚)对我的反馈:郝博雅同学在这次的博客中同样是以问题为导向,在内容里使用问题来引出小节的重点知识,并给出了一些解决的方法。同时,图片的使用也能帮助我们更好的理解读完之后,受益匪浅。另外,郝博雅同学帮助我调整了我的博客的形式,解决了我的问题。

posted on 2017-12-24 20:15  郝博雅  阅读(186)  评论(0编辑  收藏  举报