二进制炸弹 phase(2)

Posted by SGQ on March 23, 2020

一、汇编指令

1.PUSH 和 POP

  • 指令的汇编格式:PUSH SRC ;POP DST
  • 指令的基本功能:PUSH指令在程序中常用来暂存某些数据,而POP指令又可将这些数据恢复。

PUSH 等价于:

subl $4, %esp
movl %ebp (%esp)

POP 等价于:

movl (%esp), %ead

addl $4, %esp

2.CALL,RET和LEAVE

  • CALL指令的步骤:首先是将返回地址(也就是call指令要执行时EIP的值)压入栈顶,然后是将程序跳转到当前调用的方法的起始地址。执行push和jump指令。

  • RET指令则是将栈顶的返回地址弹出到EIP,然后按照EIP此时指示的指令地址继续执行程序。

  • LEAVE指令是将栈指针指向帧指针,然后POP备份的原帧指针到%EBP。

Leave等价于:

movl %ebp %esp

popl %ebp

3.lea指令

  • load effective address, 加载有效地址,可以将有效地址传送到指定的的寄存器。指令形式是从存储器读数据到寄存器, 效果是将存储器的有效地址写入到目的操作数, 简单说, 就是C语言中的”&”.

题目分析:

 08048bb4 <phase_2>:
 8048bb4:	56                   	 
 8048bb5:	53                   	push   %ebx   //将ebx里面的值写入<phase_2>这个帧。
 8048bb6:	83 ec 34             	sub    $0x34,%esp  // 为局部变量划分空间。栈向低地址方向增长,用sub
 8048bb9:	8d 44 24 18          	lea    0x18(%esp),%eax
 8048bbd:	89 44 24 04          	mov    %eax,0x4(%esp)
 8048bc1:	8b 44 24 40          	mov    0x40(%esp),%eax
 8048bc5:	89 04 24             	mov    %eax,(%esp)
 8048bc8:	e8 3f 06 00 00       	call   804920c <read_six_numbers>   //调用读取六个数字这个函数
 8048bcd:	83 7c 24 18 00       	cmpl   $0x0,0x18(%esp)    
 8048bd2:	75 07                	jne    8048bdb <phase_2+0x27>   //jne与cmpl配合判断,第一个数字是否为0,如果是则继续执行,否则将执行下面的explode_bomb函数
 8048bd4:	83 7c 24 1c 01       	cmpl   $0x1,0x1c(%esp)
 8048bd9:	74 1f                	je     8048bfa <phase_2+0x46>    //判断,第二个数字是否为1,是则继续执行,不是执行explode_bomb函数
 8048bdb:	e8 05 06 00 00       	call   80491e5 <explode_bomb>         
 8048be0:	eb 18                	jmp    8048bfa <phase_2+0x46>
 8048be2:	8b 43 f8             	mov    -0x8(%ebx),%eax   //将上上那个数的值赋给eax,可理解为eax=a[i-2]
 8048be5:	03 43 fc             	add    -0x4(%ebx),%eax   //将上个数与上上个数相加,可理解为
 eax=a[i-1]+a[i-2]

 8048be8:	39 03                	cmp    %eax,(%ebx)
 8048bea:	74 05                	je     8048bf1 <phase_2+0x3d>  //判断输入的数是否满足上面,满足跳继续,不满足引爆炸弹。
 8048bec:	e8 f4 05 00 00       	call   80491e5 <explode_bomb>
 8048bf1:	83 c3 04             	add    $0x4,%ebx  // ebx+4 指向新位置
 8048bf4:	39 f3                	cmp    %esi,%ebx  
 8048bf6:	75 ea                	jne    8048be2 <phase_2+0x2e> //判断ebx是否与esi是否相等,不等就继续执行8048be2;
 8048bf8:	eb 0a                	jmp    8048c04 <phase_2+0x50> //相等无条件跳出。
 8048bfa:	8d 5c 24 20          	lea    0x20(%esp),%ebx   //ebx指向新的地址
 8048bfe:	8d 74 24 30          	lea    0x30(%esp),%esi  //esi存的是地址esp+30
 8048c02:	eb de                	jmp    8048be2 <ph ase_2+0x2e>
 8048c04:	83 c4 34             	add    $0x34,%esp
 8048c07:	5b                   	pop    %ebx
 8048c08:	5e                   	pop    %esi
 8048c09:	c3                   	ret    


  • 根据8048bc8: e8 3f 06 00 00 call 804920c <read_six_numbers> 然后查看该函数的代码,发现 804923a: c7 44 24 04 e3 a3 04 movl $0x804a3e3,0x4(%esp),调用gdb调试器查看发现该地址存放的是%d,%d,%d,%d,%d,%d,可知要求是输入六个数字。

  • 前两个数字必须为0和1.
    8048bcd:	83 7c 24 18 00       	cmpl   $0x0,0x18(%esp) 
     8048bd2:	75 07  jne    8048bdb <phase_2+0x27> 
     8048bd4:	83 7c 24 1c 01       	cmpl   $0x1,0x1c(%esp)` 
     8048bd9:	74 1f                	je     8048bfa <phase_2+0x46> 
    
  • 根据最后判断又跳回8048be2,可知8048e2这段代码表示的是一个循环。循环的语句是将前两个输入的值相加作为第三个的值。所以根据0,1可推断之后四个数字依次为1,2,3,5
     8048be2:	8b 43 f8             	mov    -0x8(%ebx),%eax   
     8048be5:	03 43 fc             	add    -0x4(%ebx),%eax 
    

结果验证

enter description here


参考链接

汇编语言里 eax, ebx, ecx, edx, esi, edi, ebp, esp

Push, Pop, call, leave 和 Ret 指令图解

汇编指令push,mov,call,pop,leave,ret建立与释放栈的过程

汇编语言入门教程