20145231《信息安全系统设计基础》第五周学习总结

20145231第5周《信息安全系统设计基础》学习总结

教材内容总结

寻址方式历史

DOS时代的平坦模式:不区分用户空间和内核空间,很不安全。

8086的分段模式

IA32的带保护模式的平坦模式

程序编码

编译:gcc -01 -o p p1.c,-01:表示使用第一级优化。通常提高优化级别会使最终程序运行得更快,但是编译时间可能会变长,用调试工具对代码进行调试会更困难。(实际中,第二级优化-02被认为是较好的选择)

两种抽象:

指令集结构ISA:是机器级程序的格式和行为,定义了处理器状态、指令的格式,以及每条指令对状态的影响。

机器级程序使用的存储器地址是虚拟地址,看上去是一个非常大的字节数组,实际上是将多个硬件存储器和操作系统软件组合起来。

一些通常对C语言程序员隐藏的机器代码在IA32中是可见的:
程序计数器(在IA32中,通常称为“PC”,用%eip表示)指示将要执行的下一条指令在存储器中的地址。

整数寄存器:包含8个命名的位置,分别存储32位的数值,这些寄存器可以存储地址(对应C语言的指针)或整数数据,有的寄存器被用来记录某些重要的程序状态,其他的寄存器用来保存临时数据,例如过程的局部变量和函数的返回值。

条码寄存器:保存着最近执行的算术或逻辑指令的状态信息,他们用来实现控制或数据流中的条件变化。

浮点寄存器:一组浮点寄存器存放浮点数据

一条机器指令只执行一个非常基本的操作

Ubuntu中gcc -S code.c(不带-O1)产生的代码更接近教材中代码(删除"."开头的语句)

栈帧结构:机器用栈来传递过程参数、存储返回信息、保存寄存器用于以后恢复,以及本地存储。为单个过程分配的那部分栈称为栈帧。最顶端的栈帧以两个指针界定,寄存器%ebp为帧指针,寄存器%esp为栈指针。

汇编代码(函数前两条和后两条汇编代码,所有函数都有,建立函数调用栈帧):(课本)

前两条:

pushl %ebp 将寄存器%ebp的内容压入程序栈

movl %esp,%ebp 得到新栈低,将当前栈顶赋予栈低

后两条:

popl %ebp过程调用结束,恢复旧栈低

ret 子程序的返回指令

二进制文件可以用od命令查看,也可以用gdb的x命令查看。有些输出内容过多,可以使用more或less命令结合管道查看,也可以使用输出重定向来查看。

od code.o | more

od code.o > code.txt

数据格式

C语言数据类型在IA32中的大小:

IA32不支持64位整数运算

大多数GCC生成的汇编代码指令都有一个字符后缀,表明操作数的大小。

访问信息

一个IA32的中央处理器单元包含一组8个存储32位数值的寄存器。所有八个寄存器都可以作为16位(字)或32位(双字)来访问:

%esi,%edi可以用来操纵数组

%esp,%ebp用来操纵栈帧

可以独立访问前四个寄存器的两个低位字节(后向兼容)

32位的%eax,16位的%ax,8位的%ah,%al都是独立的

操作数三种类型:

立即数,即常数值

寄存器,表示某个寄存器的内容

存储器,根据计算出来的地址(有效地址)访问某个存储器位置

有效地址的计算方式:Imm(Eb,Ei,s) = Imm + R[Eb] + R[Ei]*s

C语言中“指针”其实就是地址。间接引用指针就是将该指针放在一个寄存器中,然后在存储器引用中使用这个寄存器。

局部变量通常是保存在寄存器中,而不是存储器中。寄存器访问比存储器访问要快得多。

过程

转移控制:

call指令:call指令有一个目标,即指明被调用过程起始的指令地址; call指令的效果是将返回地址入栈。并跳转到被调用过程的起始处。

ret指令:ret指从栈中弹出地址,并跳转到这个位置;ret指令返回到call指令后的那条指令。

leave指令:leave指令可以使栈做好返回的准备

寄存器使用惯例:%eax,%edx,%ecx 调用者保存寄存器;%ebx,%esi,%edi 被调用者保存寄存器;%ebp,%esp 保持寄存器。

保存某值的两种方式:由调用者保存,在调用之前就压进栈;由被调用者保存,在刚被调用的时候就压进栈,并在返回之前恢复。

实验楼学习总结

实验代码:

int h(int x)
{
  return x + 1128;
}

int z(int x)
{
  return h(x);
}

int main(void)
{
  return z(9) + 10;
}

以学号命名的文件夹创建代码

objdump加文件名查看汇编代码(编译之后;gcc+文件名+ -o +xxx.c)

代码相关文件

编译并且查看二进制

尝试使用gdb中的指令调试

无法查看栈针信息

在虚拟系统中安装git

git出错

学习中遇到的问题及解决过程

一、教材学习中的问题:

值得注意的和未理解的

1.leal指令和movl指令的区别:

前者计算有效地址,后者从指定位置读入数据

2.链接器作用(汇编与反汇编代码区别):

代码的地址范围不同;链接器确定存储全局变量accum的地址(p109)

3.局部变量保存在寄存器中,全局变量保存在存储器中吗?

4.p119页中逻辑移位和算术移位知道在操作过程中的区别,不理解其本质区别。

5.条件码寄存器定义:p124,(即汇编中学过的单字节寄存器)

6.cmp和sub用在什么地方:

(cmp和test都是不改变寄存器的值,test多用于判断操作数是否为零)

cmp:只设置条件码,不能改变寄存器的值;

sub:可以改变寄存器的值;

7.p129习题3.15第二小题,复习补码如何转化为源码,再进行加减运算;

8.p133 如何确定哪些寄存器放哪些程序值?

根据其映射关系(根据图3.14例)

9.逆向工程:其实关键就在于找这种映射关系

10.p139 习题3.23 第7.8行代码不是太理解

11.p144 习题3.27

12.p148 习题中case(?)是如何根据汇编代码和跳转表确定的?

13.栈帧:面向单个过程 寄存器:面向多个过程

14.理解ret和call(利用图解)

15.区分过程调用和习题3.30中的将程序计数器的值放入整数寄存器唯一方法的代码

16.寄存器的划分依据:调用者保存寄存器和被调用者保存寄存器还有%ebp和%esp

17.p152解释了如何保证寄存器中的数据不在调用过程中被覆盖

18.gcc分配从不使用空间:保证访问数据的严格对齐

19.p157 习题3.34代码不理解(其实还是对过程调用时栈帧的变化不理解)

二、实验楼学习中的问题:

1.使用学号创建文件夹

解决过程:查找了touch mkdir命令的用法,学会了给文件夹赋权限

2.使用gdb调试相关代码,但是没有栈针的信息

解决过程:待解决

3.虚拟机的安装没有问题,但是可能因为自己电脑的原因导致虚拟机时而能打开,时而不能打开,之前学习java时已经使用git add、git push的方式托管过代码,知道要先设置用户名和密码,还有一系列步骤,但是我在使用实验楼托管代码时,有查找方法,实验楼自带代码库,只要打开那个目录git add *、git push就行,如图;

显示出错;

解决过程:用真实虚拟机的安装步骤进行托管

心得体会

本周学习态度认真,学到了很多新的知识。主要是对书上的内容进行了深入学习,完成并思考了相关习题,前面学习相对顺利,但是后面switch语句的汇编程序如何转化为C语言,以及栈针的过程调用不太理解。实验楼主要就是敲入一段代码体会反汇编、gdb调试。机器级程序的运行比想象中的要复杂,尤其是过程和栈针的部分,还是不太理解过程调用中栈针的变化。希望在接下来的学习中加深理解。

代码托管截图

托管链接

学习进度条

博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 30篇 400小时
第一周 2/2 20/20 学习了Linux核心命令
第二周 2/4 21/41 学习了vim、gcc、gdb指令
第三周 2/6 20/61 学习了信息的表示和处理,了解了二进制在计算机系统中的重要性
第五周 2/8 20/81 学习了机器级程序,读懂汇编代码
posted on 2016-10-16 22:00  xzhkuma  阅读(185)  评论(4编辑  收藏  举报