继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Java逆向基础之静态变量存取

关注TA
已关注
手记
粉丝
获赞


注意:静态变量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: ()Vflags: ACC_STATICCode:stack=1, locals=0, args_size=00: ldc           #5                  // int 16645252: putstatic     #3                  // Field RNG_a:I5: ldc           #6                  // int 10139042237: putstatic     #4                  // Field RNG_c:I10: 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)Vflags: ACC_PUBLICCode:stack=1, locals=2, args_size=20: iload_11: putstatic     #2                  // Field rand_state:I4: 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: ()Iflags: ACC_PUBLICCode:stack=2, locals=1, args_size=10: getstatic     #2                  // Field rand_state:I3: getstatic     #3                  // Field RNG_a:I6: imul7: putstatic     #2                  // Field rand_state:I10: getstatic     #2                  // Field rand_state:I13: getstatic     #4                  // Field RNG_c:I16: iadd17: putstatic     #2                  // Field rand_state:I20: getstatic     #2                  // Field rand_state:I23: sipush        3276726: iand27: 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过度优化又说与源码不符还不好弄


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP