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

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

参考教材导读与每周考试重点---不断更新

信息安全的核心思维方式“逆向”在这有很好很直接的体现,反汇编就是直接的逆向工程。

反汇编(Disassembly):把目标代码转为汇编代码的过程,也可以说是把机器语言转换为汇编语言代码、低级转高级的意思,常用于软件破解(例如找到它是如何注册的,从而解出它的注册码或者编写注册机)、外挂技术、病毒分析、逆向工程、软件汉化等领域。学习和理解反汇编语言对软件调试、漏洞分析、OS的内核原理及理解高级语言代码都有相当大的帮助,在此过程中我们可以领悟到软件作者的编程思想。总之一句话:软件一切神秘的运行机制全在反汇编代码里面。

通常,编写程序是利用高级语言如C,C++,Delphi等高级语言进行编程的,然后再经过编译程序生成可以被计算机系统直接执行的文件(机器语言)。反汇编即是指将这些执行文件反编译还原成汇编语言或其他语言。但通常反编译出来的程序与原程序会存在些许不同,虽然执行效果相同,但程序代码会发生很大的变化,要读懂反汇编需要有扎实的高级语言编写功底和汇编功底。

X86 寻址方式:

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

ISA的定义

指令集体系结构(ISA)定义了处理器状态、指令的格式、以及每条指令对状态的影响。大多数ISA包括IA32和x84-64,将程序的行为描述成好像每条指令是按顺序执行的。

  • 汇编命令与反汇编命令

gcc -S xxx.c -o xxx.s获得汇编代码,用gcc -c code.c产生目标文件code.o(二进制文件,无法直接查看),用objdump -d xxx.o反汇编可以查看目标代码文件内容。

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

前两条:
pushl %ebp          将寄存器%ebp的内容压入程序栈
movl %esp,%ebp      得到新栈低,将当前栈顶赋予栈低
后两条:
popl %ebp           过程调用结束,恢复旧栈低
ret                 子程序的返回指令
64位机器上想要得到32代码:gcc -m32 -S xxx.c

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

查看二进制文件

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

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

不同数据的汇编代码后缀

image
Linux和Windows的汇编格式区别

1 Intel代码省略了指示大小的后缀。
2 Intel代码省略了寄存器名字前面的'%'符号。
3 Intel代码用不同的方式来描述寄存器中位置。
4 在带有多个操作数的指令情况下,列出操作数的顺序相反。

ATT是GCC、OBJDUMP和其它一些我们使用的工具的默认格式。Microsoft的工具、以及来自Intel的文档,其汇编代码都是Intel格式的。使用gcc -S -masm=intel code.c可以使GCC产生Intel格式的代码。
寄存器

esi edi可以用来操纵数组,esp ebp用来操纵栈帧。32位的eax,16位的ax,8位的ah,al都是独立的。

  • 寻址方式

image
操作数三种类型

立即数,即常数值
寄存器,表示某个寄存器的内容
存储器,根据计算出来的地址(有效地址)访问某个存储器位置。

有效地址

计算方式Imm(Eb,Ei,s) = Imm + R[Eb] + R[Ei]*s
MOV
  • MOV

相当于C语言的赋值“=”,不能从内存地址直接MOV到另一个内存地址,要用寄存器中转一下。

MOV类中的指令将源操作数的值复制到目的操作数中,源操作数指定的值是一个立即数,存储在寄存器或存储器中,目的操作数指定一个位置,要么是一个寄存器,要么是一个存储器地址。

  • push与pop

先进后出:push将数据压入栈中,pop弹出,弹出的永远是最近被压入的。用数组实现栈,进行操作的一端为栈顶。栈向下增长,栈顶元素的地址是所有栈中元素地址中最低的。栈指针%esp保存栈顶元素的地址。

源操作数、目的操作数应为字操作数。

  • 指针

C语言中“指针”其实就是地址。

  • 局部变量

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

  • 算术和逻辑运算

image

1、一元操作:只有一个操作数,既是源又是目的,可以是一个寄存器,或者存储器位置。

2、二元操作:第一个操作数可以是立即数、寄存器或者存储器位置;第二个操作数既是源也是又是目的,可以是寄存器或者存储器位置,但是不能同时是存储器位置。

操作的顺序:第二个操作数 操作符 第一个操作数

3、移位操作:先给出移位量,第二项给出要移位的数值。

源操作数(移位量):立即数或者放在单字节寄存器元素%cl中。目的操作数:一个寄存器或是一个存储器位置。

  • 使用disassemble指令获取汇编代码(因为之前执行的命令中有-m32,所以此处显示的是32位汇编代码)

image

  • i r指令查看各寄存器的值

image

可见此时主函数的栈基址为0xffffd058,用x 0xffffd058指令查看内存地址中的值:

image

因此,目前%esp所指堆栈内容为0,%ebp所指内容也为0

  • 使用display /i $pc(结合display命令和寄存器/pc内部变量)指令进行设置
    image

依次如下指令调试汇编代码,并查看%esp、%ebp和堆栈内容:

1、使用si指令单步跟踪一条机器指令
2、使用i r指令查看各寄存器的值(在这里要看%eip、%eax、%esp和%ebp)
3、使用x/na %esp对应的值指令查看堆栈变化
之后一直重复执行上述三步,直至结束

有条件跳转的条件看状态寄存器(教材上叫条件码寄存器) 注意leal不改变条件码寄存器。

1、分支(if/switch)

C语言if-else 语句:

if(test-expr)
    then-statement
else
    else-statement

(注:test-expr    整数表达式[假/真])

汇编实现形式:

t = test-expr;
if (!t)
    goto false;
then-statement
goto done;
false: 
    else-statement
done:

2、循环(while, for)

C语言do-while循环:

do
    body-statement
    while(test-expr);

汇编实现形式:

loop:
    body-statement
    t = test-expr;
    if(t)
        goto loop;

while循环、for循环均需转换成do-while形式在转换

gdb调试分析汇总表

指令 %eip %ebp %esp %eax 堆栈
push $0x13 0x80483f9 0xffffd058 0xffffd058 0xf7fbadbc 0x00000000
call 0x80483e6 0x80483fb 0xffffd058 0xffffd054 0xf7fbadbc 0x13 0x0
push %ebp 0x80483e6 0xffffd058 0xffffd050 0xf7fbadbc 0x8048400 0x13 0x0
mov %esp,%ebp 0x80483e7 0xffffd058 0xffffd04c 0xf7fbadbc 0xffffd058 0x8048400 0x13 0x0
pushl 0x8(%ebp) 0x80483e9 0xffffd04c 0xffffd04c 0xf7fbadbc 0xffffd058 0x8048400 0x13 0x0
call 0x80483db 0x80483ec 0xffffd04c 0xffffd048 0xf7fbadbc 0x13 0xffffd058 0x8048400 0x13 0x0
push %ebp 0x80483db 0xffffd04c 0xffffd044 0xf7fbadbc 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0
mov %esp,%ebp 0x80483dc 0xffffd04c 0xffffd040 0xf7fbadbc 0xffffd04c 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0
mov 0x8(%ebp),%eax 0x80483de 0xffffd040 0xffffd040 0xf7fbadbc 0xffffd04c 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0
add $0x13,%eax 0x80483e1 0xffffd040 0xffffd040 0x13 0xffffd04c 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0
pop %ebp 0x80483e4 0xffffd040 0xffffd040 0x26 0xffffd04c 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0
ret 0x80483e5 0xffffd04c 0xffffd044 0x26 0x80483f1 0x13 0xffffd058 0x8048400 0x13 0x0
add $0x4,%esp 0x80483f1 0xffffd04c 0xffffd048 0x26
leave 0x80483f4 0xffffd04c 0xffffd04c 0x26 0xffffd058 0x8048400 0x13 0x0
ret 0x80483f5 0xffffd058 0xffffd050 0x26 0x8048400 0x13 0x0
add $0x4,%esp 0x8048400 0xffffd058 0xffffd054 0x26
add $0x13,%eax 0x8048403 0xffffd058 0xffffd058 0x26
leave 0x8048406 0xffffd058 0xffffd058 0x39
ret 0x8048407 0x0 0xffffd05c 0x39

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

问题:区分MOV,MOVS,MOVZ

解决方案:

1.MOV相当于C语言的赋值”=“

2.MOVS将作了符号扩展的字节传送到字

3.MOVZ将作了零扩展的字节传送到字

代码托管

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

通过本周的学习,C语言代码的汇编和反汇编、C语言代码和汇编代码的转换以及加强阅读汇编代码的能力提高上。

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

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

  • 计划学习时间:XX小时

  • 实际学习时间:XX小时

  • 改进情况:

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

参考资料

原文地址:https://www.cnblogs.com/wang5324/p/7711341.html