二进制炸弹汇编语言分配

Posted

技术标签:

【中文标题】二进制炸弹汇编语言分配【英文标题】:Binary Bomb Assembly Language Assignment [closed] 【发布时间】:2013-11-19 15:24:24 【问题描述】:

像这里的许多人一样,我被赋予了做炸弹实验室的任务。我已经能够相当轻松地完成前 3 个,但是这个阶段让我无法理解。我已确定答案包括 2 个答案,格式为 %d %d,但我一直无法遵循递归汇编。

这是一个给学生一个炸弹的作业,并且必须输入各种输入来禁用所有 6 个阶段。如果用户输入错误,炸弹就会爆炸。你没有得到源代码,只有可执行文件。这是拆解的阶段“阶段 4”。它还调用了 func4,所以它也被反汇编了。

这里是拆弹需要的 Phase_4 和 func4 的 objdump -d

Dump of assembler code for function phase_4:
0x08048f41 <+0>:     push   %ebp
0x08048f42 <+1>:     mov    %esp,%ebp
0x08048f44 <+3>:     sub    $0x28,%esp
0x08048f47 <+6>:     lea    -0x10(%ebp),%eax
0x08048f4a <+9>:     mov    %eax,0xc(%esp)
0x08048f4e <+13>:    lea    -0xc(%ebp),%eax
0x08048f51 <+16>:    mov    %eax,0x8(%esp)
0x08048f55 <+20>:    movl   $0x804a64c,0x4(%esp)
0x08048f5d <+28>:    mov    0x8(%ebp),%eax
0x08048f60 <+31>:    mov    %eax,(%esp)
0x08048f63 <+34>:    call   0x8048894 <__isoc99_sscanf@plt>
0x08048f68 <+39>:    cmp    $0x2,%eax
0x08048f6b <+42>:    jne    0x8048f79 <phase_4+56>
0x08048f6d <+44>:    mov    -0xc(%ebp),%eax
0x08048f70 <+47>:    test   %eax,%eax
0x08048f72 <+49>:    js     0x8048f79 <phase_4+56>
0x08048f74 <+51>:    cmp    $0xe,%eax
0x08048f77 <+54>:    jle    0x8048f7e <phase_4+61>
0x08048f79 <+56>:    call   0x80493e1 <explode_bomb>
0x08048f7e <+61>:    movl   $0xe,0x8(%esp)
0x08048f86 <+69>:    movl   $0x0,0x4(%esp)
0x08048f8e <+77>:    mov    -0xc(%ebp),%eax
0x08048f91 <+80>:    mov    %eax,(%esp)
0x08048f94 <+83>:    call   0x8048c80 <func4>
0x08048f99 <+88>:    cmp    $0x12,%eax
0x08048f9c <+91>:    jne    0x8048fa4 <phase_4+99>
0x08048f9e <+93>:    cmpl   $0x12,-0x10(%ebp)
0x08048fa2 <+97>:    je     0x8048fad <phase_4+108>
0x08048fa4 <+99>:    lea    0x0(%esi,%eiz,1),%esi
0x08048fa8 <+103>:   call   0x80493e1 <explode_bomb>
0x08048fad <+108>:   leave
0x08048fae <+109>:   xchg   %ax,%ax
0x08048fb0 <+111>:   ret
End of assembler dump.

Dump of assembler code for function func4:
0x08048c80 <+0>:     push   %ebp
0x08048c81 <+1>:     mov    %esp,%ebp
0x08048c83 <+3>:     sub    $0x18,%esp
0x08048c86 <+6>:     mov    %ebx,-0x8(%ebp)
0x08048c89 <+9>:     mov    %esi,-0x4(%ebp)
0x08048c8c <+12>:    mov    0x8(%ebp),%eax
0x08048c8f <+15>:    mov    0xc(%ebp),%edx
0x08048c92 <+18>:    mov    0x10(%ebp),%esi
0x08048c95 <+21>:    mov    %esi,%ecx
0x08048c97 <+23>:    sub    %edx,%ecx
0x08048c99 <+25>:    mov    %ecx,%ebx
0x08048c9b <+27>:    shr    $0x1f,%ebx
0x08048c9e <+30>:    lea    (%ebx,%ecx,1),%ecx
0x08048ca1 <+33>:    sar    %ecx
0x08048ca3 <+35>:    lea    (%ecx,%edx,1),%ebx
0x08048ca6 <+38>:    cmp    %eax,%ebx
0x08048ca8 <+40>:    jle    0x8048cc1 <func4+65>
0x08048caa <+42>:    lea    -0x1(%ebx),%ecx
0x08048cad <+45>:    mov    %ecx,0x8(%esp)
0x08048cb1 <+49>:    mov    %edx,0x4(%esp)
0x08048cb5 <+53>:    mov    %eax,(%esp)
0x08048cb8 <+56>:    call   0x8048c80 <func4>
0x08048cbd <+61>:    add    %eax,%ebx
0x08048cbf <+63>:    jmp    0x8048cda <func4+90>
0x08048cc1 <+65>:    cmp    %eax,%ebx
0x08048cc3 <+67>:    jge    0x8048cda <func4+90>
0x08048cc5 <+69>:    mov    %esi,0x8(%esp)
0x08048cc9 <+73>:    lea    0x1(%ebx),%edx
0x08048ccc <+76>:    mov    %edx,0x4(%esp)
0x08048cd0 <+80>:    mov    %eax,(%esp)
0x08048cd3 <+83>:    call   0x8048c80 <func4>
0x08048cd8 <+88>:    add    %eax,%ebx
0x08048cda <+90>:    mov    %ebx,%eax
0x08048cdc <+92>:    mov    -0x8(%ebp),%ebx
0x08048cdf <+95>:    mov    -0x4(%ebp),%esi
0x08048ce2 <+98>:    mov    %ebp,%esp
0x08048ce4 <+100>:   pop    %ebp
0x08048ce5 <+101>:   ret
End of assembler dump.

【问题讨论】:

Q19646901 的副本,期望值为 18。 【参考方案1】:

编辑:实际上,真的很累...混淆参数和本地变量通常不是我犯的错误...

更正逆向工程: 对于phase4(),仍然只是其中的一部分:

0x08048f47 <+6>:     lea    -0x10(%ebp),%eax
0x08048f4a <+9>:     mov    %eax,0xc(%esp)            <== arg3 (&(int l)) sscanf()
0x08048f4e <+13>:    lea    -0xc(%ebp),%eax
0x08048f51 <+16>:    mov    %eax,0x8(%esp)            <== arg2 (&(int m)) sscanf()
0x08048f55 <+20>:    movl   $0x804a64c,0x4(%esp)      <== arg0 (fmt) sscanf()
0x08048f5d <+28>:    mov    0x8(%ebp),%eax
0x08048f60 <+31>:    mov    %eax,(%esp)               <== arg0 --> arg1 sscanf()
0x08048f63 <+34>:    call   0x8048894 <__isoc99_sscanf@plt>
0x08048f68 <+39>:    cmp    $0x2,%eax
0x08048f6b <+42>:    jne    0x8048f79 <phase_4+56>    <== if (sscanf(...) != 2)
0x08048f6d <+44>:    mov    -0xc(%ebp),%eax                   explode_bomb();
0x08048f70 <+47>:    test   %eax,%eax
0x08048f72 <+49>:    js     0x8048f79 <phase_4+56>    <== if (m < 0) // signed
0x08048f74 <+51>:    cmp    $0xe,%eax                         explode_bomb();
0x08048f77 <+54>:    jle    0x8048f7e <phase_4+61>    <== if (!(m <= 14))
0x08048f79 <+56>:    call   0x80493e1 <explode_bomb>          explode_bomb();
[ ... ]
0x08048f94 <+83>:    call   0x8048c80 <func4>
0x08048f99 <+88>:    cmp    $0x12,%eax                <== if (func4(...) != 18)
0x08048f9c <+91>:    jne    0x8048fa4 <phase_4+99>            explode_bomb();
0x08048f9e <+93>:    cmpl   $0x12,-0x10(%ebp)         <== if (l != 18)
0x08048fa2 <+97>:    je     0x8048fad <phase_4+108>           explode_bomb();
0x08048fa4 <+99>:    lea    0x0(%esi,%eiz,1),%esi
0x08048fa8 <+103>:   call   0x80493e1 <explode_bomb>
0x08048fad <+108>:   leave

所以这会调用sscanf(),格式字符串存储在0x804a64c(可能是"%d %d"),将phase4()的参数作为字符串解析;即在 C 源代码中,它是 sscanf("%d "%d", phase4_arg, &amp;l, &amp;m);,其中 lm 是本地 int 变量。它测试两个数字是否已成功解析,然后检查它们的值。

【讨论】:

只是出于好奇:我和你在这里的深度差不多,翻译相同...当我注意到你翻译为 argv3 的内容(我做了同样的)实际上很难-spot "-" 对 %ebp 的引用 - 或者至少看起来... 哈,感谢您的发现……那里真的太累了:)

以上是关于二进制炸弹汇编语言分配的主要内容,如果未能解决你的问题,请参考以下文章

二进制炸弹,汇编代码解读

非保姆级二进制炸弹破解分析

CMU-CSAPP-Lab2拆解二进制炸弹

二元炸弹 - 第 4 阶段

非保姆级二进制炸弹破解分析

非保姆级二进制炸弹破解分析