混淆在-0x20(%ebp)

时间:2015-04-15 08:09:09

标签: assembly

我最近自学了计算机系统。我不理解二进制炸弹实验室第2阶段的代码。我输入1 2 3 4 5 6作为输入

这些车道有什么作用? 这个-0x20是怎么来的?它的目的是什么?

0x08048bab <+7>:    lea    -0x20(%ebp),%eax
0x08048bae <+10>:   mov    %eax,0x4(%esp)

这些代码来自

Dump of assembler code for function phase_2:

0x08048ba4 <+0>:    push   %ebp
0x08048ba5 <+1>:    mov    %esp,%ebp
0x08048ba7 <+3>:    push   %ebx
0x08048ba8 <+4>:    sub    $0x34,%esp
0x08048bab <+7>:    lea    -0x20(%ebp),%eax
0x08048bae <+10>:   mov    %eax,0x4(%esp)
0x08048bb2 <+14>:   mov    0x8(%ebp),%eax
0x08048bb5 <+17>:   mov    %eax,(%esp)
0x08048bb8 <+20>:   call   0x804928d <read_six_numbers>
0x08048bbd <+25>:   cmpl   $0x0,-0x20(%ebp)
0x08048bc1 <+29>:   jns    0x8048be3 <phase_2+63>
0x08048bc3 <+31>:   call   0x804924b <explode_bomb>
0x08048bc8 <+36>:   jmp    0x8048be3 <phase_2+63>
0x08048bca <+38>:   mov    %ebx,%eax
0x08048bcc <+40>:   add    -0x24(%ebp,%ebx,4),%eax
0x08048bd0 <+44>:   cmp    %eax,-0x20(%ebp,%ebx,4)
0x08048bd4 <+48>:   je     0x8048bdb <phase_2+55>
0x08048bd6 <+50>:   call   0x804924b <explode_bomb>
0x08048bdb <+55>:   inc    %ebx
0x08048bdc <+56>:   cmp    $0x6,%ebx
0x08048bdf <+59>:   jne    0x8048bca <phase_2+38>
0x08048be1 <+61>:   jmp    0x8048bea <phase_2+70>

2

我觉得

mov 0xc(%ebp),%eax

正在获得投入。

我试过x / s $ ebp + oxc,它打印出这个字符串\ 350 \ 366 \ 377 \ 277 \ b \ 367 \ 377 \ 277&gt; \ 223 \ 004 \ b {\ 246 \ 004 \ b。 那是什么?我真的很难理解这是做什么的?我试图在每个内存地址中打印出值,但它没有帮助。

当我尝试在cmp $ 0x5,%eax之前打印出x / d $ eax时,它显示无法访问地址0x0处的内存。

 Dump of assembler code for function read_six_numbers:
0x0804928d <+0>:    push   %ebp
0x0804928e <+1>:    mov    %esp,%ebp
0x08049290 <+3>:    sub    $0x28,%esp
0x08049293 <+6>:    mov    0xc(%ebp),%eax
0x08049296 <+9>:    lea    0x14(%eax),%edx
0x08049299 <+12>:   mov    %edx,0x1c(%esp)
0x0804929d <+16>:   lea    0x10(%eax),%edx
0x080492a0 <+19>:   mov    %edx,0x18(%esp)
0x080492a4 <+23>:   lea    0xc(%eax),%edx
0x080492a7 <+26>:   mov    %edx,0x14(%esp)
0x080492ab <+30>:   lea    0x8(%eax),%edx
0x080492ae <+33>:   mov    %edx,0x10(%esp)
0x080492b2 <+37>:   lea    0x4(%eax),%edx
0x080492b5 <+40>:   mov    %edx,0xc(%esp)
0x080492b9 <+44>:   mov    %eax,0x8(%esp)
0x080492bd <+48>:   movl   $0x804a64b,0x4(%esp)
0x080492c5 <+56>:   mov    0x8(%ebp),%eax
0x080492c8 <+59>:   mov    %eax,(%esp)
0x080492cb <+62>:   call   0x8048860 <__isoc99_sscanf@plt>
0x080492d0 <+67>:   cmp    $0x5,%eax
0x080492d3 <+70>:   jg     0x80492da <read_six_numbers+77>
0x080492d5 <+72>:   call   0x804924b <explode_bomb>

2 个答案:

答案 0 :(得分:1)

正如迈克尔所说,sub $0x34,%esp为局部变量创造了空间。由于mov %esp,%ebp之前已将%esp复制到%ebp,因此此分配的空间也可以相对于%ebp %ebp-0x34%ebp的{​​{1}}来解决。 %ebp-0x20是局部变量的地址,在这种情况下,它是大小为6的整数数组的基址(即int numbers[6];)。此地址被加载到%eax并随后写入到堆栈:

0x08048bab <+7>:    lea    -0x20(%ebp),%eax
0x08048bae <+10>:   mov    %eax,0x4(%esp)

适用的调用约定指定参数应在堆栈上传递。因此,这是将地址作为第二个参数传递给以下函数调用。第一个是%esp

0x08048bb2 <+14>:   mov    0x8(%ebp),%eax
0x08048bb5 <+17>:   mov    %eax,(%esp)
0x08048bb8 <+20>:   call   0x804928d <read_six_numbers>

请注意,当前函数的传入参数也在堆栈上,并且可以使用来自%ebp的正偏移来解决,从8开始。因此,上面的代码将第一个传入的参数作为第一个参数传递给read_six_numbers。总而言之,到目前为止,代码可能看起来像这样:

void phase_2(char* text)
{
    int numbers[6];
    read_six_numbers(text, numbers);
    ...
}

查看read_six_numbers我们可以看到它获取传入的参数并为sscanf创建一堆传出参数:

void read_six_numbers(char* text, int* numbers)
{
    if (sscanf(text, "%d %d %d %d %d %d", numbers, numbers + 1,
            numbers + 2, numbers + 3, numbers + 4, numbers + 5) != 6)
        explode_bomb();
}

我相信你可以在汇编代码中看到这是如何完成的。

答案 1 :(得分:0)

EBP指向堆栈框架的“底部”。因此,当您需要将内容放入堆栈时,可以通过从EBP中减去来解决它。

因此,在您的示例中,它采用“EBP - 0x20”的地址并将结果存储在EAX中。