zoukankan      html  css  js  c++  java
  • Java逆向系列-基础指令:静态变量存取

    注意:静态变量static可以多次赋值,不能多次赋值的是final static

    线性同余伪随机数算法LCG 算法数学上基于公式:

    X(n+1) = (a * X(n) + c) % m

    其中,各系数为:

    模m, m > 0

    系数a, 0 < a < m

    增量c, 0 <= c < m

    原始值(种子) 0 <= X(0) < m

    其中参数c, m, a比较敏感,或者说直接影响了伪随机数产生的质量。

    一般而言,高LCG的m是2的指数次幂(一般2^32或者2^64),因为这样取模操作截断最右的32或64位就可以了。多数编译器的库中使用了该理论实现其伪随机数发生器rand()。

    这里m取2^32,a取1664525,c取1013904223

    LCG算法实现例子

    public class LCG
    {
    public static int rand_state;
    public void my_srand (int init)
    {
    rand_state=init;
    }
    public static int RNG_a=1664525;
    public static int RNG_c=1013904223;
    public int my_rand ()
    {
    rand_state=rand_state*RNG_a;
    rand_state=rand_state+RNG_c;
    return rand_state & 0x7fff;
    }
    }

    编译

    javac LCG.java

    反编译

    javap -c -verbose LCG.class

    静态块的初始化

    static {};
    descriptor: ()V
    flags: ACC_STATIC
    Code:
    stack=1, locals=0, args_size=0
    0: ldc           #5                  // int 1664525
    2: putstatic     #3                  // Field RNG_a:I
    5: ldc           #6                  // int 1013904223
    7: putstatic     #4                  // Field RNG_c:I
    10: return

    ldc  #5 取常量1664525压栈

    putstatic  #3 从栈顶取值,存入静态变量RNG_a:I中

    ldc  #6 取常量1013904223压栈

    putstatic  #4 从栈顶取值,存入静态变量RNG_c:I中

    这里putstatic实现了给静态变量初始化值。

    下面的my_srand()函数将输入值存储到rand_state中

    public void my_srand(int);
    descriptor: (I)V
    flags: ACC_PUBLIC
    Code:
    stack=1, locals=2, args_size=2
    0: iload_1
    1: putstatic     #2                  // Field rand_state:I
    4: return

    iload_1 //将第一个参数(init)压入栈,为什么不是iload_0?iload_0已经在默认生成的构造方法中使用了

    (iload_0在构造方法中将this压入栈顶)

    putstatic #2 //取出栈顶的init的值,将值保存至静态变量rand_state:I

    这里补充说明一下,不知道是译者还是原作者的问题,这个存的值应该是类的初始化的时候的stack分的静态变量存储区域,不是所说的第二存储位

    再看my_rand()

    public int my_rand();
    descriptor: ()I
    flags: ACC_PUBLIC
    Code:
    stack=2, locals=1, args_size=1
    0: getstatic     #2                  // Field rand_state:I
    3: getstatic     #3                  // Field RNG_a:I
    6: imul
    7: putstatic     #2                  // Field rand_state:I
    10: getstatic     #2                  // Field rand_state:I
    13: getstatic     #4                  // Field RNG_c:I
    16: iadd
    17: putstatic     #2                  // Field rand_state:I
    20: getstatic     #2                  // Field rand_state:I
    23: sipush        32767
    26: iand
    27: ireturn

    原文评论了17的putstatic #2和20的getstatic #2效率不高,实际上这只是java语句的翻译而已

    试试把

    public int my_rand ()
    {
    rand_state=rand_state*RNG_a;
    rand_state=rand_state+RNG_c;
    return rand_state & 0x7fff;
    }

    改成

    public int my_rand ()
    {
    rand_state=rand_state*RNG_a+RNG_c;
    return rand_state & 0x7fff;
    }

    再看这部分的反编译

      public int my_rand();
        descriptor: ()I
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=1, args_size=1
             0: getstatic     #2                  // Field rand_state:I
             3: getstatic     #3                  // Field RNG_a:I
             6: imul
             7: getstatic     #4                  // Field RNG_c:I
            10: iadd
            11: putstatic     #2                  // Field rand_state:I
            14: getstatic     #2                  // Field rand_state:I
            17: sipush        32767
            20: iand
            21: ireturn

    这样就把原来的20行去掉了,这个应该在源码方面优化的就别交给JVM去优化了,JVM过度优化又说与源码不符还不好弄

    本文参考:逆向工程权威指南.下册.pdf 和http://blog.51cto.com/7317859/2105269

  • 相关阅读:
    Tomcat虚拟目录的映射方式
    Linux常用命令
    java断点调试
    破解MyEclipse
    JS判断浏览器
    css3 box-sizing详解。
    this-使用call . apply
    this-内部函数
    this-对象方法调用
    this-纯函数
  • 原文地址:https://www.cnblogs.com/llhl/p/9648610.html
Copyright © 2011-2022 走看看