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

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

学习目标

  • 理解逆向的概念
  • 掌握X86汇编基础,能够阅读(反)汇编代码
  • 了解ISA(指令集体系结构)
  • 理解函数调用栈帧的概念,并能用GDB进行调试

教材学习内容总结

  • 本章概述:

    本周学习了c提供的抽象层下面的东西,了解机器级编程。通过编译器产生机器级程序的汇编代码表示,我们了解了编译器和它的优化能力,还有一些机器、数据类型和指令集。机器级程序和它们的汇编代码表示与C程序的差别很大。程序是以指令序列来表示的,每条指令都完成一个单独的操作。编译器必须使用多条指令来产生和操作各种数据结构。
    用字节代码作为程序的低级表示,优点是相同的代码可以在许多不同的机器上执行。

  • x86经历的寻址方式:

    • DOS时代的平坦模式,不区分用户空间和内核空间,不安全。
    • 8086的分段模式
    • IA32的带保护模式的平坦模式。
  • 程序编码和数据格式:

    • 使用GCC编译时候命令行中加入 -o1使用第一级优化 、-o2使用第二级优化
    • gcc -S xxx.c -o xxx.s获得汇编代码,也可以用objdump -d xxx反汇编; 注意函数前两条和后两条汇编代码,所有函数都有,建立函数调用栈帧。
    • b:8位、w:16位、l:32位。
    • 注意: 64位机器上想要得到32代码:gcc -m32 -S xxx.c
    • 格式的注解:ATT和Intel汇编代码格式。
    • 理解寄存器%eax、%ecx、%edx、%ebx为通用寄存器,%esi和%edi可以用来操作数组,%esp和%edp可以操作指针。
    • MOV指令是使用最频繁的指令,注意不能直接从一个内存地址MOV到另一个内存地址,要在寄存器中中转一下。
    • 注意栈顶元素的地址是所有栈中元素地址中最低的。
    • 指针就是地址,局部变量保存在寄存器中。
  • 算数和逻辑操作:

    • leal指令,加载有效地址,是movl指令的一个变形
    • 一元操作只有一个操作数,既是源又是目的。
    • 注意二元操作,源操作数是第一个,目的操作数是第二个,注意减法操作后-前
    • 移位操作先可以给出移位量,第二项再给出要移位的数值。
  • 控制:

    • 用jump指令可以改变一组机器代码指令的执行顺序。对于switch语句可以采用jump table跳转表来完成跳转。
    • 条件码寄存器用来设置跳转的条件位的。
    • leal不改变条件码寄存器。
    • SET指令根据计算t=a-b设置条件码。
    • 有条件跳转(if、while、for)注意看条件码寄存器和无条件跳转(goto)。
    • if-else结构:使用了goto语句。
    • 循环结构:do-while是最基本的循环结构,其他的循环首先会转换成do-while来产生循环代码。每次循环会测试表达式,如果测试为真(非零)继续循环。c语言中三种形式的循环do-while、while和for都可以用一种简单策略来翻译,产生包含一个或多个条件分支的代码。控制条件转移为循环翻译成机器代码提供了基本机制。
    • switch的jt表中引用&&作为新的指针,执行switch语句的关键步骤是通过跳转表来访问代码位置。
  • 过程:

    • IA32程序用程序栈来支持过程调用。注意:栈是向低地址增长的。
    • 栈帧结构:用来传递参数、储存返回信息、保存寄存器、以及本地存储
    • call/ret; 函数返回值存在%eax中
    • leave指令可以使栈做好返回的准备
    • 程序寄存器是唯一能被所有过程共享的资源。

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

  • 对于数据格式的知识

    在书p111页给了数据格式,在汇编代码的后缀。在之后学习mov指令的时候,其中有一个指令movl $Ox4050,%eax ,可是在之后使用中发现movl指令对于双精度浮点数可以进行传送。后来看书,知道了汇编代码也使用后缀‘l’`来表示4字节整数和8字节双精度浮点数。其实并不会产生歧义,因为浮点数使用的是一组完全不同的指令和寄存器。

  • 对于寻址模式

    首先在对于%eax和(%eax)有点疑问,不知道二者样子相同,二者具体有什么不同,后来通过看书上p113的表格,其中有寄存器Ea,操作数值是R[Ea],储存器(Ea)操作数值是M[R[Ea]]。虽然二者看起来样子很相似,但本质还是不一样的,一个是寄存器,另一个则表示缓存器,二者所代表的值也是不同的。

  • 对于栈

    栈在数据结构中就有所接触,遵循先进后出的原则。但是对于为什么栈底的地址大,栈顶的地址值小?如果这样那么栈就不会很大吗?通过网上百度,解决了这一问题。在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在Windows下栈的大小是固定的空间(1M或2M)超过栈的剩余空间会提示overflow。就类似于数组中的内个i,stack[i],入栈后i-1,出栈后i+1,i始终指向栈顶。

  • 对于Switch语句

    起初书上给的例子是有开关100、102~104、106,通过汇编代码,首先将106与100做差值运算,这样就会简化汇编语言的操作。可是对于这个例子102 开关之后没有break;既没有跳出语句,会继续操作103的代码,汇编语言是怎么实现的?通过自己动手操作了书上的例子后,两种情况有不同的目的地址,将这两个代码块都汇总到将result加11的代码,这样就解决了问题。

代码练习以及问题

  • P107

    • 利用vim编写一个xxx.c文件
    • gcc -S xxx.c得到汇编文件xxx.s
    • 利用vim进入xxx.s或者利用cat xxx.s查看xxx.s的内容

  • P108反汇编练习

    • 利用gcc -c xxx.c产生二进制文件xxx.o
    • 利用objdump -d xxx.o来看到反汇编后的内容

  • 教材P121练习题3.9验算反馈

    • 练习题给出汇编代码,要求补全C语言代码,补全后,下图为实际验算

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

  • 习题3.1

    其中有一个是260(%ecx,%edc)计算值,一直把260当作十进制运算,可是没有结果,后来发现运算时需要将其转换为16进制再次参与运算,这样260=Ox104这样答案也就得到了。

  • 习题3.2

    指令的补全,对于mov指令格式为mov s,d,将s传送给d。但是对于MOV %eax,(%eax) 为什么是MOVL而不是MOVW?后来知道%ax为寄存器16位,%eax是扩展寄存器32位,这样就需要传送双字,就需要MOVL指令。

  • 习题3.29

    对于switch语句的汇编代码,最初在做的时候存在序号问题,后来仔细查阅了解C语言中case对应的序号对应着跳转表中的序号,要注意的是候跳转表中的序号从0开始的!

代码托管

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

这周在本章下了很多时间,也补了很多汇编语言的功课,总之还是要去认认真真去对待每一个章节的知识点,这样才能融汇贯通。

学习进度条

代码行数(新增/累积) 博客量(新增/累积) 学习时间(新增/累积) 重要成长
目标 5000行 30篇 400小时
第一周 200/200 2/2 20/20
第二周 300/500 2/4 18/38
第三周 500/1000 3/7 22/60
第四周 300/1300 4/9 30/90

尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。

参考:软件工程软件的估计为什么这么难软件工程 估计方法

  • 计划学习时间:15小时

  • 实际学习时间:15小时

(有空多看看现代软件工程 课件
软件工程师能力自我评价表
)

参考资料

原文地址:https://www.cnblogs.com/hxl681207/p/7988784.html