反汇编

反汇编

  • 反汇编:把目标代码转为汇编代码的过程。 通常,编写程序是利用高级语言如C,Pascal等高级语言进行编程的,然后再经过编译程序生成可以被计算机系统直接执行的文件。反汇编即是指将这些执行文件反编译还原成汇编语言或其他高级语言。但通常反编译出来的程序与原程序会存在许多不同,虽然执行效果相同.
  • gdb相关操作:
    b linenumber 设置断点
    run 运行
    disassemble 获取汇编代码
    用i(nfo) r(egisters)查看各寄存器的值
    用x查看内存地址中的值
  • 具体步骤:
    设置断点在main函数调用f函数的位置gdb> b main
    gdb> run运行
    gdb> disassemble反汇编
    display /i $pc
    i r
    x查看内存中的内容
    si执行下一条汇编
  • 反汇编:
    使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器:
  • 用gcc在64位机器上编译一个32位的程序,遇到报错,具体如下图:
    32位错误
  • 这是因为编译64位Linux版本32位的二进制文件,需要安装一个库,使用指令
    sudo apt-get install libc6-dev-i386

开始gdb

  • 进入之后先在main函数处设置一个断点,再run一下,使用disassemble指令获取汇编代码,用i(info) r(registers)指令查看各寄存器的值:

获取汇编代码
查看寄存器的值

  • 可见此时主函数的栈基址为0xffffd1e8,用x(examine)指令查看内存地址中的值,但目前%esp所指堆栈内容为0,%ebp所指内容也为0
    x 0ffffd1e8
    以上为入门小练习,接下来让我们直接进入f函数中,查看f函数的每一步汇编代码
    “display /i $pc”
        其中 $pc 代表当前汇编指令,/i 表示以十六进行显示。当需要关心汇编代码时,此命令相当有用。这样在每次执行下一条汇编语句时,都会显示出当前执行的语句。下面展示每一步时%esp、%ebp、%eip、%eax和堆栈内容的变化:

f

ebp esp
eip
eax

汇编代码

  • movl 指令:把值0x1b存在%ebp-0x4中

下一条指令

ebp esp eip eax

栈值2a

  • 将上一个函数的地址入栈,以%ebp+0x8作为基址 待考证

下一条指令

ebp esp eip eax

栈值3a

  • call指令将下一条指令的地址入栈

下一条指令

ebp esp eip eax

栈值4a

  • endbr32

这是Intel 为 CONTROL-FLOW ENFORCEMENT TECHNOLOGY 新加的指令:

The ENDBRANCH (see Section 73 for details) is a new instruction that is used to mark valid jump target addresses of indirect calls and jumps in the program. This instruction opcode is selected to be one that is a NOP on legacy machines such that programs compiled with ENDBRANCH new instruction continue to function on old machines without the CET enforcement. On processors that support CET the ENDBRANCH is still a NOP and is primarily used as a marker instruction by the processor pipeline to detect control flow violations. The CPU implements a state machine that tracks indirect jmp and call instructions. When one of these instructions is seen, the state machine moves from IDLE to WAIT_FOR_ENDBRANCH state. In WAIT_FOR_ENDBRANCH state the next instruction in the program stream must be an ENDBRANCH. If an ENDBRANCH is not seen the processor causes a control protection exception (#CP), else the state machine moves back to IDLE state.

给技术要求相对跳转的目标地址一定是一条 endbr32 或 endbr64 指令,否则就会异常。该指令并不执行任何操作,只是用于验证目标地址是期望的跳转目标。

下一条指令

ebp esp eip eax

栈值5a

下一条指令

ebp esp eip eax

栈值6a

  • 将上一个函数的基址入栈,从当前%esp开始作为新基址

下一条指令

ebp esp eip eax

  • 此处栈底地址改变,下图是新地址与原始地址的对比图:

栈值7a

  • call下一条指令入栈

下一条指令

ebp esp eip eax

栈值8a

  • 将%esp指向的地址中的值赋给%eax寄存器

下一条指令

ebp esp eip eax

栈值9a

  • ret指令将栈顶弹给%eip

下一条指令

ebp esp eip eax

栈值10a

将$0x2e23寄存器中的值与%eax寄存器中的值相加,存在$0x2e23寄存器中

下一条指令

ebp esp eip eax

栈值11a

  • 将%eax寄存器中的值存到0x8+%ebp地址中,也就是堆栈中
    存的值

下一条指令

ebp esp eip eax

栈值12a

  • %eax寄存器的值与$0x3寄存器的值相加后的值存到$0x3寄存器中

下一条指令

ebp esp eip eax

  • pop %ebp指令将栈顶弹到%ebp中,同时%esp增加4字节

下一条指令

ebp esp eip eax

  • ret指令将栈顶弹给%eip

  • leave

在32位汇编下相当于:
mov esp,ebp;//将ebp指向(ebp内部应当保存一个地址,所谓指向即这个地址对应的空间)的值赋给esp
pop ebp

/* leave指令将EBP寄存器的内容复制到ESP寄存器中,
以释放分配给该过程的所有堆栈空间。然后,它从堆栈恢复EBP寄存器的旧值。*/

posted @ 2021-10-28 22:20  氧气2019  阅读(2223)  评论(0编辑  收藏  举报