• 逆向知识第十二讲,识别全局变量,静态全局变量,局部静态变量,以及变量.


    一丶认识全局的 (静态变量全局变量)

    高级代码:

    int RetInt()
    {
        int n = 0;
        scanf("%d",&n);
        return n;
    }
    static int g_Number = RetInt(); 
    int main(int argc, char* argv[])
    {
        g_Number = 3;
        scanf("%d",&g_Number);
        return g_Number;
    }

    我们的静态局部变量 g_Number 会通过一个函数进行赋值初始化

    VC6.0调试查看.

    我们发现通过栈回朔会调用4个函数

    调用顺序:

      _cinit()

      _initterm()

      $E2()

      #E1();

    首先讲解一下, _cinit函数是初始化函数,其中里面有个_initterm用来初始化全局变量的(不管是静态的全局变量,还是局部的全局变量,还是全局变量)

    E1() E2()函数,这里的两个函数涉及到一个设计的问题.要理解这个问题,我们看下调用_initterm里面是做的什么.

    _initterm()

    可以看到内部,函数指针遍历,建立了一个表来查询,然后调用这个函数指针.

    这个函数指针就是E2() 为了保证参数一致,返回值一致,所以调用了E2函数,当做一个固定接口

    那么E1函数就是具体做事情的

    E2函数中查看E1函数调用:

    所以说E2只是为了 _initterm的表的接口.

    E1函数内部:

    所以真正工作的函数是在E1内部,因为我们知道,在main函数之前定义全局变量,它会优先于main函数的开始进行初始化,怎么初始化的,就是通过_initerm遍历全局变量表,E2做接口,调用E1函数,进行初始化的.

    上面属于Debug下的汇编

    Release下的汇编

      PS: Release下的汇编会做优化,有可能你看不到E2这个代理函数了.

    找的方法同上,优先于main函数之前找_cinit 然后找到_initterm(注意有多个,不确定是哪个,可以看下入口点特征,前几讲已经说过)

      然后看_initterm的参数,指向的是那个函数指针,我们跳过去即可.

    IDA

    所以有时我们会看到一个.

    二丶认识局部静态变量

    高级代码:

    int main(int argc, char* argv[])
    {
        static number = argc;
        scanf("%d",&number);
        return number;
    }

    注意我是初始化给的变量,常量的话优化会直接优化了.很简单,不讲解.

    Debug下的汇编代码

    我们说过,静态局部变量,其实也是一个全局变量,只不过限制了作用域,但是限制的前提是什么,前提就是加标记,所以我们才会看到一个跳转.判断标记的.

    识别局部变量和参数

    这个很简单了,因为一直在用,  一般来说,局部变量都是使用ebp或者esp寻址, 如果碰到ebp-xxx,也就是减量的时候就是访问局部变量,如果变为增量的话就是寻找参数.

    转载于:

    作者:IBinary
    出处:http://www.cnblogs.com/iBinary/

  • 相关阅读:
    [转载]很完整的2、8、10、16进制转换方法
    [转载]C++星号的含义
    [转载]C++星号的含义
    [转载]麦凯66表格
    [转载]js入门·对象属性方法大总结
    [转载]图解《越狱》中纸玫瑰的折法
    [转载]比较开始日期与结束日期的js方法
    Cannot set device tcp segmentation offload settings: Invalid argument
    记一次薪酬谈判的教训
    TCP拥塞状态机的实现(中)
  • 原文地址:https://www.cnblogs.com/gd-luojialin/p/11219869.html
Copyright © 2020-2023  润新知