https://blog.csdn.net/elicococoo/article/details/41851473
C语言随机数的实现:mingw与glibc
关于随机数的实现都是基于线性同余生成器(LCG,linear congruential generator)。
r(n + 1)= (r(n) * a + c) mod m 其中参数a、c、m直接影响r的质量。vc上微软对随机数生成范围进行了修改,方法较简单,直接执行上述方程并取高16位数即可。作者在文章中给出了随机数产生方式的推理过程以及代码实现。
https://blog.csdn.net/u013378306/article/details/63682945
http://www.cnblogs.com/cr330326/p/5534915.html
java 代码混淆原理
混淆器是由于Java程序运行时是动态连接的,因此编译成的目标文件中包含有符号表,使得Java程序很容易被反编译,混淆器可以打乱class文件中的符号信息,使反向工程变得非常困难。现有的混淆器仍然存在很多无法完全避免的问题。Java混淆编译器是在Sun JDK中提供的Java编译器(javac)的基础上完成的,修改了代码生成过程,对编译器生成的中间代码进行混淆,最后再生成class文件,这样编译和混淆只需要一个步骤就可以完成。最后,作者介绍了如何安装并运行JOC、如何使用符号保留指令以及给出一个JOC混淆后的案例。
ProGuard代码混淆技术详解
首先,Proguard是一个Java类文件压缩器、优化器、混淆器、预校验器。压缩环节会检测以及移除没有用到的类、字段、方法以及属性。优化环节会分析以及优化方法的字节码。混淆环节会用无意义的短变量去重命名类、变量、方法。这些步骤让代码更精简,更高效,也更难被逆向(破解)。 在编写一个ProGuard文件时,需要经过基本混淆、针对APP的量身定制、针对第三方jar包的解决方案三个基本过程。Android项目的安全性需要Proguard去保证,Proguard使开发的APK更健壮。
https://www.cnblogs.com/wsq-888/p/jie-gou-ti-dui-qi-gui-ze-ji-ju-li.html
结构体(对齐规则及举例)
结构体是C语言中聚合数据类型的一类;可以被声明为变量、数组、指针等,用以实现比较复杂的数据结构;是一系列元素的集合,这些元素被称为结构体成员;结构体成员需要用结构体名访问。文章主要阐述了结构体进行对齐的原因和规则,并在文章末尾处举例说明。对于结构体对齐有如下说明:计算结构体大小不是元素单纯相加;32位CPU取四个字节比一个字节更高效方便;一般情况下32位默认4字节对齐。平台原因(移植原因):不是所有的硬件平台都能访问任意地址的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据的,否则抛出硬件异常。性能原因:数据结构(尤其是栈),应该尽可能在自然边界上对齐,因为在访问为对齐的内存时,处理器需要访问两次,而对齐的内存处理器只需要访问一次。这些外部和内部的原因都决定了对于编译器来讲,结构体是否对齐会影响处理器的性能。
http://www.cis.syr.edu/~wedu/seed/Labs_16.04/Crypto/Crypto_MD5_Collision/
1)用md5collgen生成两个不同的文件:
2)比较生成的两文件:
可以看出,生成的两个文件内容并不相同,但他们的哈希值是一样的。
3)bless编辑器查看两文件:
可以看出,两文件的前缀都是一样的(qwerty),而两文件的内容是存在差异的,比如0000006d处的字节就不同。从中可以分析出md5collgen的原理。它从prifix.txt中取前缀,如果前缀不是64的倍数,则用零填充。md5collgen为两个输出文件生成128字节的内容,这两个输出文件就是在这128字节中存在部分差异。
问题1:如果前缀文件的长度不是64的倍数会发生什么?
答1:md5collgen会自动填充0,直到前缀长度满足是64的倍数。
问题2:创建一个正好64字节的前缀文件,然后再次运行冲突工具看看会发生什么。
答2:无填充,64字节即为前缀。
问题3:md5collgen为两个输出文件生成的数据(128字节)是否完全不同?请识别所有不同的字节。
答3:不是完全不同,其中不同的字节如下表所示:
1)将二进制文件out1.bin和out2.bin分别与out3.bin连接成一个文件(命名分别为out13.bin,out23.bin):
2)计算out13.bin和out23.bin的哈希值:
可以看出,两文件的哈希值是一样的。可以证明MD5具有该属性:给定两个输入M和N,如果MD5(M) = MD5(N),即M和N的MD5散列相同,那么对于任何输入T,MD5(M || T) = MD5(N || T),其中||代表串联。
1)编译题目所给代码命名为1,将1复制一份命名为2。我们的目的是程序1,2虽不同,但它们的哈希值是一样的:
2)bless打开程序1,找出数组的位置:
可以看出,数组的起始位置是0x00001040。前面有0x1040字节,正好是0x40的倍数,所以我们可以用前0x1040字节当前缀。
3)将程序1的前0x1040字节作为prefix,用md5collgen生成两哈希值相同的文件out1.bin,out2.bin:
4)用out1.bin的尾缀128字节覆盖程序1的数组,用out2.bin的尾缀128字节覆盖程序2的数组:
5)运行程序1和程序2,计算程序1和程序2的哈希值:
运行程序1和程序2,发现程序1和程序2的输出结果不同:说明程序1和程序2是不同的程序。同时这两个程序的md5哈希值是相同的。这就说明我们构造哈希值相同但内容不同的两个可执行文件,所以实验成功。
1)编译构造的代码并命名为1。将1复制命名为2。我们的目的是程序1和程序2行为虽不同,但它们的哈希值是一样的。
代码如下:
#include <stdio.h> unsigned char X[200] = { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }; unsigned char Y[200] = { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 }; main() { if (!strcmp(X, Y)) printf("run benign code"); else printf("run malicious code"); return; }2)bless打开程序1,找出数组的位置:
可以看出,数组的起始位置是0x00001040。前面有0x1040字节,正好是0x40的倍数,所以我们可以用前0x1040字节当前缀。
3)将程序1的前0x1040字节作为prefix,用md5collgen生成两哈希值相同的文件out1.bin,out2.bin:
4)用out1.bin的尾缀128字节覆盖程序1的数组X、数组Y和程序2的数组Y,用out2.bin的尾缀128字节覆盖程序2的数组X:
5)运行程序1和程序2,计算程序1和程序2的哈希值:
运行程序1时会执行正常代码,而运行程序2时会执行恶意代码,且这两个程序的md5哈希值相同。这就说明我们构造了行为不同但哈希值相同的两个程序,所以实验成功。