zoukankan      html  css  js  c++  java
  • 汇编语言基础之九 关于栈指针的规律性的总结

    栈底指针可以被用来判断传递的参数的值,还有函数的局部变量的值。

    让我们继续用上一个例子来说明一下吧。

    ChildEBP RetAddr 
    0012ff34 00401121 Simple!Foo2+0x64 [C:\Labfiles\Module04\Simple\Simple.cpp @ 82]
    0012ff4c 004010da Simple!Foo1+0x31 [C:\Labfiles\Module04\Simple\Simple.cpp @ 65]
    0012ff64 00401096 Simple!Foo+0x2d [C:\Labfiles\Module04\Simple\Simple.cpp @ 49]
    0012ff80 00404739 Simple!main+0x36 [C:\Labfiles\Module04\Simple\Simple.cpp @ 33]
    0012ffc0 7c817077 Simple!mainCRTStartup+0xe9 [crt0.c @ 206]

    栈中的内容如下:

    dd esp

    0012ff14  cccccccc cccccccc cccccccc cccccccc
    0012ff24  cccccccc cccccccc cccccccc cccccccc
    0012ff34  0012ff4c 00401121 00000001 00000002
    0012ff44  00000002 00000001 0012ff64 004010da
    0012ff54  0012ff60 0012ff5c 00000002 00000001
    0012ff64  0012ff80 00401096 00000001 00000002
    0012ff74  00000002 00000001 cccccccc 0012ffc0
    0012ff84  00404739 00000001 00420e90 00420de0

    dd

    0012ff94  43010000 00000000 7ffde000 00000001
    0012ffa4  00000006 0012ff94 80621a58 0012ffe0
    0012ffb4  00408084 00417218 00000000 0012fff0
    0012ffc4  7c817077 43010000 00000000 7ffde000
    0012ffd4  8054c6ed 0012ffc8 8918f3e8 ffffffff
    0012ffe4  7c839ad8 7c817080 00000000 00000000
    0012fff4  00000000 00404650 00000000 78746341
    00130004  00000020 00000001 000024b8 000000c4

    利用EBP确定参数

    ==============

    函数Foo2的栈底位置为0012ff34 ,而函数返回值的位置就在栈底的下方,即ebp+4. 在这里为00401121。

    第一个参数在参数表的最左边,是最后一个压栈的参数,所以第一个参数的起始地址为ebp+8,根据前面我们的程序Simple.cpp,可以看出第一个参数的值为1, 第二个参数的值为2.

    运行如下的命令来验证。可以看到ebp+8所指向的内存中,值为1。第二个参数的位置为ebp+12,在下面的内存dump中,可以看到该位置的值确实为2.

    dd ebp+8

    0012ff3c  00000001 00000002 00000002 00000001
    0012ff4c  0012ff64 004010da 0012ff60 0012ff5c
    0012ff5c  00000002 00000001 0012ff80 00401096
    0012ff6c  00000001 00000002 00000002 00000001
    0012ff7c  cccccccc 0012ffc0 00404739 00000001
    0012ff8c  00420e90 00420de0 43010000 00000000
    0012ff9c  7ffde000 00000001 00000006 0012ff94
    0012ffac  80621a58 0012ffe0 00408084 00417218

    Windbg有个查看函数ebp,返回值和前三个参数的命令,很方便。

    ChildEBP RetAddr  Args to Child             
    0012ff34 00401121 00000001 00000002 00000002 Simple!Foo2+0x64 [C:\Labfiles\Module04\Simple\Simple.cpp @ 82]
    0012ff4c 004010da 0012ff60 0012ff5c 00000002 Simple!Foo1+0x31 [C:\Labfiles\Module04\Simple\Simple.cpp @ 65]
    0012ff64 00401096 00000001 00000002 00000002 Simple!Foo+0x2d [C:\Labfiles\Module04\Simple\Simple.cpp @ 49]
    0012ff80 00404739 00000001 00420e90 00420de0 Simple!main+0x36 [C:\Labfiles\Module04\Simple\Simple.cpp @ 33]
    0012ffc0 7c817077 43010000 00000000 7ffde000 Simple!mainCRTStartup+0xe9 [crt0.c @ 206]
    WARNING: Stack unwind information not available. Following frames may be wrong.
    0012fff0 00000000 00404650 00000000 78746341 kernel32!RegisterWaitForInputIdle+0x49

    利用EBP确定局部变量

    ==============

    局部变量的地址是按照与EBP的距离由近到远,从第一个往后分配地址的。

    所以,第一个局部变量的位置是ebp-4,第二个是ebp-8.

    由于有些局部变量在函数中非常的常用,所以有时局部变量不一定会被压入栈中,而在寄存器中。所以,确定局部变量有可能需要去查看汇编代码,来看变量时从哪里来的,如何移动的,以及如何改变的。

    总结一下

    项目 根据EBP的计算公式
    当前函数栈底的位置 EBP
    上一个函数栈底位置 [EBP]
    当前函数的返回地址 EBP+4
    第一个局部变量 EBP-4
    第二个局部变量 EBP-0x8
    第三个局部变量 EBP-0xc
    第一个参数 EBP+8
    第二个参数 EBP+0xc
  • 相关阅读:
    【老三层总结】老三层 页面 传值
    【总结-前台发送后台接收表单】MVC提交表单的四种方式
    Django使用Channels实现WebSocket数据推送功能
    关于子网、子网划分的一些内容
    关于摄像头推流拉流的一些内容
    群晖 docker frp公网访问
    Gitea搭建(搭建私有github仓库)
    frp内网穿透搭建流程,UDP通讯测试
    Centos7基础内容-命令
    Django 使用forms进行POST字段校验(文件上传校验)
  • 原文地址:https://www.cnblogs.com/awpatp/p/1597269.html
Copyright © 2011-2022 走看看