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

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

教材学习内容总结

  • X86 寻址方式经历三代:  
    1 DOS时代的平坦模式,不区分用户空间和内核空间,很不安全  
    2 8086的分段模式  
    3 IA32的带保护模式的平坦模式

  • CPU包含一组8个存储32位值的寄存器 存整数数据和指针:eax,ecx,edx,ebx,esi,edi,esp,ebp。 大多数情况下前六个都用作通用寄存器,eax,ecx,edx的存储和恢复惯例不同于ebx,edi,esi(前三者为被调用者保存,后三者为调用者保存)。最后两个用于存储指针,由于在过处理中非常重要,分别指向栈帧的顶部和底部,必须保持。

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

  • 两种抽象:

    • 指令集结构ISA:是机器级程序的格式和行为,定义了处理器状态、指令的格式,以及每条指令对状态的影响。
    • 机器级程序使用的存储器地址是虚拟地址,看上去是一个非常大的字节数组,实际上是将多个硬件存储器和操作系统软件组合起来。
  • ATT与Intel:Intel省略了指示大小的后缀、寄存器前面的%、用不同的方式来描述存储器中的位置。

  • 一些通常对C语言程序员隐藏的机器代码在IA32中是可见的:

  • 程序计数器(在IA32中,通常称为“PC”,用%eip表示)指示将要执行的下一条指令在存储器中的地址。
  • 整数寄存器:包含8个命名的位置,分别存储32位的数值,这些寄存器可以存储地址(对应C语言的指针)或整数数据,有的寄存器被用来记录某些重要的程序状态,其他的寄存器用来保存临时数据,例如过程的局部变量和函数的返回值。
  • 条码寄存器:保存着最近执行的算术或逻辑指令的状态信息,他们用来实现控制或数据流中的条件变化。
  • 浮点寄存器:一组浮点寄存器存放浮点数据

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

  • gcc -S xxx.c -o xxx.s 获得汇编代码,也可以用objdump -d xxx 反汇编

  • 64位机器上想要得到32代码:gcc -m32 -S xxx.c

  • 二进制文件可以用od 命令查看,也可以用gdb的x命令查看。 有些输出内容过多

  • 当一个源文件生成了'.o'的目标二进制文件后,无法直接查看。

  • 数据传送指令有三个变种:movb(传送字节)movw(传送字)movl(传送双字)

  • 寄存器:

    esi edi可以用来操纵数组

    esp ebp用来操纵栈帧

    对于寄存器,特别是通用寄存器中的eax,ebx,ecx,edx,要理解32位的eax,16位的ax,8位的ah,al都是独立的

  • 操作数的三种类型:立即数、寄存器、存储器

    立即数:即常数值

    寄存器:表示某个寄存器内容

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

  • leal指令:从存储器读取数据到寄存器,是将有效地址写入到目的操作数(不改变任何条件码)

  • CMP:与sub指令相似,但只设置条件码二不改变目的寄存器的值
  • TEST:与AND指令相似,但只设置条件码二不改变目的寄存器的值
  • jmp是无条件跳转,可以是直接,也可以是间接跳转;条件跳转只能是直接跳转
  • 栈帧结构:机器用栈来传递过程参数、存储返回信息、保存寄存器用于以后恢复,以及本地存储
  • 为单个过程分配的那部分栈称为栈帧,寄存器%ebp为帧指针,%esp为栈指针
  • call指令:将返回地址入栈,并跳转到被调用过程的起始处,返回地址是在程序中紧跟在call后面的那条指令的地址
  • ret指令从栈中弹出地址,并跳转到这个位置 寄存器%eax、%edx、%ecx被划分为调用者保存寄存器,寄存器%ebx、%esi、%edi被划分为被调用者保存寄存器
  • call指令:call指令有一个目标,即指明被调用过程起始的指令地址; call指令的效果是将返回地址入栈。并跳转到被调用过程的起始处。
  • ret指令:ret指从栈中弹出地址,并跳转到这个位置;ret指令返回到call指令后的那条指令。
  • leave指令:leave指令可以使栈做好返回的准备,leave指令的使用在返回前,既重置了栈指针,也重置了帧指针
  • 使用GDB的堆栈跟踪功能(GDB中有很多针对调用堆栈的命令,都需要一个目标栈帧,例如打印局部变量值的命令)

    1.在栈帧之间切换

    frame args 将当前栈帧设置为args(编号或Address)指定的栈帧,并打印该栈帧的简要信息。

    up n 向上回退n个栈帧(更外层),n默认为1.

    down n 向下前进n个栈帧(更内层),n默认为1.

    2.打印栈帧信息(不移动栈帧)

    frame 打印当前栈帧的简要信息。

    info frame 打印当前栈帧的详细信息。

    info frame args 打印指定栈帧的详细信息。

    info args 打印函数参数信息。

    info locals 打印当前可访问的局部变量的信息。

    3.打印调用堆栈

    backtrace 打印全部栈帧的简要信息,按Ctrl-c可终止打印。

    backtrace n 打印最内层的n个栈帧的简要信息。

    backtrace -n 打印最外层的n个栈帧的简要信息。

    backtrace full 打印全部栈帧的详细信息。

    backtrace full n 打印最内层的n个栈帧的详细信息。

    backtrace full -n 打印最外层的n个栈帧的详细信息。

教材学习中的问题和解决过程

3.2 练习中关于改变push $0xff的指令后缀,请教同学后明白对于栈操作都是双字操作,所以不管是pop还是push都应该使用pushl和popl

实验过程中发现gcc -s 对于错误描述的很详细,我们根据描述即可发现问题。

纠错后:

课后作业中的问题和解决过程

main.c:

main.s:

main.o:

反汇编:

删去“.”开头的编译指令并注释:

本周代码托管截图

其他(感悟、思考等,可选)

这周的学习内容涉及许多汇编的知识,需要我们对汇编的相关知识进行再回顾与复习,加深巩固了对于汇编的理解。并且结合实验内容,从中体会到自己动手与眼高手低的区别,当时对汇编知识的一知半解,可能更多的原因在于并没有亲自动手去进行操作,希望通过这次的学习能够把汇编知识真正学好。

学习进度条

 代码行数(新增/累积)博客量(新增/累积)学习时间(新增/累积)重要成长
目标  4000行  24篇  400小时   
第一周  150/150  1/1  15/15  对Linux有了初步的认识
第二周  200/350 1/2 20/35 vim的使用 
第三周  250/600 1/4 20/55 各种信息的表示方法
第五周  250/850 1/5 25/80 汇编与反汇编

参考资料

原文地址:https://www.cnblogs.com/5301z/p/5967982.html