【问题标题】:Example assembly language program for stack buffer overflow堆栈缓冲区溢出的示例汇编语言程序
【发布时间】:2018-05-25 19:20:54
【问题描述】:

我正在尝试编写一个示例程序来理解堆栈缓冲区溢出,并且我有以下程序。

溢出.s:

    .section .data
    .section .text
    .globl _start
    _start:
          call sum
          movl %eax, %ebx
          movl $15, %ebx
          movl $1, %eax
          int $0x80

         .type sum, @function
    sum:
         pushl %ebp        # save the current base pointer
         movl %esp, %ebp   # store current stack pointer to %ebp
         subl $4, %esp     # inc the stack pointer by 4 bytes for local variable 
         movl $5, -8(%ebp) # store value 5 from 8 bytes of %ebp 4 bytes beyond stack pointer
         addl $5, -8(%ebp) # add 5 to the value store beyond of stack pointer 
         movl -8(%ebp), %eax # store the value in %eax
         movl %ebp, %esp
         popl %ebp
         ret

组装和链接程序:

   as -gstabs+ overflow.s -o oveflow.o
   ld overflow.o -o overflow
   ./overflow
   echo $?
   15 <============= the result

我希望我得到一些垃圾或段错误。但它似乎按预期工作。因此,在 sum 函数中,当我将堆栈指针增加 4 个字节并从基指针存储值 5 8 个字节时,我期待这是对溢出的模拟。上面的程序是不是用堆栈缓冲区溢出的例子是错误的。 ?

【问题讨论】:

  • 顺便说一句,GAS 中的注释字符是#,而不是;。我认为您在复制代码后添加了 cmets,因为那实际上不会组装。 (; 像换行符一样工作,因此您可以使用它在宏或其他东西的一行中放置多个指令或指令。)

标签: assembly buffer-overflow gnu-assembler


【解决方案1】:

%esp 下面的内存可能会被异步破坏(由信号处理程序1),但程序的行为并不取决于您使用@987654323 读取/写入的值@ 或 movl -8(%ebp), %eax,在 ESP 正下方的 4 字节堆栈槽中。

在 Linux 上,触摸低于 ESP 的内存并不是错误,一直到最大堆栈大小的限制(ulimit -s,默认为 8192 kiB)。如果内存还没有映射,堆栈映射会自动扩展以映射那里的所有页面和当前映射的具有最低地址的堆栈页面。 (或者,对于线程堆栈,它已经被完全分配,而不是动态增长。但是初始进程堆栈是特殊的。)


如果你在循环中运行 push(没有 pop 或其他任何东西来平衡它),堆栈会增长,直到 ESP 减少到指向超出点的未映射页面内核将为您增加堆栈。然后下一个push(或call 或其他)会出现段错误,我们称之为堆栈溢出。


如果您使用sub $12, %espint arr[3] 保留空间,但随后写信给int arr[5],则会出现缓冲区溢出:这将覆盖您的返回地址,因此最终的ret 将跳到攻击者想让你跳的地方。

 # arg in EAX: how many array elements to store into arr[3]
 vulnerable_function:
    sub  $12, %esp
    mov  %esp, %ecx
.Lloop:
    mov  %eax, (%ecx)
    add  $4, %ecx
    dec  %eax
    jnz  .Lloop

    add  $12, %esp
    ret

脚注 1: 您还没有安装任何信号处理程序,因此(在 Linux 上)没有任何东西可以异步使用堆栈内存,并且您在 ESP 下有无限的

但这是一个特殊情况,当您编写一个完整的程序并且不使用任何库时,如果用于保留和释放堆栈空间的额外指令具有不小的成本,通常您应该只内联小函数。

此外,如果您在 GDB 中执行 print foo() 或让它在某个断点处停止时调用函数,调试器可以踩到这个空间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-23
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 2017-06-26
    • 2015-07-03
    相关资源
    最近更新 更多