• 反汇编测试


    1.通过输入gcc -S -o main.s main.c 将下面c程序”week0303学号.c“编译成汇编代码

    2.使用gdb跟踪汇编代码,在纸上画出f中每一条语句引起的eip(rip),ebp(rbp),esp(rsb),eax(rax)的值和栈的变化情况。提交照片,要有学号信息。

    相关知识:
    esp:寄存器存放当前线程的栈顶指针
    ebp:寄存器存放当前线程的栈底指针
    eip:寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,然后继续执行。
    eax:是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。

    一个标准的函数起始代码:

    push ebp ;保存当前ebp
    mov ebp,esp ;EBP设为当前堆栈指针
    sub esp, xxx ;预留xxx字节给函数临时变量.

    使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器
    这里我遇到了一个问题,有下图的报错

    后来上网查了资料,解决办法是输入命令sudo apt-get install gcc-multilib

    进入之后先在main函数处设置一个断点,再run一下.

    使用disassemble指令获取汇编代码,用i(info) r(registers)指令查看各寄存器的值

    这里我发现了一条陌生的指令,<__x86.get_pc_thunk.ax>,其他的指令都差不多可以理解。

    后来上网查了资料,get_pc_thunk.xx是一个子程序,是被调用的,程序调用时,会把调用者的下一条指令的地址压栈保存(用于返回),所以进入get_pc_thunk.xx时,栈顶esp就是调用者的下一条指令地址。

    <__x86.get_pc_thunk.ax>这样的一条指令,就类似下面的操作:

    __get_pc_thunk.ax:
    movel (%esp),%eax
    return

    就是把esp的内容赋值给eax。

    call 0x56556213 <__x86.get_pc_thunk.ax>执行时,会把该指令的下一条指令的地址压栈保存。也就是把指令add 0x2ddd,%eax的地址0x565561ff压入栈中

    所以当进入子程序0x56556213<__x86.get_pc_thunk.ax>时,主要是执行:

    movel (%esp),%eax

    我的单步运行也证明了这一点:

    当调用者call 0x56556213<__x86.get_pc_thunk.ax>执行完毕返回时,将要执行的是:

    add 0x2ddd,%eax

    这里eax原始值就是该条指令本身的地址(在<__x86.get_pc_thunk.ax>中给eax赋值的)!然后加上0x2ddd,就是在本条指令偏移0x2ddd地址。

    所以call 0x56556213<__x86.get_pc_thunk.ax>的意义就是为了获取下一条指令的地址。

    利用了调用子程序会将下一条指令地址压栈的特性,提前获取下一条指令的地址。

    接着来分析

    由图可知,esp所在的地址为0xffffd0dc,所以此时主函数的栈基址为0xffffd0dc,用x(examine)指令查看内存地址中的值

    结合display命令和寄存器或pc内部变量,做如下设置:display /i $pc,这样在每次执行下一条汇编语句时,都会显示出当前执行的语句。下面展示每一步时%esp、%ebp和堆栈内容的变化:

    执行到call函数时,esp和ebp的地址发生了变化,变为了0xffffd0d8

    运行到即将调用f函数时,call指令将下一条指令的地址入栈,此时%esp,%ebp的值分别为0xffffd0d4和0xffffd0d8:

    这样就真正进入了f函数,下面是f函数的汇编代码

    将上一个函数的基址入栈,从当前%esp开始作为新基址

    实参的计算在%eax中进行

    通过一步一步调试,我记录了每一步运行时esp、ebp、eip、eax的变化

    指令 esp ebp eip eax 堆栈
    push %ebp 0xffffd0d0 0xffffd0d8 0x565561ca 0x56558fdc 0x5655620b
    mov %esp,%ebp 0xffffd0cc 0xffffd0d8 0x565561cb 0x56558fdc 0xffffd0d8,0x5655620b
    sub $0x10,%esp 0xffffd0cc 0xffffd0cc 0x565561cd 0x56558fdc 0xffffd0d8,0x5655620b
    call 0x56556213 0xffffd0bc 0xffffd0cc 0x565561d0 0x56558fdc 0x56556241,0xf7fe22d0,0x0,0x0,0xffffd0d8,0x5655620b
    add $0x2e07,%eax 0xffffd0bc 0xffffd0cc 0x565561d5 0x565561d5 0x56556241,0xf7fe22d0,0x0,0x0,0xffffd0d8,0x5655620b
    movl $0x10,-0x4(%epb) 0xffffd0bc 0xffffd0cc 0x565561da 0x56558fdc 0x56556241,0xf7fe22d0,0x0,0x0,0xffffd0d8,0x5655620b
    pushl 0x8(%ebp) 0xffffd0bc 0xffffd0cc 0x565561e1 0x56558fdc 0x56556241,0xf7fe22d0,0x0,0x0,0xffffd0d8,0x5655620b
    call 0x565561ad 0xffffd0b8 0xffffd0cc 0x565561e4 0x56558fdc 0x8,0x56556241,0xf7fe22d0,0x0,0x0,0xffffd0d8,0x5655620b
    add $0x4,%esp 0xffffd0b8 0xffffd0cc 0x565561e9 0xb 0x8,0x56556241,0xf7fe22d0,0x0,0x0,0xffffd0d8,0x5655620b
    mov -0x4(%ebp),%edx 0xffffd0bc 0xffffd0cc 0x565561ec 0xb 0x56556241,0xf7fe22d0,0x0,0x0,0xffffd0d8,0x5655620b
    add %edx,%eax 0xffffd0bc 0xffffd0cc 0x565561ef 0xb 0x56556241,0xf7fe22d0,0x0,0x0,0xffffd0d8,0x5655620b
    leave 0xffffd0bc 0xffffd0cc 0x565561f1 0xb 0x56556241,0xf7fe22d0,0x0,0x0,0xffffd0d8,0x5655620b
    ret 0xffffd0d0 0xffffd0d8 0x565561f2 0xb 0x5655620b

    参考:
    https://www.k2zone.cn/?p=1911
    https://blog.csdn.net/u012060033/article/details/79218909此时

  • 相关阅读:
    实现移动端1像素线--stylus
    用户信息认证session和token
    深入了解new的过程,和call,apply,bind的区别
    微信公众号开发过程--踏坑指南
    Better-scroll巨坑!!!
    JS ES6中Arguments和Parameters的区别
    知识点1
    面试--随笔1
    pytts3语音合成遇到的中文问题
    需求,需要谁参与进来?
  • 原文地址:https://www.cnblogs.com/ffffatal/p/15490925.html
Copyright © 2020-2023  润新知