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

第五周(10.05-10.11):

学习计时:共xxx小时

读书:参考资料:课本

代码:

作业:

博客:参考博客:闫佳歆(特此声明)  

一、学习目标

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

二、学习资源

1. 教材:第三章《程序的机器级表示》,详细学习指导见:重点是3.7,3.11

2. 课程资料:https://www.shiyanlou.com/courses/413 实验四,课程邀请码:W7FQKW4Y

3. 教材中代码运行、思考一下,读代码的学习方法见

三、学习方法

1. 进度很重要:必须跟上每周的进度,阅读,练习,问答,项目。我会认真对待每一位同学,请你不要因为困难半途而废。

2. 问答很重要:遇到知识难点请多多提问,这是你的权利更是您对自己负责的义务。问答到博客园讨论小组:http://group.cnblogs.com/103791/
3. 实践很重要:解决书中习题,实践书中实例,完成每周项目,才算真的消化了这本好书。通过实验楼环境或自己安装的虚拟机在实践中进行学习
4. 实验报告很重要:详细记录你完成项目任务的思路,获得老师点评和帮助自己复习。学习完成后在博客园中(http://www.cnblogs.com/)把学习过程通过博客发表,博客标题“学号-信息安全系统设计基础第五周学习总结”

四、学习任务

1. 阅读教材,完成课后练习(书中有参考答案)

3.1-3.7中练习,重点:3.1,3.3,3.5,3.6,3.9,3.14,3.15,3.16,3.22,3.23,3.27,3.29,3.30,3.33,3.34

2. 考核:练习题把数据变换一下

3. 实验:需要动手的到实验楼中练习一下

4. 深化、实践题目,额外加分

、后续学习预告(可选):

第四章《处理器体系结构》

、学习过程

第三章 程序的机器级表示

一、教材导读

本章学习内容是汇编语言,现在直接写汇编的机会不多了,但一定要能读懂,信息安全的核心思维方式“逆向”在这有很好很直接的体现,反汇编就是直接的逆向工程。

本章重点是3.7,但没有3.1-3.6的基础也是不行,如果想真正的提高动手能力,3.11如何用GDB调试汇编要好好练习一下,不过大多GDB技巧大家都会了。

3.1-3.7中练习,重点:3.1,3.3,3.5,3.6,3.9,3.14,3.15,3.16,3.22,3.23,3.27,3.29,3.30,3.33,3.34

练习:

x的高32位为xh,低32位为xl

y的符号位扩展成32位之后为ysys0或者-1)。

dest_h = (xl*ys)_l + (xh*y)_l + (xl*y)_h

dest_l = (xl*y)_l

注意,所有的乘法都是unsigned*unsigned

也就是说对于 1*(-1),如果存入两个寄存器中,那么高32位是0,低32位是-1 

相当于 1*(UNSIGNED_MAX)

p104, p105: X86 寻址方式经历三代:

     1  DOS时代的平坦模式,不区分用户空间和内核空间,很不安全
     2  8086的分段模式
     3  IA32的带保护模式的平坦模式

p106: ISA的定义,ISA需要大家能总结规律,举一反三,比如能对比学习ARM的ISA;PC寄存器要好好理解;

p107: gcc -S xxx.c -o xxx.s 获得汇编代码,也可以用objdump -d xxx 反汇编; 注意函数前两条和后两条汇编代码,所有函数都有,建立函数调用栈帧,应该理解、熟记。

注意:  64位机器上想要得到32代码:gcc -m32 -S xxx.c
       MAC OS中没有objdump, 有个基本等价的命令otool 
       Ubuntu中 gcc -S code.c (不带-O1) 产生的代码更接近教材中代码(删除"."开头的语句)

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

            od code.o | more
            od code.o > code.txt

p109: gcc -S 产生的汇编中可以把 以”.“开始的语句都删除了再阅读

p110: 了解Linux和Windows的汇编格式有点区别:ATT格式和Intel格式

p111: 表中不同数据的汇编代码后缀

p112: 这几个寄存器要深入理解,知道它们的用处。esi edi可以用来操纵数组,esp ebp用来操纵栈帧。 对于寄存器,特别是通用寄存器中的eax,ebx,ecx,edx,大家要理解32位的eax,16位的ax,8位的ah,al都是独立的,我们通过下面例子说明:

    假定当前是32位x86机器,eax寄存器的值为0x8226,执行完addw $0x8266, %ax指令后eax的值是多少? 
解析:0x8226+0x826=0x1044c, ax是16位寄存器,出现溢出,最高位的1会丢掉,剩下0x44c,不要以为eax是32位的不会发生溢出.

p113: 结合表,深入理解各种 寻址方式;理解操作数的三种类型:立即数、寄存器、存储器;

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

p114: MOV相当于C语言的赋值”=“,注意ATT格式中的方向,

另外注意不能从内存地址直接MOV到另一个内存地址,要用寄存器中转一下。能区分MOV,MOVS,MOVZ,掌握push,pop

p115/p116: 栈帧与push pop; 注意栈顶元素的地址是所有栈中元素地址中最低的。

p117: 指针就是地址;局部变量保存在寄存器中。

p119: 结合表理解一下算术和逻辑运算, 注意目的操作数都是什么类型 特别注意一下减法是谁减去谁 注意移位操作移位量可以是立即数或%cl中的数

p123: 结合C语言理解一下控制部分,也就是分支(if/switch),循环语句(while, for)如何实现的。考验大家举一反三的学习能力。控制中最核心的是跳转语句:有条件跳转p128(实现if,switch,while,for),无条件跳转jmp(实现goto)

p124: 有条件跳转的条件看状态寄存器(教材上叫条件码寄存器) 注意leal不改变条件码寄存器 思考一下:CMP和SUB用在什么地方 p125: SET指令根据t=a-b的结果设置条件码

p127: 跳转与标号

p130/p131: if-else 的汇编结构

p132/p133: do-while

p134/p135: while

p137/p138: for

p144/p145: switch

p149: IA32通过栈来实现过程调用。掌握栈帧结构,注意函数参数的压栈顺序.

p150/p151: call/ret; 函数返回值存在%eax中

p174: bt/frame/up/down :关于栈帧的gdb命令

 

1.数据格式

· 由于是从16位体系结构扩展成32位,intel用术语字(word)表示16位数据类型,因此32位为双字(double words),64位数为4字(quad words)。

·  以下是比较容易模糊的数据类型大小:

          32位机上:float 4    long int 4   double 8    longlong 8    char* 4   unsigned long 4

          64位机上:float 4    long int 8   double 8    longlong 8    char* 8   unsigned long 8

          另外,GCC long double表示扩展精度(10字节),出于存储器性能考虑,会被存储为12字节

 

2.访问信息

· 一个IA32 CPU包含一组8个存储32位值的寄存器,用以存整数数据和指针:eax,ecx,edx,ebx,esi,edi     esp,ebp

大多数情况下前六个都用作通用寄存器,eax,ecx,edx的存储和恢复惯例不同于ebx,edi,esi(前三者为被调用者保存,后三者为调用者保存,详见3.7.3);

最后两个用于存储指针,由于在过处理中非常重要,分别指向栈帧的顶部和底部,必须保持。

 

 

3.计算机machine-level programming重要的两类抽象

一个重要抽象,是将format and behavior of a machine-level program抽象形成instruction set architecture,即ISA(指令集体系结构)

对于ISA,要有以下基本观念:IA32的ISA和x86-64的ISA,以及其他大多数ISA,在抽象时都将指令按顺序执行抽象。

但是处理器的硬件可以并发地执行许多指令,并且采用了一些safeguards来确保并行执行之后的结果和一条一条顺序执行的结果一样。

第二个重要抽象,是将整个计算机中的memory system用虚拟地址来抽象,使得memory system就好像一个“连续”的字节块。

 

 4.反汇编

通常,编写程序是利用高级语言如C,Pascal等语言进行编程的,后再经过编译程序生成可以 被计算机系统 直接执行的执行文件。
反汇编即是指将这些执行文件反编译还原成 汇编语言或其他 高级语言。但通常反编译出来的程序与原程序会存在许多不同,虽然执行效果相同,但程序代码 会发生很大的变化,非编程高手很难读懂。
另外,有许多程序也可以 进行逆向操作即 反编译 以求修改,例如Flash的文件生成的SWF文件,也可以被反汇编成Flash原码,但会发现与原程序有很大变化。

5.操作数指示符

操作数:指示出执行一个操作中要引用的源数据值,以及放置结果的目标位置。

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

结果存放的两种可能:寄存器中、存储器中

 

6.寻址方式:

(1)立即数寻址方式

格式:$后加用标准c表示法表示的整数,如$0xAFF

(2)寄存器寻址方式

%eax,与汇编中学过的AX寄存器类比。

 (3)存储器寻址方式

  • 直接寻址方式
  • 寄存器间接寻址方式
  • 寄存器相对寻址方式
  • 基址变址寻址方式
  • 相对基址变址寻址方式

7.算术和逻辑操作

       这类操作符大致分为四个小类:

           1、加载有交地址(leal),通常用来执行简单算术操作,目前还不太懂这个与mov的区别

           2、一元或二元操作:incl  decl  negl  notl  addl  subl  imull  xorl  orl  andl

           3、移位操作 :sall==shll(填0)  sarl(算术右移,填符号位)  shrl(逻辑右移,填0

           4、特殊算术操作:imull(有符号64位乘法)  mull(无符号64位乘法)  cltd(转换为四字)

                idivl(有符号除法)   divl(无符号除法)

 

8.gcc编译器编译流程:

·C预处理器扩展源代码;

·编译器产生两个源代码的汇编代码 p1.s p2.s

·汇编器将汇编代码转换成二进制目标代码文件 p1.o p2.o

·链接器将两个目标代码文件与实现库函数的代码合并,并产生可执行代码p

 

9.push&pop

1)堆栈

需要注意两点:

1.后进先出

2.栈指针指向栈顶元素

3.栈朝低地址方向增长

2)压栈push

指令格式——PUSH r16/m16/seg

指令功能

第一步:SPSP-2  ;堆栈指针SP上移

第二步:(SS):(SP)r16/m16/seg  ;字操作数存入堆栈顶部

注意 堆栈操作必须至少以字为单位,这时栈顶指针-2

如果压入的是双字,栈顶指针-4

3)出栈pop

指令格式——POP r16/m16/seg
指令功能

第一步:r16/m16/seg← (SS):(SP) ;栈顶的一个字传送到指定的目的操作数

第二步:SPSP2   ;堆栈指针SP下移,指向新的栈顶

栈顶指针变化同压栈。

10.循环

·do-while

一般形式如下:
do
语句;
while(表达式);
 

·while

一般形式如下:
while(表达式)
 

·for

for语句是循环控制结构中使用最广泛的一种循环控制语句,特别适合已知循环次数的情况。
一般形式如下:
for ( [表达式 1]; [表达式 2 ]; [表达式3] )

七、遇到的问题及解决

1.抽象的概念理解的不是很清晰。比如这句:将整个计算机中的memory system用虚拟地址来抽象,使得memory system就好像一个“连续”的字节块。

 2.如何快速读懂反汇编的汇编代码?

链接:http://www.zhihu.com/question/22299883

八、其他

1指针其实是地址,间接引用指针就是将该指针放在一个寄存器中 ,然后在间接存储器引用中引用这个寄存器

2、局部变量通常保存在寄存器中,而不是存储器

原文地址:https://www.cnblogs.com/20135213lhj/p/4869853.html