assembly 堆栈缓冲区溢出的汇编语言程序示例

nx7onnlm  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(152)

我试图写一个示例程序来理解堆栈缓冲区溢出,我有以下程序。
溢出。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

我期望要么我得到一些垃圾或segfault。但它似乎工作的预期。所以在和函数中,当我增加堆栈指针4字节,当我存储的值5 8字节从基指针,我期待这是一个溢出的模拟。上述程序是错误的使用堆栈缓冲区溢出的例子。

pokxtpni

pokxtpni1#

%esp以下的内存可能会被异步清除(通过信号处理程序1),但**程序的行为并不取决于您在ESP正下方的4字节堆栈槽中用addl $5, -8(%ebp)movl -8(%ebp), %eax**读/写的值。
在Linux上,至少在同一页面内,接触ESP以下的内存不是错误。如果超过这个范围,它可能会出现segfault而不是growing the stack(对于主线程的堆栈),除非堆栈指针先被移动。(线程堆栈已经被完全分配,而不是动态增长。初始进程堆栈是特殊的。)

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

如果您执行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下有一个无限的red-zone

但这是一种特殊情况,当你在编写一个完整的程序,而不使用任何库时,通常你应该只内联小函数,如果预留和释放堆栈空间的额外指令有不小的开销。
此外,如果您在GDB中执行print foo()或其他操作,使其在某个断点处停止时调用函数,则调试器可以使用此空间。

相关问题