二进制炸弹实验 计算机系统基础

一、汇编源码

阶段 1:字符串比较

08048b80 <phase_1>:

 8048b80:      55                          push   %ebp

 8048b81:      89 e5                        mov    %esp,%ebp

 8048b83:      83 ec 08             sub    $0x8,%esp

 8048b86:      c7 44 24 04 18 99 04      movl   $0x8049918,0x4(%esp)

 8048b8d:      08

 8048b8e:       8b 45 08             mov    0x8(%ebp),%eax

 8048b91:      89 04 24             mov    %eax,(%esp)

 8048b94:      e8 c6 04 00 00          call   804905f <strings_not_equal>

 8048b99:      85 c0                        test   %eax,%eax

//判断返回值是否为0,如果为0,那么test将eax=0,否则为1

 8048b9b:      74 05                        je     8048ba2 <phase_1+0x22>

 8048b9d:      e8 84 0a 00 00          call   8049626 <explode_bomb>

 8048ba2:      c9                          leave 

 8048ba3:      c3                          ret   

阶段 2:循环

08048ba4 <phase_2>:

 8048ba4:      55                         push   %ebp

 8048ba5:      89 e5                       mov    %esp,%ebp

 8048ba7:      83 ec 28             sub    $0x28,%esp

 

 8048baa:      8d 45 e4                     lea    -0x1c(%ebp),%eax

 8048bad:      89 44 24 04          mov    %eax,0x4(%esp)

 8048bb1:      8b 45 08                     mov    0x8(%ebp),%eax

 8048bb4:      89 04 24                     mov    %eax,(%esp)

 8048bb7:      e8 10 04 00 00         call   8048fcc <read_six_numbers>

 8048bbc:      c7 45 fc 01 00 00 00      movl   $0x1,-0x4(%ebp)

 

 8048bc3:       eb 1e                       jmp    8048be3 <phase_2+0x3f>

 8048bc5:       8b 45 fc             mov    -0x4(%ebp),%eax

 8048bc8:       8b 54 85 e4          mov    -0x1c(%ebp,%eax,4),%edx

 8048bcc:       8b 45 fc             mov    -0x4(%ebp),%eax

 8048bcf:       48                         dec    %eax

                                     //--

 8048bd0:      8b 44 85 e4          mov    -0x1c(%ebp,%eax,4),%eax

 8048bd4:      83 c0 05             add    $0x5,%eax

                                    //%eax+5

 8048bd7:      39 c2                       cmp    %eax,%edx

 8048bd9:      74 05                       je     8048be0 <phase_2+0x3c>

                                  //%edx-%eax==0时跳转,否则爆炸

 8048bdb:      e8 46 0a 00 00         call   8049626 <explode_bomb>

 8048be0:       ff 45 fc               incl   -0x4(%ebp)

                                        //++

 8048be3:       83 7d fc 05            cmpl   $0x5,-0x4(%ebp)

 8048be7:       7e dc                       jle    8048bc5 <phase_2+0x21>

                                  //-0x4(%ebp) 5跳转

 8048be9:       c9                         leave 

 8048bea:       c3                         ret   

初始化:

push %ebp mov %esp,%ebp 是典型的函数入口点,它们保存了旧的基本指针(base pointer)并设置新的基本指针。

sub $0x28,%esp 减小栈指针,为局部变量预留空间。

读取输入:

使用 lea -0x1c(%ebp),%eax 创建一个指向局部变量数组的指针。

读取一个参数(可能是一个文件描述符或类似的东西)并使用 read_six_numbers 函数从该源读取6个数字。

检查数字:

初始化一个循环计数器(在 -0x4(%ebp) 处)。

使用 jmp 8048be3 跳转到循环的末尾检查部分。

在循环内部,代码从数组中取出两个相邻的数字(当前索引和下一个索引),比较它们(下一个数字是否比当前数字大5)。

如果条件不满足(即 je 8048be0 je 分支不执行),则调用 explode_bomb 函数,这很可能是一个错误处理函数,用于在检测到错误时“爆炸”或终止程序。

如果条件满足,则递增循环计数器并继续下一个迭代。

循环结束检查:

使用 cmpl $0x5,-0x4(%ebp) 检查是否已检查了5个数字对(即,是否检查了6个数字中的每一对相邻数字)。

如果已经检查完5对数字,则退出循环。

退出函数:

使用 leave ret 指令退出函数。

简而言之,此函数读取6个数字,并检查每对相邻的数字是否满足“下一个数字比当前数字大5”的条件。如果任何一对数字不满足此条件,则程序会调用 explode_bomb 函数。如果所有对都满足条件,则函数正常返回。

阶段 3:条件/分支

08048beb <phase_3>:

 8048beb:      55                         push   %ebp

 8048bec:       89 e5                       mov    %esp,%ebp

 8048bee:       83 ec 28             sub    $0x28,%esp

 8048bf1:       c7 45 f8 00 00 00 00      movl   $0x0,-0x8(%ebp)

 8048bf8:       c7 45 fc 00 00 00 00      movl   $0x0,-0x4(%ebp)

 8048bff:        8d 45 f0             lea    -0x10(%ebp),%eax

 8048c02:       89 44 24 0c          mov    %eax,0xc(%esp)

 8048c06:       8d 45 f4             lea    -0xc(%ebp),%eax

 8048c09:       89 44 24 08          mov    %eax,0x8(%esp)

 8048c0d:       c7 44 24 04 47 99 04     movl   $0x8049947,0x4(%esp)

 

 8048c14:       08

 8048c15:       8b 45 08                     mov    0x8(%ebp),%eax

 8048c18:       89 04 24                     mov    %eax,(%esp)

 8048c1b:       e8 48 fc ff ff             call   8048868 <sscanf@plt>

 8048c20:       89 45 fc             mov    %eax,-0x4(%ebp)

 

 8048c23:       83 7d fc 01            cmpl   $0x1,-0x4(%ebp)

 8048c27:       7f 05                        jg     8048c2e <phase_3+0x43>

                                   //-0x4(%ebp)大于1个跳转,否则爆炸

 8048c29:       e8 f8 09 00 00          call   8049626 <explode_bomb>

 8048c2e:       8b 45 f4             mov    -0xc(%ebp),%eax

 8048c31:       89 45 ec             mov    %eax,-0x14(%ebp)

 8048c34:       83 7d ec 07          cmpl   $0x7,-0x14(%ebp)

 8048c38:       77 54                       ja     8048c8e <phase_3+0xa3>

                                     //-0x14(%ebp)大于7爆炸

 8048c3a:       8b 55 ec             mov    -0x14(%ebp),%edx

 8048c3d:       8b 04 95 50 99 04 08     mov    0x8049950(,%edx,4),%eax

 8048c44:       ff e0                jmp    *%eax

 8048c46:       c7 45 f8 c7 03 00 00      movl   $0x3c7,-0x8(%ebp)

 8048c4d:       eb 44                       jmp    8048c93 <phase_3+0xa8>

 8048c4f:        c7 45 f8 93 00 00 00      movl   $0x93,-0x8(%ebp)

 8048c56:       eb 3b                       jmp    8048c93 <phase_3+0xa8>

 8048c58:       c7 45 f8 96 02 00 00      movl   $0x296,-0x8(%ebp)

 8048c5f:        eb 32                       jmp    8048c93 <phase_3+0xa8>

 8048c61:       c7 45 f8 25 02 00 00      movl   $0x225,-0x8(%ebp)

 8048c68:       eb 29                       jmp    8048c93 <phase_3+0xa8>

 8048c6a:       c7 45 f8 a6 03 00 00      movl   $0x3a6,-0x8(%ebp)

 8048c71:       eb 20                       jmp    8048c93 <phase_3+0xa8>

 8048c73:       c7 45 f8 7a 01 00 00      movl   $0x17a,-0x8(%ebp)

 8048c7a:       eb 17                       jmp    8048c93 <phase_3+0xa8>

 8048c7c:       c7 45 f8 e5 01 00 00      movl   $0x1e5,-0x8(%ebp)

 8048c83:       eb 0e                       jmp    8048c93 <phase_3+0xa8>

 8048c85:       c7 45 f8 6b 01 00 00      movl   $0x16b,-0x8(%ebp)

 8048c8c:       eb 05                       jmp    8048c93 <phase_3+0xa8>

 8048c8e:       e8 93 09 00 00         call   8049626 <explode_bomb>

 8048c93:       8b 45 f0             mov    -0x10(%ebp),%eax

 8048c96:       39 45 f8             cmp    %eax,-0x8(%ebp)

 8048c99:       74 05                       je     8048ca0 <phase_3+0xb5>

 

 8048c9b:       e8 86 09 00 00         call   8049626 <explode_bomb>

 8048ca0:       c9                         leave 

 8048ca1:       c3                         ret   

检查输入值:

如果 sscanf 没有成功读取一个输入值(返回值不为1),则调用 explode_bomb

输入值范围检查:

检查读取到的值(位于 -0x14(%ebp))是否在07之间。

如果不是,则调用 explode_bomb

基于输入值的间接跳转:

根据输入值,通过间接跳转(jmp *%eax)设置局部变量 -0x8(%ebp) 的值。

检查设置的值与另一个局部变量的关系:

-0x10(%ebp) 的值与 -0x8(%ebp) 的值进行比较。

如果它们相等,则函数正常返回。

如果不相等,则调用 explode_bomb

阶段 4:递归调用和栈

08048ca2 <func4>:

 8048ca2:       55                         push   %ebp

 8048ca3:       89 e5                       mov    %esp,%ebp

 8048ca5:       83 ec 08             sub    $0x8,%esp

 8048ca8:       83 7d 08 01          cmpl   $0x1,0x8(%ebp)

 8048cac:       7f 09                        jg     8048cb7 <func4+0x15>

 8048cae:       c7 45 fc 01 00 00 00      movl   $0x1,-0x4(%ebp)

 8048cb5:       eb 15                       jmp    8048ccc <func4+0x2a>

 8048cb7:       8b 45 08                     mov    0x8(%ebp),%eax

 8048cba:       48                         dec    %eax

 8048cbb:      89 04 24                     mov    %eax,(%esp)

 8048cbe:       e8 df ff ff ff              call   8048ca2 <func4>

 8048cc3:       89 c2                       mov    %eax,%edx

 8048cc5:       0f af 55 08            imul   0x8(%ebp),%edx

 8048cc9:       89 55 fc             mov    %edx,-0x4(%ebp)

 8048ccc:        8b 45 fc             mov    -0x4(%ebp),%eax

 8048ccf:        c9                         leave 

 8048cd0:       c3                         ret   

 

08048cd1 <phase_4>:

 8048cd1:       55                         push   %ebp

 8048cd2:       89 e5                       mov    %esp,%ebp

 8048cd4:       83 ec 28             sub    $0x28,%esp

 8048cd7:       8d 45 f4             lea    -0xc(%ebp),%eax

 8048cda:       89 44 24 08          mov    %eax,0x8(%esp)

 8048cde:       c7 44 24 04 70 99 04     movl   $0x8049970,0x4(%esp)

 8048ce5:       08

 8048ce6:       8b 45 08                     mov    0x8(%ebp),%eax

 8048ce9:       89 04 24                     mov    %eax,(%esp)

 8048cec:        e8 77 fb ff ff            call   8048868 <sscanf@plt>

 8048cf1:        89 45 fc             mov    %eax,-0x4(%ebp)

 8048cf4:        83 7d fc 01            cmpl   $0x1,-0x4(%ebp)

 8048cf8:        75 07                       jne    8048d01 <phase_4+0x30>

 

 8048cfa:        8b 45 f4             mov    -0xc(%ebp),%eax

 8048cfd:       85 c0                       test   %eax,%eax

 8048cff: 7f 05                        jg     8048d06 <phase_4+0x35>

                                    // %eax大于0跳转,否则爆炸

 8048d01:      e8 20 09 00 00         call   8049626 <explode_bomb>

 8048d06:      8b 45 f4             mov    -0xc(%ebp),%eax

 8048d09:      89 04 24                     mov    %eax,(%esp)

 8048d0c:       e8 91 ff ff ff             call   8048ca2 <func4>

 8048d11:       89 45 f8             mov    %eax,-0x8(%ebp)

 8048d14:      81 7d f8 00 5f 37 00      cmpl   $0x375f00,-0x8(%ebp)

 8048d1b:      74 05                       je     8048d22 <phase_4+0x51>

 8048d1d:      e8 04 09 00 00         call   8049626 <explode_bomb>

 8048d22:      c9                         leave 

 8048d23:      c3                         ret   

func4 函数

参数检查:

检查传入的参数(位于 0x8(%ebp))是否大于1

递归基:

如果参数小于或等于1,则将局部变量 -0x4(%ebp) 设置为1,并跳转到函数末尾返回。

递归步骤:

如果参数大于1,则执行以下操作:

参数减1,并递归调用 func4

将递归调用的返回值与原始参数相乘,并将结果存储在 -0x4(%ebp)。即求阶乘。

返回结果:

返回局部变量 -0x4(%ebp) 的值。

 

读取输入:

lea -0xc(%ebp),%eax 获取栈上分配的一个地址(-0xc(%ebp)),这个地址可能用于存储输入的字符串。

接着,使用sscanf函数(通过call 8048868 <sscanf@plt>)从标准输入读取一个整数,并存储在-0xc(%ebp)指向的地址中。

检查输入:

movl $0x8049970,0x4(%esp) 可能是将某个字符串(可能是输入格式字符串)的地址推送到栈上。

cmpl $0x1,-0x4(%ebp) 检查sscanf的返回值(存储在-0x4(%ebp)中)是否为1,确保正确读取了一个整数。

如果不是,调用explode_bomb函数。

检查整数值:

mov -0xc(%ebp),%eax 获取用户输入的整数值。

test %eax,%eax 检查该值是否为0(如果是0,则jg不会跳转)。

如果输入的值不大于0(无符号比较),则调用explode_bomb函数。

调用func4函数:

调用func4函数,并将用户输入的整数值作为参数传递。

func4的返回值存储在-0x8(%ebp)中。

检查结果:

cmpl $0x375f00,-0x8(%ebp) 检查func4的返回值是否等于0x375f00

如果不等于,调用explode_bomb函数。

函数结束:

leave ret 指令用于恢复栈并返回。

总结:

phase_4函数要求用户输入一个整数。这个整数首先被检查是否成功读取(sscanf的返回值是否为1),然后检查其是否大于0。接着,这个整数被传递给func4函数,并且func4的返回值必须等于0x375f00,否则程序会调用explode_bomb函数。

阶段 5:指针

08048d24 <phase_5>:

 8048d24:      55                         push   %ebp

 8048d25:      89 e5                       mov    %esp,%ebp

 8048d27:      83 ec 18             sub    $0x18,%esp

 8048d2a:      8b 45 08                     mov    0x8(%ebp),%eax

 8048d2d:      89 04 24                     mov    %eax,(%esp)

 8048d30:      e8 00 03 00 00         call   8049035 <string_length>

 8048d35:      89 45 fc             mov    %eax,-0x4(%ebp)

 8048d38:      83 7d fc 06            cmpl   $0x6,-0x4(%ebp)

 8048d3c:       74 05                       je     8048d43 <phase_5+0x1f>

 

 8048d3e:       e8 e3 08 00 00         call   8049626 <explode_bomb>

 8048d43:      c7 45 f8 00 00 00 00      movl   $0x0,-0x8(%ebp)

 8048d4a:      c7 45 f4 00 00 00 00      movl   $0x0,-0xc(%ebp)

 8048d51:      eb 1c                       jmp    8048d6f <phase_5+0x4b>

 8048d53:      8b 45 f4             mov    -0xc(%ebp),%eax

 8048d56:      03 45 08                     add    0x8(%ebp),%eax

 8048d59:      0f b6 00             movzbl (%eax),%eax

 8048d5c:       0f be c0             movsbl %al,%eax

 8048d5f:       83 e0 0f             and    $0xf,%eax

 8048d62:      8b 04 85 c0 a5 04 08     mov    0x804a5c0(,%eax,4),%eax

 8048d69:      01 45 f8             add    %eax,-0x8(%ebp)

 8048d6c:       ff 45 f4               incl   -0xc(%ebp)

 8048d6f:       83 7d f4 05          cmpl   $0x5,-0xc(%ebp)

 8048d73:      7e de                       jle    8048d53 <phase_5+0x2f>

 8048d75:      83 7d f8 2c            cmpl   $0x2c,-0x8(%ebp)

 8048d79:      74 05                       je     8048d80 <phase_5+0x5c>

 

 8048d7b:      e8 a6 08 00 00         call   8049626 <explode_bomb>

 8048d80:      c9                         leave 

 8048d81:      c3                         ret   

读取输入字符串的长度:

函数首先通过string_length函数(通过call 8049035 <string_length>)获取输入字符串(存储在%ebp+8中)的长度,并将结果存储在%ebp-4中。

检查字符串长度:

使用cmpl $0x6,-0x4(%ebp)检查字符串长度是否为6(即6个字符)。

如果不是,调用explode_bomb函数导致程序崩溃。

初始化循环变量:

8048d438048d51的代码中,两个局部变量(%ebp-8%ebp-12)被初始化为0

处理字符串:

接下来的代码块(从8048d53开始)是一个循环,它遍历输入字符串的每个字符(由于之前检查了长度为6,所以循环会执行6次)。

在每次迭代中,它做以下操作:

使用movzbl (%eax),%eaxmovsbl %al,%eax从字符串中读取一个字节,并将其符号扩展到32位。

使用and $0xf,%eax将字节值限制在015之间(即取低4位)。

使用mov 0x804a5c0(,%eax,4),%eax从数组0x804a5c0中索引一个值(基于当前字符的低4位)。这个数组可能包含某种映射或转换。

将从数组中检索到的值累加到%ebp-8指向的变量中。

增加%ebp-12的值以跟踪循环的进度。

检查最终累积值:

在循环结束后,使用cmpl $0x2c,-0x8(%ebp)检查累积值(存储在%ebp-8中)是否为0x2c(即44的十六进制)。

如果不是,调用explode_bomb函数。

函数返回:

如果所有检查都通过,函数使用leaveret指令返回。

总结:

phase_5函数要求用户输入一个长度为6的字符串。这个字符串的每个字符的低4位被用来从一个数组(位于0x804a5c0)中索引一个值,并将这些值累加起来。如果最终累积值等于0x2c44),则函数成功返回;否则,程序会调用explode_bomb函数并崩溃。

阶段 6:链表/指针/结构

08048d82 <fun6>:

 8048d82:      55                         push   %ebp

 8048d83:      89 e5                       mov    %esp,%ebp

 8048d85:      83 ec 10             sub    $0x10,%esp

 8048d88:      8b 45 08                     mov    0x8(%ebp),%eax

 8048d8b:      89 45 f0             mov    %eax,-0x10(%ebp)

 8048d8e:       8b 45 08                     mov    0x8(%ebp),%eax

 8048d91:      89 45 f0             mov    %eax,-0x10(%ebp)

 8048d94:      8b 45 08                     mov    0x8(%ebp),%eax

 8048d97:      8b 40 08                     mov    0x8(%eax),%eax

 8048d9a:      89 45 f4             mov    %eax,-0xc(%ebp)

 8048d9d:      8b 45 f0             mov    -0x10(%ebp),%eax

 8048da0:      c7 40 08 00 00 00 00     movl   $0x0,0x8(%eax)

 8048da7:      eb 62                       jmp    8048e0b <fun6+0x89>

 8048da9:      8b 45 f0             mov    -0x10(%ebp),%eax

 8048dac:       89 45 fc             mov    %eax,-0x4(%ebp)

 8048daf:       8b 45 f0             mov    -0x10(%ebp),%eax

 8048db2:      89 45 f8             mov    %eax,-0x8(%ebp)

 8048db5:      eb 0f                        jmp    8048dc6 <fun6+0x44>

 

 8048db7:      8b 45 fc             mov    -0x4(%ebp),%eax

 8048dba:      89 45 f8             mov    %eax,-0x8(%ebp)

 8048dbd:      8b 45 fc             mov    -0x4(%ebp),%eax

 8048dc0:       8b 40 08                     mov    0x8(%eax),%eax

 8048dc3:       89 45 fc             mov    %eax,-0x4(%ebp)

 8048dc6:       83 7d fc 00            cmpl   $0x0,-0x4(%ebp)

 8048dca:       74 0e                       je     8048dda <fun6+0x58>

 

 8048dcc:       8b 45 fc             mov    -0x4(%ebp),%eax

 8048dcf:       8b 10                       mov    (%eax),%edx

 8048dd1:      8b 45 f4             mov    -0xc(%ebp),%eax

 8048dd4:      8b 00                       mov    (%eax),%eax

 8048dd6:      39 c2                       cmp    %eax,%edx

 8048dd8:      7f dd                       jg     8048db7 <fun6+0x35>

 

 8048dda:      8b 45 f8             mov    -0x8(%ebp),%eax

 8048ddd:      3b 45 fc             cmp    -0x4(%ebp),%eax

 8048de0:       74 0b                       je     8048ded <fun6+0x6b>

 

 8048de2:       8b 55 f8             mov    -0x8(%ebp),%edx

 8048de5:       8b 45 f4             mov    -0xc(%ebp),%eax

 8048de8:       89 42 08                     mov    %eax,0x8(%edx)

 8048deb:      eb 06                       jmp    8048df3 <fun6+0x71>

 

 8048ded:      8b 45 f4             mov    -0xc(%ebp),%eax

 8048df0:       89 45 f0             mov    %eax,-0x10(%ebp)

 8048df3:       8b 45 f4             mov    -0xc(%ebp),%eax

 8048df6:       8b 40 08                     mov    0x8(%eax),%eax

 8048df9:       89 45 f8             mov    %eax,-0x8(%ebp)

 8048dfc:       8b 55 f4             mov    -0xc(%ebp),%edx

 8048dff:        8b 45 fc             mov    -0x4(%ebp),%eax

 8048e02:       89 42 08                     mov    %eax,0x8(%edx)

 8048e05:       8b 45 f8             mov    -0x8(%ebp),%eax

 8048e08:       89 45 f4             mov    %eax,-0xc(%ebp)

 8048e0b:       83 7d f4 00          cmpl   $0x0,-0xc(%ebp)

 8048e0f:        75 98                       jne    8048da9 <fun6+0x27>

 8048e11:       8b 45 f0             mov    -0x10(%ebp),%eax

 8048e14:       c9                         leave 

 8048e15:       c3                         ret   

 

08048e16 <phase_6>:

 8048e16:       55                         push   %ebp

 8048e17:       89 e5                       mov    %esp,%ebp

 8048e19:       83 ec 18             sub    $0x18,%esp

 8048e1c:       c7 45 f8 6c a6 04 08      movl   $0x804a66c,-0x8(%ebp)

 8048e23:       8b 45 08                     mov    0x8(%ebp),%eax

 8048e26:       89 04 24                     mov    %eax,(%esp)

 8048e29:       e8 2a fa ff ff             call   8048858 <atoi@plt>

 8048e2e:       89 c2                       mov    %eax,%edx

 8048e30:       8b 45 f8             mov    -0x8(%ebp),%eax

 8048e33:       89 10                       mov    %edx,(%eax)

 8048e35:       8b 45 f8             mov    -0x8(%ebp),%eax

 8048e38:       89 04 24                     mov    %eax,(%esp)

 8048e3b:       e8 42 ff ff ff             call   8048d82 <fun6>

 8048e40:       89 45 f8             mov    %eax,-0x8(%ebp)

 8048e43:       8b 45 f8             mov    -0x8(%ebp),%eax

 8048e46:       89 45 fc             mov    %eax,-0x4(%ebp)

 8048e49:       c7 45 f4 01 00 00 00      movl   $0x1,-0xc(%ebp)

 8048e50:       eb 0c                       jmp    8048e5e <phase_6+0x48>

 8048e52:       8b 45 fc             mov    -0x4(%ebp),%eax

 8048e55:       8b 40 08                     mov    0x8(%eax),%eax

 8048e58:       89 45 fc             mov    %eax,-0x4(%ebp)

 8048e5b:       ff 45 f4               incl   -0xc(%ebp)

 8048e5e:       83 7d f4 05          cmpl   $0x5,-0xc(%ebp)

 8048e62:       7e ee                        jle    8048e52 <phase_6+0x3c>

 8048e64:       8b 45 fc             mov    -0x4(%ebp),%eax

 8048e67:       8b 10                       mov    (%eax),%edx

 8048e69:       a1 6c a6 04 08         mov    0x804a66c,%eax

 8048e6e:       39 c2                       cmp    %eax,%edx

 8048e70:       74 05                       je     8048e77 <phase_6+0x61>

 

 8048e72:       e8 af 07 00 00          call   8049626 <explode_bomb>

 8048e77:       c9                         leave 

 8048e78:       c3                         ret   

初始化变量:

movl $0x804a66c, -0x8(%ebp) 将一个地址(可能是一个全局数组或链表的头)存储在局部变量中。

从用户输入读取一个整数:

mov 0x8(%ebp), %eax 获取传递给函数的参数(可能是用户输入)。

call 8048858 <atoi@plt> 调用 atoi 函数将字符串参数转换为整数。

将返回的整数存储在局部变量中,并用于修改全局数组或链表的某个元素。

调用 fun6 函数:

使用之前初始化的全局数组或链表的地址作为参数调用 fun6 函数。

fun6 函数的返回值被存储在局部变量中。

遍历链表或数组:

使用一个循环(jmp cmpl 指令)来遍历链表或数组的某个部分。

在循环内部,从当前元素加载一个值(mov 0x8(%eax), %eax),并将其存储在局部变量中。

递增一个计数器(incl -0xc(%ebp))。

检查链表或数组的结束条件:

当计数器达到 5 时,循环结束。

检查链表或数组的最后一个元素:

加载链表或数组的最后一个元素,并将其与全局数组或链表的头进行比较。

如果它们相等,则函数正常返回。

如果它们不相等,则调用 explode_bomb 函数。

总结:

phase_6 函数首先读取一个用户输入的整数,并使用它来修改全局数组或链表的某个元素。

然后,它调用 fun6 函数对链表或数组进行操作。

接着,它遍历链表或数组的前五个元素。

最后,它检查链表或数组的最后一个元素是否与初始值相同,如果不同,则调用 explode_bomb 函数。

为了成功通过此阶段,用户输入的整数必须导致 fun6 函数修改全局数组或链表的正确元素,使得最后一个元素保持不变。

隐藏阶段:

08048e79 <fun7>:

 8048e79:       55                          push   %ebp

 8048e7a:       89 e5                        mov    %esp,%ebp

 8048e7c:       83 ec 0c             sub    $0xc,%esp

 8048e7f:        83 7d 08 00          cmpl   $0x0,0x8(%ebp)

 8048e83:       75 09                        jne    8048e8e <fun7+0x15>

 

 8048e85:       c7 45 fc ff ff ff ff    movl   $0xffffffff,-0x4(%ebp)

 8048e8c:       eb 54                        jmp    8048ee2 <fun7+0x69>

 8048e8e:       8b 45 08             mov    0x8(%ebp),%eax

 8048e91:       8b 00                       mov    (%eax),%eax

 8048e93:       3b 45 0c             cmp    0xc(%ebp),%eax

 8048e96:       7e 1c                jle    8048eb4 <fun7+0x3b>

 8048e98:       8b 45 08             mov    0x8(%ebp),%eax

 8048e9b:       8b 50 04             mov    0x4(%eax),%edx

 8048e9e:       8b 45 0c             mov    0xc(%ebp),%eax

 8048ea1:       89 44 24 04            mov    %eax,0x4(%esp)

 8048ea5:       89 14 24             mov    %edx,(%esp)

 8048ea8:       e8 cc ff ff ff              call   8048e79 <fun7>

 8048ead:       01 c0                        add    %eax,%eax

 8048eaf:        89 45 fc               mov    %eax,-0x4(%ebp)

 8048eb2:       eb 2e                        jmp    8048ee2 <fun7+0x69>

 8048eb4:       8b 45 08             mov    0x8(%ebp),%eax

 8048eb7:       8b 00                       mov    (%eax),%eax

 8048eb9:       3b 45 0c             cmp    0xc(%ebp),%eax

 8048ebc:       75 09                        jne    8048ec7 <fun7+0x4e>

 8048ebe:       c7 45 fc 00 00 00 00      movl   $0x0,-0x4(%ebp)

 8048ec5:       eb 1b                       jmp    8048ee2 <fun7+0x69>

 8048ec7:       8b 45 08             mov    0x8(%ebp),%eax

 8048eca:       8b 50 08             mov    0x8(%eax),%edx

 8048ecd:       8b 45 0c             mov    0xc(%ebp),%eax

 8048ed0:       89 44 24 04            mov    %eax,0x4(%esp)

 8048ed4:       89 14 24             mov    %edx,(%esp)

 8048ed7:       e8 9d ff ff ff             call   8048e79 <fun7>

 8048edc:       01 c0                        add    %eax,%eax

 8048ede:       40                          inc    %eax

 8048edf:       89 45 fc               mov    %eax,-0x4(%ebp)

 8048ee2:       8b 45 fc             mov    -0x4(%ebp),%eax

 8048ee5:       c9                          leave 

 8048ee6:       c3                          ret   

 

08048ee7 <secret_phase>:

 8048ee7:       55                          push   %ebp

 8048ee8:       89 e5                        mov    %esp,%ebp

 8048eea:       83 ec 18             sub    $0x18,%esp

 8048eed:       e8 a8 03 00 00          call   804929a <read_line>

 8048ef2:        89 45 f4             mov    %eax,-0xc(%ebp)

 8048ef5:        8b 45 f4             mov    -0xc(%ebp),%eax

 8048ef8:        89 04 24             mov    %eax,(%esp)

 8048efb:       e8 58 f9 ff ff             call   8048858 <atoi@plt>

 8048f00:       89 45 f8             mov    %eax,-0x8(%ebp)

 8048f03:       83 7d f8 00            cmpl   $0x0,-0x8(%ebp)

 8048f07:       7e 09                        jle    8048f12 <secret_phase+0x2b>

 

 8048f09:       81 7d f8 e9 03 00 00      cmpl   $0x3e9,-0x8(%ebp)

 8048f10:       7e 05                        jle    8048f17 <secret_phase+0x30>

 

 8048f12:       e8 0f 07 00 00          call   8049626 <explode_bomb>

 8048f17:       8b 45 f8             mov    -0x8(%ebp),%eax

 8048f1a:       89 44 24 04            mov    %eax,0x4(%esp)

 8048f1e:        c7 04 24 20 a7 04 08      movl   $0x804a720,(%esp)

 8048f25:       e8 4f ff ff ff              call   8048e79 <fun7>

 8048f2a:       89 45 fc               mov    %eax,-0x4(%ebp)

 8048f2d:       83 7d fc 05            cmpl   $0x5,-0x4(%ebp)

 8048f31:       74 05                        je     8048f38 <secret_phase+0x51>

 

 8048f33:       e8 ee 06 00 00          call   8049626 <explode_bomb>

 8048f38:       c7 04 24 74 99 04 08      movl   $0x8049974,(%esp)

 8048f3f: e8 84 f8 ff ff             call   80487c8 <puts@plt>

 8048f44:       e8 07 07 00 00          call   8049650 <phase_defused>

 8048f49:       c9                          leave 

 8048f4a:       c3                          ret   

 8048f4b:       90                          nop

 

08049650 <phase_defused>:

 8049650:       55                          push   %ebp

 8049651:       89 e5                        mov    %esp,%ebp

 8049653:       83 ec 78             sub    $0x78,%esp

 8049656:       a1 8c a8 04 08          mov    0x804a88c,%eax

 804965b:      83 f8 06             cmp    $0x6,%eax

 804965e:       75 6e                        jne    80496ce <phase_defused+0x7e>

 8049660:       b8 90 a9 04 08         mov    $0x804a990,%eax

 8049665:       89 c2                        mov    %eax,%edx

 8049667:       8d 45 ac             lea    -0x54(%ebp),%eax

 804966a:       89 44 24 0c            mov    %eax,0xc(%esp)

 804966e:       8d 45 a8             lea    -0x58(%ebp),%eax

 8049671:       89 44 24 08            mov    %eax,0x8(%esp)

 8049675:       c7 44 24 04 10 9e 04      movl   $0x8049e10,0x4(%esp)

 804967c:       08

 804967d:      89 14 24             mov    %edx,(%esp)

 8049680:       e8 e3 f1 ff ff             call   8048868 <sscanf@plt>

 8049685:       89 45 fc               mov    %eax,-0x4(%ebp)

 8049688:       83 7d fc 02            cmpl   $0x2,-0x4(%ebp)

 804968c:       75 34                        jne    80496c2 <phase_defused+0x72>

 804968e:       c7 44 24 04 16 9e 04      movl   $0x8049e16,0x4(%esp)

 8049695:       08

 8049696:       8d 45 ac             lea    -0x54(%ebp),%eax

 8049699:       89 04 24             mov    %eax,(%esp)

 804969c:       e8 be f9 ff ff             call   804905f <strings_not_equal>

 80496a1:       85 c0                        test   %eax,%eax

 80496a3:       75 1d                       jne    80496c2 <phase_defused+0x72>

 80496a5:       c7 04 24 24 9e 04 08      movl   $0x8049e24,(%esp)

 80496ac:       e8 17 f1 ff ff             call   80487c8 <puts@plt>

 80496b1:      c7 04 24 4c 9e 04 08      movl   $0x8049e4c,(%esp)

 80496b8:      e8 0b f1 ff ff             call   80487c8 <puts@plt>

 80496bd:      e8 25 f8 ff ff             call   8048ee7 <secret_phase>

 80496c2:       c7 04 24 84 9e 04 08      movl   $0x8049e84,(%esp)

 80496c9:       e8 fa f0 ff ff              call   80487c8 <puts@plt>

 80496ce:       c9                          leave 

 80496cf:        c3                          ret   

fun7函数接收两个参数,一个在%ebp+8(函数参数通常从右到左压栈,所以这是第一个参数),另一个在%ebp+0xC(第二个参数)。

函数开始:

push %ebp mov %esp, %ebp 是常见的函数开始时的栈帧设置。

sub $0xC, %esp 为局部变量在栈上分配了12字节的空间(三个32位整数)。

检查第一个参数:

cmpl $0x0, 0x8(%ebp) 检查第一个参数是否为0

如果为0,则跳转到错误处理部分,将局部变量(位于%ebp-4)设置为-1(表示错误)并跳转到函数末尾。

主逻辑:

函数接下来检查第一个参数(可能是链表或某种数据结构的指针)所指向的值(mov (%eax),%eax)。

这个值与第二个参数进行比较(cmp 0xc(%ebp),%eax)。

如果第一个参数所指向的值小于或等于第二个参数,执行一个分支(标签为<fun7+0x3b>)。

否则,执行另一个分支,它首先读取第一个参数所指向的数据结构的下一个字段(偏移为4的字段,可能是链表节点的下一个节点),并递归调用fun7函数自身。

递归调用:

在递归调用中,传递了当前节点的下一个字段(edx)和第二个参数(eax)作为参数。

递归调用的返回值乘以2add %eax,%eax),并存储在局部变量中(mov %eax,-0x4(%ebp))。

小于或等于的分支:

如果第一个参数所指向的值小于或等于第二个参数,函数检查它们是否相等。

如果相等,将局部变量设置为0(成功的情况)。

如果不相等且之前也没有递归调用(即,这是第一个节点),则跳转到函数末尾。

另一个递归调用:

如果第一个参数所指向的值大于第二个参数,但又不满足上述条件,函数会读取数据结构的另一个字段(偏移为8的字段,可能是链表节点的另一个属性或子节点),并递归调用fun7

递归调用的返回值乘以2并加1inc %eax),然后存储在局部变量中。

函数结束:

函数最后返回局部变量(位于%ebp-4)的值作为结果。

 

读取输入:

调用read_line函数读取一行输入(call 804929a <read_line>)。

read_line的返回值(可能是一个指向输入字符串的指针)存储在局部变量中(mov %eax,-0xc(%ebp))。

将输入转换为整数:

将这个指针作为参数传递给atoi函数(call 8048858 <atoi@plt>),将字符串转换为整数。

atoi的返回值(整数)存储在另一个局部变量中(mov %eax,-0x8(%ebp))。

检查输入值:

检查这个整数是否为0或负数(cmpl $0x0,-0x8(%ebp) jle 8048f12 <secret_phase+0x2b>)。

如果不是,进一步检查它是否小于或等于0x3e9cmpl $0x3e9,-0x8(%ebp) jle 8048f17 <secret_phase+0x30>)。

如果不满足上述任一条件(即输入值不在00x3e9之间),则调用explode_bomb函数,可能是使程序崩溃或触发某种错误处理机制(call 8049626 <explode_bomb>)。

调用fun7:

如果输入值满足条件,将其作为参数传递给fun7函数(mov -0x8(%ebp),%eax call 8048e79 <fun7>)。

fun7的返回值存储在另一个局部变量中(mov %eax,-0x4(%ebp))。

检查fun7的返回值:

检查fun7的返回值是否为5cmpl $0x5,-0x4(%ebp) je 8048f38 <secret_phase+0x51>)。

如果不是,再次调用explode_bomb函数。

解密成功处理:

如果fun7的返回值是5,则打印一条消息(可能是“解密成功”之类的信息,调用puts函数,地址是0x8049974)。

接着调用phase_defused函数,可能是标记当前阶段已成功解除或进行后续处理(call 8049650 <phase_defused>)。

函数结束:

使用leave指令恢复栈帧(leave)。

返回(ret)。

二、实验过程

阶段 1:字符串比较

1216be39fd4f4a40bfcde3460d496436.png

eebc6e33443449b69dfb72474f89a97c.png

fbad5a1b76ac4b14922d11533511b6c4.png

141a683a0ebe474d8095ca78bdbba63d.png

阶段 2:循环

f65b160a2c6440d984cee4be2e72941e.png

2aa569f861d345e085da6b76f1f1122e.png

随便输入六个数

c8595d6d27184f309793a30a4e5bcb00.png

第二个数应该是-1,即比-65

172e9fa29d2b4177b81a4582f6a7e52d.png

重复,这次需要循环到第二个0x08048bd7

5ef1bd9953f44d14beafc159d171c056.png

第三个数应该是……

a1d181702e26403ebd6b3fcaccb9c9cd.png

阶段 3:条件/分支

ad9d55d05279422aaafae531933fe1fc.png

应该输入两个整数

b77e1328620445f1a554054ee426fd85.png

0 9671 1472 662 …… 7 363

阶段 4:递归调用和栈

9cc7f57a4a48488ea5d3fcc8f6c7bbdd.png

应该输入一个整数

6d77115a69ba40029d7d21b5d89d9be9.png

10= 0x375f00

阶段 5:指针

d4ad1f1ec6a54bad90fc293c1e42d647.png

2                10             6          1

12              16                9              3

0000         0001      0010         0011        0101             0110

80             81           82           83             85                 86         PQRSUV

96             97          98            99            101              102         bcdegh

51e71c6d1f1b427ebf640242ce7f84a7.png

阶段 6:链表/指针/结构

9a497695de8a405ea7f0a746e2007a3d.png

循环5次到0x08048e6e

9402f0d6e65e4f3399ea2a31d6d437b2.png

1f78b18f35cc47098b97ef0141088486.png

344345好像都行?

dab87426804246d3b288379f359a565a.png

7b0bfcbff0ca4b1fb071ec1baaf369b4.png

隐藏阶段:

3798063c99734beba7a1b290b14a9099.png

即在阶段4要输入一个整数一个字符串 austinpowers

e20fa16c6c854f16aa647589718d0982.png

int fun7(const int *a, int b)

{

        if (a == NULL)

                return -1;

        int ret = 0;

        if (*a - b > 0)

        {

                ret = fun7(*(a + 4), b);

                ret *= 2

        }

        else if (*a - b == 0)

                return 0;

        else

        {

                ret = fun7(*(a + 8), b);

                ret = ret * 2 + 1;

        }

        return ret;

}

由于最后的返回值是5,根据函数数的结构可以想到这样的结构:

  c9c350755a2646a2835cdf32872d24ba.png

用穷举的方法试了下,似乎也只有这样一个唯一的结构可以得出5

根据以上的结构以及C代码,就可以知道要做些什么了。

74b0264dc4f1494183b975086e901fc7.png

1*0x804a720=0x24,之后在*a-b<0 (0x24 b < 0)的分支中*(a + 8)=0x804a708,所以fun7(0x804a708, b)

2*0x804a708=0x32*a-b>0 (0x32 - b > 0),递归fun7(*(0x804a708 + 4) = 0x804a6f0, b)

3*0x804a6f0=0x2d*a-b<0 (0x2d - b < 0)fun7(*(0x804a6f0 + 8) = 0x804a684, b)

4*0x804a684=0x2f*a b == 0 (0x2f b == 0),所以b = 0x2f,递归返回。

得到3个不等式和一个等式:

1) 0x24 0x2f < 0

2) 0x32 0x2f > 0

3) 0x2d 0x2f < 0

4) b = 0x2f

都符合要求,所以我们得出最后输入的值就是十进制数47(0x2f)

参考逆向工程——二进制炸弹(CSAPP Project) - chkkch - 博客园 (cnblogs.com)

a86401cd54e44a6e96048a7665d7b0ea.png

5ee036f5baa648bc9db284c964e26203.png

 

 

  • 29
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值