├── LICENSE.txt
├── Makefile
├── ModularMath.cs
├── MyUInt256.cs
├── PRNGs
├── PrngBase.cs
├── PrngBsdLibc.cs
├── PrngBsdLibcOld.cs
├── PrngDotNet.cs
├── PrngDotNetBase.cs
├── PrngDotNetMod.cs
├── PrngGlibc3.cs
├── PrngJava.cs
├── PrngLcgBase.cs
├── PrngLehmerBase.cs
├── PrngMssql.cs
├── PrngMsvcrt.cs
├── PrngMsvcrtBase.cs
├── PrngMsvcrtMul.cs
├── PrngMysql.cs
├── PrngPureBasic.cs
├── PrngV8.cs
└── PrngVbscript.cs
├── Prangster.csproj
├── PrangsterApp.cs
├── Properties
└── AssemblyInfo.cs
└── README.txt
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
2 | For updates, please visit .
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 | 1. Redistributions of source code must retain the above copyright
7 | notice, this list of conditions and the following disclaimer.
8 | 2. Redistributions in binary form must reproduce the above copyright
9 | notice, this list of conditions and the following disclaimer in the
10 | documentation and/or other materials provided with the distribution.
11 | 3. All advertising materials mentioning features or use of this software
12 | must display the following acknowledgement:
13 | This product includes software developed by Cylance, Inc.
14 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
15 | may be used to endorse or promote products derived from this software
16 | without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
19 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
29 |
30 |
31 |
32 | Portions of this software are based on FreeBSD rand.c, which bears the following copyright notice and conditions:
33 |
34 | Copyright (c) 1990, 1993
35 | The Regents of the University of California. All rights reserved.
36 |
37 | Redistribution and use in source and binary forms, with or without
38 | modification, are permitted provided that the following conditions
39 | are met:
40 | 1. Redistributions of source code must retain the above copyright
41 | notice, this list of conditions and the following disclaimer.
42 | 2. Redistributions in binary form must reproduce the above copyright
43 | notice, this list of conditions and the following disclaimer in the
44 | documentation and/or other materials provided with the distribution.
45 | 4. Neither the name of the University nor the names of its contributors
46 | may be used to endorse or promote products derived from this software
47 | without specific prior written permission.
48 |
49 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 | SUCH DAMAGE.
60 |
61 |
62 |
63 |
64 | Portions of this software are based on Microsoft SSCLI/Rotor random.cs (modified 06/14/2013), which is subject to the following copyright notice and license:
65 |
66 | Copyright (c) Microsoft Corporation. All rights reserved.
67 |
68 | MICROSOFT SHARED SOURCE CLI, C#, AND JSCRIPT LICENSE
69 |
70 | This License governs use of the accompanying Software, and your use of
71 | the Software constitutes acceptance of this license.
72 |
73 | You may use this Software for any non-commercial purpose, subject to
74 | the restrictions in this license. Some purposes which can be
75 | non-commercial are teaching, academic research, and personal
76 | experimentation. You may also distribute this Software with books or
77 | other teaching materials, or publish the Software on websites, that
78 | are intended to teach the use of the Software.
79 |
80 | You may not use or distribute this Software or any derivative works in
81 | any form for commercial purposes. Examples of commercial purposes
82 | would be running business operations, licensing, leasing, or selling
83 | the Software, or distributing the Software for use with commercial
84 | products.
85 |
86 | You may modify this Software and distribute the modified Software for
87 | non-commercial purposes, however, you may not grant rights to the
88 | Software or derivative works that are broader than those provided by
89 | this License. For example, you may not distribute modifications of
90 | the Software under terms that would permit commercial use, or under
91 | terms that purport to require the Software or derivative works to be
92 | sublicensed to others.
93 |
94 | You may use any information in intangible form that you remember after
95 | accessing the Software. However, this right does not grant you a
96 | license to any of Microsoft's copyrights or patents for anything you
97 | might create using such information.
98 |
99 | In return, we simply require that you agree:
100 |
101 | 1. Not to remove any copyright or other notices from the Software.
102 |
103 | 2. That if you distribute the Software in source or object form,
104 | you will include a verbatim copy of this license.
105 |
106 | 3. That if you distribute derivative works of the Software in
107 | source code form you do so only under a license that
108 | includes all of the provisions of this License, and if you
109 | distribute derivative works of the Software solely in object
110 | form you do so only under a license that complies with this
111 | License.
112 |
113 | 4. That if you have modified the Software or created derivative
114 | works, and distribute such modifications or derivative
115 | works, you will cause the modified files to carry prominent
116 | notices so that recipients know that they are not receiving
117 | the original Software. Such notices must state: (i) that
118 | you have changed the Software; and (ii) the date of any
119 | changes.
120 |
121 | 5. THAT THE SOFTWARE COMES "AS IS", WITH NO WARRANTIES. THIS
122 | MEANS NO EXPRESS, IMPLIED OR STATUTORY WARRANTY, INCLUDING
123 | WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY OR FITNESS
124 | FOR A PARTICULAR PURPOSE OR ANY WARRANTY OF TITLE OR
125 | NON-INFRINGEMENT. ALSO, YOU MUST PASS THIS DISCLAIMER ON
126 | WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.
127 |
128 | 6. THAT MICROSOFT WILL NOT BE LIABLE FOR ANY DAMAGES RELATED TO
129 | THE SOFTWARE OR THIS LICENSE, INCLUDING DIRECT, INDIRECT,
130 | SPECIAL, CONSEQUENTIAL OR INCIDENTAL DAMAGES, TO THE MAXIMUM
131 | EXTENT THE LAW PERMITS, NO MATTER WHAT LEGAL THEORY IT IS
132 | BASED ON. ALSO, YOU MUST PASS THIS LIMITATION OF LIABILITY
133 | ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE
134 | WORKS.
135 |
136 | 7. That if you sue anyone over patents that you think may apply
137 | to the Software or anyone's use of the Software, your
138 | license to the Software ends automatically.
139 |
140 | 8. That your rights under the License end automatically if you
141 | breach it in any way.
142 |
143 | 9. Microsoft reserves all rights not expressly granted to you in
144 | this license.
145 |
146 |
147 |
148 |
149 | Portions of this software are based on GNU C Library (glibc) random_r.cs, which bears the following copyright notices and conditions:
150 |
151 | Copyright (C) 1995, 2005, 2009 Free Software Foundation
152 |
153 | The GNU C Library is free software; you can redistribute it and/or
154 | modify it under the terms of the GNU Lesser General Public
155 | License as published by the Free Software Foundation; either
156 | version 2.1 of the License, or (at your option) any later version.
157 |
158 | The GNU C Library is distributed in the hope that it will be useful,
159 | but WITHOUT ANY WARRANTY; without even the implied warranty of
160 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
161 | Lesser General Public License for more details.
162 |
163 | You should have received a copy of the GNU Lesser General Public
164 | License along with the GNU C Library; if not, see
165 | .
166 |
167 |
168 | Copyright (C) 1983 Regents of the University of California.
169 | All rights reserved.
170 |
171 | Redistribution and use in source and binary forms, with or without
172 | modification, are permitted provided that the following conditions
173 | are met:
174 |
175 | 1. Redistributions of source code must retain the above copyright
176 | notice, this list of conditions and the following disclaimer.
177 | 2. Redistributions in binary form must reproduce the above copyright
178 | notice, this list of conditions and the following disclaimer in the
179 | documentation and/or other materials provided with the distribution.
180 | 4. Neither the name of the University nor the names of its contributors
181 | may be used to endorse or promote products derived from this software
182 | without specific prior written permission.
183 |
184 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
185 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
186 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
187 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
188 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
189 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
190 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
191 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
192 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
193 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
194 | SUCH DAMAGE.
195 |
196 |
197 |
198 |
199 | Portions of this software are based on Oracle JDK 7 Random.java, which bears the following copyright notice:
200 |
201 | Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
202 |
203 |
204 |
205 |
206 | Portions of this software are based on Microsoft Visual Studio 2012 CRT rand.c, which bears the following copyright notice:
207 |
208 | Copyright (c) 2006 Microsoft Corporation. All rights reserved.
209 |
210 |
211 |
212 |
213 | Portions of this software are based on MySQL sql/item_func.cc and mysys_ssl/my_rnd.cc, which bear the following copyright notice and license:
214 |
215 | Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
216 |
217 | This program is free software; you can redistribute it and/or modify
218 | it under the terms of the GNU General Public License as published by
219 | the Free Software Foundation; version 2 of the License.
220 |
221 | This program is distributed in the hope that it will be useful,
222 | but WITHOUT ANY WARRANTY; without even the implied warranty of
223 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
224 | GNU General Public License for more details.
225 |
226 | You should have received a copy of the GNU General Public License
227 | along with this program; if not, write to the Free Software
228 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
229 |
230 |
231 |
232 |
233 | Portions of this software are based on Google V8 v8.cc, which is subject to the following copyright and conditions:
234 |
235 | Copyright 2012 the V8 project authors. All rights reserved.
236 | Redistribution and use in source and binary forms, with or without
237 | modification, are permitted provided that the following conditions are
238 | met:
239 |
240 | * Redistributions of source code must retain the above copyright
241 | notice, this list of conditions and the following disclaimer.
242 | * Redistributions in binary form must reproduce the above
243 | copyright notice, this list of conditions and the following
244 | disclaimer in the documentation and/or other materials provided
245 | with the distribution.
246 | * Neither the name of Google Inc. nor the names of its
247 | contributors may be used to endorse or promote products derived
248 | from this software without specific prior written permission.
249 |
250 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
251 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
252 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
253 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
254 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
255 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
256 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
257 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
258 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
260 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
261 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 |
2 | all: release
3 |
4 | release: bin/Release/Prangster.exe
5 |
6 | debug: bin/Debug/Prangster.exe
7 |
8 | bin/Release/Prangster.exe:
9 | xbuild /p:Configuration=Release Prangster.csproj
10 |
11 | bin/Debug/Prangster.exe:
12 | xbuild /p:Configuration=Debug Prangster.csproj
13 |
14 | clean:
15 | $(RM) -r bin
16 |
--------------------------------------------------------------------------------
/ModularMath.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | using System;
32 |
33 | namespace Cylance.Research.Prangster
34 | {
35 |
36 | public static class ModularMath
37 | {
38 |
39 | ///
40 | /// Computes the greatest common divisor (GCD) of and ,
41 | /// as well as the multiplicative inverse of modulo .
42 | ///
43 | /// A positive integer less than .
44 | /// A positive integer greater than .
45 | /// Receives the multiplicative inverse of modulo
46 | /// if and are coprime, or 0 otherwise.
47 | /// The greatest common divisor of and .
48 | public static ulong ExtendedEuclidean(long a, long b, out ulong mulInverse)
49 | {
50 | if (a <= 0 || a >= b)
51 | throw new ArgumentOutOfRangeException("a must be a positive integer less than b");
52 |
53 | long r0 = b, r1 = a; // ordered this way because b > a
54 | long q, r;
55 | long x0 = 0, x1 = 1; // x is a's coefficient; we don't maintain b's coefficient
56 | long x = 1; // return multiplicative inverse of 1 if loop breaks before x is assigned and if GCD (q) is 1
57 |
58 | for (; ; )
59 | {
60 | unchecked // we know r0 and r1 are non-negative, even though they're signed types, so perform unsigned division for performance
61 | {
62 | r = (long)((ulong)r0 % (ulong)r1);
63 | if (r == 0) break; // break before overwriting previous value of q
64 |
65 | q = (long)((ulong)r0 / (ulong)r1);
66 | }
67 |
68 | x = (x0 - q * x1);
69 |
70 | r0 = r1; r1 = r;
71 | x0 = x1; x1 = x;
72 | }
73 |
74 | if (x < 0) x += b;
75 | mulInverse = (ulong)(r1 == 1 ? x : 0);
76 |
77 | return (ulong)r1;
78 | } //ModularMath.ExtendedEuclidean(long,long,out ulong)
79 |
80 | ///
81 | /// Computes the greatest common divisor (GCD) of and ,
82 | /// as well as the multiplicative inverse of modulo .
83 | ///
84 | /// A positive integer less than .
85 | /// A positive integer greater than .
86 | /// Receives the multiplicative inverse of modulo
87 | /// if and are coprime, or null otherwise.
88 | /// The greatest common divisor of and .
89 | public static MyUInt256 ExtendedEuclidean(MyUInt256 a, MyUInt256 b, out MyUInt256 mulInverse)
90 | {
91 | if (a.IsZero() || a.Compare(b) >= 0)
92 | throw new ArgumentOutOfRangeException("a must be a positive integer less than b");
93 |
94 | MyUInt256 r0 = new MyUInt256(b), r1 = new MyUInt256(a); // ordered this way because b > a
95 | MyUInt256 q = new MyUInt256(), r = new MyUInt256();
96 | MyUInt256 x0 = new MyUInt256(0), x1 = new MyUInt256(1); // x is a's coefficient; we don't maintain b's coefficient
97 | MyUInt256 x = new MyUInt256(1); // return multiplicative inverse of 1 if loop breaks before x is assigned and if GCD (q) is 1
98 | MyUInt256 tmp = new MyUInt256();
99 |
100 | for (; ; )
101 | {
102 | r.Set(r0); // r = r0 % r1
103 | r.Modulo(r1);
104 | if (r.IsZero()) break; // break before overwriting previous value of q
105 |
106 | q.Set(r0); // q = r0 / r1
107 | q.Divide(r1);
108 |
109 | x.Set(x0); // x = x0 - q * x1
110 | tmp.Set(q);
111 | tmp.Multiply(x1);
112 | x.Subtract(tmp);
113 |
114 | r0.Set(r1); r1.Set(r);
115 | x0.Set(x1); x1.Set(x);
116 | }
117 |
118 | if (x.IsMsbSet()) x.Add(b);
119 | mulInverse = (r1.Compare(1) == 0 ? x : null);
120 |
121 | return r1;
122 | } //ModularMath.ExtendedEuclidean(MyUInt256,MyUInt256,out MyUInt256)
123 |
124 | ///
125 | /// Computes the multiplicative inverse of modulo .
126 | ///
127 | /// A non-negative integer less than .
128 | /// A non-negative integer defining the integer ring in which resides.
129 | /// The multiplicative inverse of modulo ,
130 | /// or 0 if no such multiplicative inverse exists.
131 | public static ulong MultiplicativeInverse(long a, long modulus)
132 | {
133 | if (a < 0 || a >= modulus)
134 | throw new ArgumentOutOfRangeException("a must be a non-negative integer less than modulus");
135 |
136 | if (a == 0)
137 | return 0;
138 |
139 | ulong mi;
140 | ExtendedEuclidean(a, modulus, out mi);
141 |
142 | return mi;
143 | } //ModularMath.MultiplicativeInverse(long,long)
144 |
145 | ///
146 | /// Computes the multiplicative inverse of modulo .
147 | ///
148 | /// A non-negative integer less than .
149 | /// A non-negative integer defining the integer ring in which resides.
150 | /// The multiplicative inverse of modulo ,
151 | /// or null if no such multiplicative inverse exists.
152 | public static MyUInt256 MultiplicativeInverse(MyUInt256 a, MyUInt256 modulus)
153 | {
154 | if (a.IsMsbSet() || a.Compare(modulus) >= 0)
155 | throw new ArgumentOutOfRangeException("a must be a non-negative integer less than modulus");
156 |
157 | if (a.IsZero())
158 | return null;
159 |
160 | MyUInt256 mi;
161 | ExtendedEuclidean(a, modulus, out mi);
162 |
163 | return mi;
164 | } //ModularMath.MultiplicativeInverse(MyUInt256,MyUInt256)
165 |
166 | } //class ModularMath
167 |
168 | } //namespace Cylance.Research.Prangster
169 |
--------------------------------------------------------------------------------
/PRNGs/PrngBase.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | using System;
32 |
33 | namespace Cylance.Research.Prangster
34 | {
35 |
36 | ///
37 | /// Base class from which pseudorandom number generator (PRNG) implementations are derived.
38 | ///
39 | public abstract class PrngBase
40 | {
41 |
42 | ///
43 | /// Represents the lowest 64-bit seed value that this PRNG will accept during initialization.
44 | ///
45 | public abstract ulong MinimumSeed
46 | {
47 | get;
48 | }
49 |
50 | ///
51 | /// Represents the largest 64-bit seed value that this PRNG will accept during initialization.
52 | ///
53 | public abstract ulong MaximumSeed
54 | {
55 | get;
56 | }
57 |
58 | ///
59 | /// When overridden in a derived class, initializes the internal state of the PRNG using the supplied seed.
60 | ///
61 | /// An integer between and with which to seed the PRNG.
62 | public abstract void Seed(ulong seed);
63 |
64 | ///
65 | /// When overridden in a derived class, generates a pseudorandom integer and advances the internal state of the PRNG.
66 | ///
67 | /// The next pseudorandom integer generated by the PRNG.
68 | public abstract ulong Next();
69 |
70 | ///
71 | /// Generates a pseudorandom integer in the range [0..) and advances the internal state of the PRNG.
72 | ///
73 | /// The lowest positive integer greater than the maximum desired value.
74 | /// The next pseudorandom integer generated by the PRNG modulo .
75 | ///
76 | /// This method should be used whenever appropriate instead of , as some
77 | /// PRNGs offer a specialized implementation for generating a pseudorandom number within a range.
78 | ///
79 | public virtual ulong Next(ulong limit)
80 | {
81 | return (this.Next() % limit);
82 | }
83 |
84 | ///
85 | /// When overridden in a derived class, gets a value indicating whether the PRNG supports reversing.
86 | ///
87 | public virtual bool CanReverse
88 | {
89 | get
90 | {
91 | return false;
92 | }
93 | }
94 |
95 | ///
96 | /// When overridden in a derived class, generates a pseudorandom integer and reverses the internal state of the PRNG, if the PRNG supports reversing.
97 | ///
98 | /// The previous pseudorandom integer generated by the PRNG.
99 | /// The PRNG does not support reversing.
100 | public virtual ulong Previous()
101 | {
102 | throw new NotImplementedException("This PRNG does not support reversing.");
103 | }
104 |
105 | ///
106 | /// Generates a pseudorandom integer in the range [0..) and reverses the internal state of the PRNG, if the PRNG supports reversing.
107 | ///
108 | /// The lowest positive integer greater than the maximum desired value.
109 | /// The previous pseudorandom integer generated by the PRNG modulo .
110 | /// The PRNG does not support reversing.
111 | public virtual ulong Previous(ulong limit)
112 | {
113 | return (this.Previous() % limit);
114 | }
115 |
116 | ///
117 | /// When overridden in a derived class, gets a value indicating whether the PRNG supports seeking.
118 | ///
119 | public virtual bool CanSeek
120 | {
121 | get
122 | {
123 | return false;
124 | }
125 | }
126 |
127 | ///
128 | /// When overridden in a derived class, advances the PRNG by states.
129 | ///
130 | /// The number of states to skip, starting with the current state.
131 | public virtual void SeekAhead(ulong offset)
132 | {
133 | throw new NotImplementedException("This PRNG does not support seeking.");
134 | }
135 |
136 | ///
137 | /// When overridden in a derived class, reverses the PRNG by states.
138 | ///
139 | /// The number of states to skip, starting with the current state.
140 | public virtual void SeekBack(ulong offset)
141 | {
142 | throw new NotImplementedException("This PRNG does not support seeking.");
143 | }
144 |
145 | ///
146 | /// When overridden in a derived class, gets a value indicating whether the PRNG supports seeking from one seed to another.
147 | ///
148 | public virtual bool CanSeekSeed
149 | {
150 | get
151 | {
152 | return false;
153 | }
154 | }
155 |
156 | ///
157 | /// When overridden in a derived class, computes the seed representing the 'th state after the state corresponding to .
158 | ///
159 | /// The seed used to the determine the initial state relative to which to seek.
160 | /// The number of states to skip.
161 | public virtual ulong SeekSeedAhead(ulong seed, ulong offset)
162 | {
163 | throw new NotImplementedException("This PRNG does not support seed seeking.");
164 | }
165 |
166 | ///
167 | /// When overridden in a derived class, computes the seed representing the 'th state preceding the state corresponding to .
168 | ///
169 | /// The seed used to the determine the initial state relative to which to seek.
170 | /// The number of states to skip.
171 | public virtual ulong SeekSeedBack(ulong seed, ulong offset)
172 | {
173 | throw new NotImplementedException("This PRNG does not support seed seeking.");
174 | }
175 |
176 | ///
177 | /// Discovers the seed or seeds that produce the supplied PRNG output sequence.
178 | ///
179 | /// A sequence containing one or more PRNG output values (modulo )
180 | /// and any number of instances of .
181 | /// The lowest positive integer greater than the maximum allowed output value, or 0 if no limit was imposed on the output.
182 | /// A number which will match any PRNG output value when encountered in .
183 | /// A method to invoke with seed discovery or progress notifications.
184 | /// The number of seeds to test between progress notifications, or 0 to not receive progress notifications.
185 | /// true if seed discovery completed (even if no seed was discovered), or false if the callback canceled discovery or an error occurred.
186 | /// If progress notifications are requested, will be invoked for a final progress notification event before true is returned.
187 | public virtual bool RecoverSeed(ulong[] output, ulong limit, ulong wildcard, RecoverSeedCallback callback, ulong progressInterval)
188 | {
189 | ulong seed = this.MinimumSeed;
190 | ulong maxseed = this.MaximumSeed;
191 |
192 | if (seed > maxseed)
193 | return false;
194 |
195 | return
196 | RecoverSeed(
197 | seed, maxseed, 1,
198 | output, limit, wildcard,
199 | callback, progressInterval);
200 | }
201 |
202 | ///
203 | /// Discovers the seed or seeds that produce the supplied PRNG output sequence.
204 | ///
205 | /// The first seed value to test.
206 | /// The last seed value that could be tested.
207 | /// A positive integer specifying the interval at which to test seeds.
208 | /// A value of 1 tests each seed serially, a value of 2 tests every other seed, and so on.
209 | /// A sequence containing one or more PRNG output values (modulo )
210 | /// and any number of instances of .
211 | /// The lowest positive integer greater than the maximum allowed output value, or 0 if no limit was imposed on the output.
212 | /// A number which will match any PRNG output value when encountered in .
213 | /// A method to invoke with seed discovery or progress notifications.
214 | /// The number of seeds to test between progress notifications, or 0 to not receive progress notifications.
215 | /// true if seed discovery completed (even if no seed was discovered), or false if the callback canceled discovery or an error occurred.
216 | /// If progress notifications are requested, will be invoked for a final progress notification event before true is returned.
217 | protected virtual bool RecoverSeed(ulong seedStart, ulong seedEnd, ulong seedIncrement, ulong[] output, ulong limit, ulong wildcard, RecoverSeedCallback callback, ulong progressInterval)
218 | {
219 | if (seedStart > seedEnd || seedIncrement == 0)
220 | return false;
221 |
222 | if (callback == null)
223 | progressInterval = 0;
224 |
225 | ulong totalcount = unchecked((seedEnd - seedStart) / seedIncrement + 1); // count = 0 (2**64) if minimum seed = 0, maxseed = 2**64 - 1, and seedIncrement = 1
226 | ulong totalcountdown = totalcount;
227 |
228 | RecoverSeedEventArgs args = new RecoverSeedEventArgs();
229 |
230 | ulong seed = seedStart;
231 |
232 | do
233 | {
234 | ulong countdown = ((totalcountdown < progressInterval || progressInterval == 0) ? totalcountdown : progressInterval);
235 | totalcountdown = unchecked(totalcountdown - countdown); // allow integer underflow so that 0 == 2**64
236 |
237 | do
238 | {
239 | this.Seed(seed);
240 |
241 | int i;
242 |
243 | if (limit != 0)
244 | {
245 | for (i = 0; i < output.Length; i++)
246 | {
247 | if (this.Next(limit) != output[i] && output[i] != wildcard)
248 | break;
249 | }
250 | }
251 | else
252 | {
253 | for (i = 0; i < output.Length; i++)
254 | {
255 | if (this.Next() != output[i] && output[i] != wildcard)
256 | break;
257 | }
258 | }
259 |
260 | if (i == output.Length) // invoke callback for seed discovery notification
261 | {
262 | args.EventType = RecoverSeedEventType.SeedDiscovered;
263 | args.Seed = seed;
264 | args.CurrentAttempts = (totalcount - totalcountdown - countdown);
265 | args.TotalAttempts = totalcount;
266 |
267 | callback(args);
268 |
269 | if (args.Cancel)
270 | return false;
271 | }
272 |
273 | seed += seedIncrement;
274 | }
275 | while (unchecked(--countdown) != 0); // allow integer underflow here, so that 0 is equivalent to 2**64
276 |
277 | if (progressInterval != 0) // invoke callback for progress notification
278 | {
279 | args.EventType = RecoverSeedEventType.ProgressNotification;
280 | args.Seed = seed;
281 | args.CurrentAttempts = (totalcount - totalcountdown - countdown);
282 | args.TotalAttempts = totalcount;
283 |
284 | callback(args);
285 |
286 | if (args.Cancel)
287 | return false;
288 | }
289 | }
290 | while (totalcountdown != 0);
291 |
292 | return true;
293 | } //PrngBase.RecoverSeed(ulong,ulong,ulong,ulong[],ulong,ulong,RecoverSeedCallback,ulong)
294 |
295 | } //class PrngBase
296 |
297 | public delegate void RecoverSeedCallback(RecoverSeedEventArgs args);
298 |
299 | public class RecoverSeedEventArgs
300 | {
301 | public RecoverSeedEventType EventType;
302 | public bool Cancel;
303 | public ulong Seed;
304 | public ulong CurrentAttempts;
305 | public ulong TotalAttempts;
306 | }
307 |
308 | public enum RecoverSeedEventType
309 | {
310 | SeedDiscovered,
311 | ProgressNotification
312 | }
313 |
314 | } //namespace Cylance.Research.Prangster
315 |
--------------------------------------------------------------------------------
/PRNGs/PrngBsdLibc.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | // Based on FreeBSD rand.c, which bears the following copyright notice and conditions:
32 | /*-
33 | * Copyright (c) 1990, 1993
34 | * The Regents of the University of California. All rights reserved.
35 | *
36 | * Redistribution and use in source and binary forms, with or without
37 | * modification, are permitted provided that the following conditions
38 | * are met:
39 | * 1. Redistributions of source code must retain the above copyright
40 | * notice, this list of conditions and the following disclaimer.
41 | * 2. Redistributions in binary form must reproduce the above copyright
42 | * notice, this list of conditions and the following disclaimer in the
43 | * documentation and/or other materials provided with the distribution.
44 | * 4. Neither the name of the University nor the names of its contributors
45 | * may be used to endorse or promote products derived from this software
46 | * without specific prior written permission.
47 | *
48 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 | * SUCH DAMAGE.
59 | */
60 |
61 | using System;
62 |
63 | namespace Cylance.Research.Prangster
64 | {
65 |
66 | public sealed class PrngBsdLibc : PrngLehmerBase
67 | {
68 |
69 | private uint _State;
70 |
71 | private const uint _Multiplier = 16807;
72 | private const uint _Modulus = 0x7FFFFFFF;
73 |
74 | private const uint _MultiplierInverse = 1407677000; // multiplicative inverse of _Multiplier modulo _Modulus
75 |
76 | public PrngBsdLibc()
77 | {
78 | }
79 |
80 | public PrngBsdLibc(ulong seed)
81 | : this()
82 | {
83 | this.Seed(seed);
84 | }
85 |
86 | public override ulong MaximumSeed
87 | {
88 | get
89 | {
90 | return (_Modulus - 1);
91 | }
92 | }
93 |
94 | public override ulong Multiplier
95 | {
96 | get
97 | {
98 | return _Multiplier;
99 | }
100 | }
101 |
102 | public override ulong Modulus
103 | {
104 | get
105 | {
106 | return _Modulus;
107 | }
108 | }
109 |
110 | public override ulong DiscardDivisor
111 | {
112 | get
113 | {
114 | return 1;
115 | }
116 | }
117 |
118 | public override void Seed(ulong seed)
119 | {
120 | //if (seed < 1 || seed > (_Modulus - 1))
121 | // throw new ArgumentOutOfRangeException("seed must be a positive 32-bit integer");
122 |
123 | unchecked // disable arithmetic checks for performance
124 | {
125 | this._State = (uint)seed % _Modulus;
126 | }
127 | }
128 |
129 | public override ulong Next()
130 | {
131 | unchecked // disable arithmetic checks for performance
132 | {
133 | return (this._State = (uint)(((ulong)this._State * (ulong)_Multiplier) % (ulong)_Modulus));
134 | }
135 | }
136 |
137 | public override ulong Next(ulong limit)
138 | {
139 | unchecked // disable arithmetic checks for performance
140 | {
141 | uint next = (uint)this.Next();
142 |
143 | if (limit != 0 && limit < _Modulus)
144 | next %= (uint)limit;
145 |
146 | return next;
147 | }
148 | }
149 |
150 | public override bool CanReverse
151 | {
152 | get
153 | {
154 | return true;
155 | }
156 | }
157 |
158 | private static uint PreviousState(uint state)
159 | {
160 | return unchecked((uint)(((ulong)state * _MultiplierInverse) % _Modulus));
161 | }
162 |
163 | public override ulong Previous()
164 | {
165 | uint current = this._State;
166 | this._State = PreviousState(current);
167 |
168 | return current;
169 | }
170 |
171 | public override ulong Previous(ulong limit)
172 | {
173 | unchecked // disable arithmetic checks for performance
174 | {
175 | uint current = (uint)this.Previous();
176 |
177 | if (limit != 0 && limit < _Modulus)
178 | current %= (uint)limit;
179 |
180 | return current;
181 | }
182 | }
183 |
184 | public override bool CanSeek
185 | {
186 | get
187 | {
188 | return true;
189 | }
190 | }
191 |
192 | public override void SeekAhead(ulong offset)
193 | {
194 | this._State = unchecked((uint)SeekState(this._State, offset, _Multiplier, _Modulus));
195 | }
196 |
197 | public override void SeekBack(ulong offset)
198 | {
199 | this._State = unchecked((uint)SeekState(this._State, offset, _MultiplierInverse, _Modulus));
200 | }
201 |
202 | public override ulong SeekSeedAhead(ulong seed, ulong offset)
203 | {
204 | return SeekState(seed, offset, _Multiplier, 0, _Modulus);
205 | }
206 |
207 | public override ulong SeekSeedBack(ulong seed, ulong offset)
208 | {
209 | return SeekState(seed, offset, _MultiplierInverse, 0, _Modulus);
210 | }
211 |
212 | protected override bool RecoverSeed(ulong seedStart, ulong seedEnd, ulong seedIncrement, ulong[] output, ulong limit, ulong wildcard, RecoverSeedCallback callback, ulong progressInterval)
213 | {
214 | if (output.Length < 2 || output[0] >= limit || output[0] == wildcard || limit == 0 || limit > _Modulus || seedIncrement != 1)
215 | return base.RecoverSeed(seedStart, seedEnd, seedIncrement, output, limit, wildcard, callback, progressInterval);
216 |
217 | if (seedStart < this.MinimumSeed)
218 | seedStart = this.MinimumSeed;
219 |
220 | if (seedEnd > this.MaximumSeed)
221 | seedEnd = this.MaximumSeed;
222 |
223 | if (seedStart > seedEnd)
224 | return false;
225 |
226 | this._OriginalCallback = callback;
227 |
228 | unchecked // disable arithmetic checks for performance
229 | {
230 | // operate on output suffix of length N - 1 so we can fix bottom portion of seed to output[0]
231 | ulong[] suboutput = new ulong[output.Length - 1];
232 | Array.Copy(output, 1, suboutput, 0, output.Length - 1);
233 |
234 | uint ofs = unchecked(((uint)limit + (uint)output[0] - ((uint)seedStart % (uint)limit)) % (uint)limit);
235 | if (ofs != 0) seedStart += ofs; // advance 'seedStart' to first value in range that produces output[0] modulo 'limit'
236 |
237 | // pass 'limit' instead of 'seedIncrement' (1), skipping all seeds that don't (modulo 'limit') equal output[0]
238 | return base.RecoverSeed(seedStart, seedEnd, limit, suboutput, limit, wildcard, this.RecoverSeedCallback, progressInterval);
239 | } //unchecked
240 | } //PrngBsdLibc.RecoverSeed
241 |
242 | private RecoverSeedCallback _OriginalCallback;
243 |
244 | private void RecoverSeedCallback(RecoverSeedEventArgs args)
245 | {
246 | if (args.EventType == RecoverSeedEventType.SeedDiscovered)
247 | args.Seed = PreviousState(unchecked((uint)args.Seed));
248 |
249 | this._OriginalCallback(args);
250 | }
251 |
252 | } //class PrngBsdLibc
253 |
254 | } //namespace Cylance.Research.Prangster
255 |
--------------------------------------------------------------------------------
/PRNGs/PrngBsdLibcOld.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | // Based on FreeBSD rand.c, which bears the following copyright notice and conditions:
32 | /*-
33 | * Copyright (c) 1990, 1993
34 | * The Regents of the University of California. All rights reserved.
35 | *
36 | * Redistribution and use in source and binary forms, with or without
37 | * modification, are permitted provided that the following conditions
38 | * are met:
39 | * 1. Redistributions of source code must retain the above copyright
40 | * notice, this list of conditions and the following disclaimer.
41 | * 2. Redistributions in binary form must reproduce the above copyright
42 | * notice, this list of conditions and the following disclaimer in the
43 | * documentation and/or other materials provided with the distribution.
44 | * 4. Neither the name of the University nor the names of its contributors
45 | * may be used to endorse or promote products derived from this software
46 | * without specific prior written permission.
47 | *
48 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 | * SUCH DAMAGE.
59 | */
60 |
61 | using System;
62 |
63 | namespace Cylance.Research.Prangster
64 | {
65 |
66 | public sealed class PrngBsdLibcOld : PrngLcgBase
67 | {
68 |
69 | private uint _State;
70 |
71 | private const uint _Multiplier = 1103515245;
72 | private const uint _Increment = 12345;
73 | private const uint _Modulus = 0x80000000; // & 0x7FFFFFFF (31 bits)
74 |
75 | private const uint _MultiplierInverse = 1857678181; // multiplicative inverse of _Multiplier modulo _Modulus
76 | private const uint _IncrementInverseMulInv = 2088216195; // additive inverse of _Increment modulo _Modulus, multiplied by _MultiplierInverse
77 |
78 | public PrngBsdLibcOld()
79 | {
80 | }
81 |
82 | public PrngBsdLibcOld(ulong seed)
83 | : this()
84 | {
85 | this.Seed(seed);
86 | }
87 |
88 | public override ulong MinimumSeed
89 | {
90 | get
91 | {
92 | return 0;
93 | }
94 | }
95 |
96 | public override ulong MaximumSeed
97 | {
98 | get
99 | {
100 | return (_Modulus - 1);
101 | }
102 | }
103 |
104 | public override ulong Multiplier
105 | {
106 | get
107 | {
108 | return _Multiplier;
109 | }
110 | }
111 |
112 | public override ulong Increment
113 | {
114 | get
115 | {
116 | return _Increment;
117 | }
118 | }
119 |
120 | public override ulong Modulus
121 | {
122 | get
123 | {
124 | return _Modulus;
125 | }
126 | }
127 |
128 | public override ulong DiscardDivisor
129 | {
130 | get
131 | {
132 | return 1;
133 | }
134 | }
135 |
136 | public override void Seed(ulong seed)
137 | {
138 | //if (seed < 0 || seed > (_Modulus - 1))
139 | // throw new ArgumentOutOfRangeException("seed must be a 31-bit integer");
140 |
141 | unchecked // disable arithmetic checks for performance
142 | {
143 | this._State = ((uint)seed & 0x7FFFFFFF);
144 | }
145 | }
146 |
147 | public override ulong Next()
148 | {
149 | unchecked // disable arithmetic checks for performance
150 | {
151 | uint next = (this._State * _Multiplier) + _Increment;
152 | this._State = next;
153 | return (next & 0x7FFFFFFF);
154 | }
155 | }
156 |
157 | public override ulong Next(ulong limit)
158 | {
159 | unchecked // disable arithmetic checks for performance
160 | {
161 | uint next = (this._State * _Multiplier) + _Increment;
162 | this._State = next;
163 |
164 | next = (next & 0x7FFFFFFF);
165 |
166 | if (limit != 0 && limit <= 0x7FFFFFFF)
167 | next %= (uint)limit;
168 |
169 | return next;
170 | }
171 | }
172 |
173 | public override bool CanReverse
174 | {
175 | get
176 | {
177 | return true;
178 | }
179 | }
180 |
181 | private static uint PreviousState(uint seed)
182 | {
183 | unchecked // disable arithmetic checks for performance
184 | {
185 | uint diff = (seed - _Increment);
186 | return (diff * _MultiplierInverse) & 0x7FFFFFFF; // we can let multiplication overflow 32 bits because modulus is a power of two
187 | }
188 | }
189 |
190 | public override ulong Previous()
191 | {
192 | uint current = this._State;
193 | this._State = PreviousState(current);
194 |
195 | return (current & 0x7FFFFFFF);
196 | }
197 |
198 | public override ulong Previous(ulong limit)
199 | {
200 | unchecked // disable arithmetic checks for performance
201 | {
202 | uint current = (uint)this.Previous();
203 |
204 | if (limit != 0 && limit <= 0x7FFFFFFF)
205 | current %= (uint)limit;
206 |
207 | return current;
208 | }
209 | }
210 |
211 | public override bool CanSeek
212 | {
213 | get
214 | {
215 | return true;
216 | }
217 | }
218 |
219 | public override void SeekAhead(ulong offset)
220 | {
221 | this._State = unchecked((uint)SeekState(this._State, offset, _Multiplier, _Increment, _Modulus));
222 | }
223 |
224 | public override void SeekBack(ulong offset)
225 | {
226 | this._State = unchecked((uint)SeekState(this._State, offset, _MultiplierInverse, _IncrementInverseMulInv, _Modulus));
227 | }
228 |
229 | public override ulong SeekSeedAhead(ulong seed, ulong offset)
230 | {
231 | return unchecked((uint)SeekState(seed, offset, _Multiplier, _Increment, _Modulus));
232 | }
233 |
234 | public override ulong SeekSeedBack(ulong seed, ulong offset)
235 | {
236 | return unchecked((uint)SeekState(seed, offset, _MultiplierInverse, _IncrementInverseMulInv, _Modulus));
237 | }
238 |
239 | protected override bool RecoverSeed(ulong seedStart, ulong seedEnd, ulong seedIncrement, ulong[] output, ulong limit, ulong wildcard, RecoverSeedCallback callback, ulong progressInterval)
240 | {
241 | if (output.Length < 2 || output[0] >= limit || output[0] == wildcard || limit == 0 || limit > _Modulus || seedIncrement != 1)
242 | return base.RecoverSeed(seedStart, seedEnd, seedIncrement, output, limit, wildcard, callback, progressInterval);
243 |
244 | if (seedStart < this.MinimumSeed)
245 | seedStart = this.MinimumSeed;
246 |
247 | if (seedEnd > this.MaximumSeed)
248 | seedEnd = this.MaximumSeed;
249 |
250 | if (seedStart > seedEnd)
251 | return false;
252 |
253 | this._OriginalCallback = callback;
254 |
255 | unchecked // disable arithmetic checks for performance
256 | {
257 | // operate on output suffix of length N - 1 so we can fix bottom portion of seed to output[0]
258 | ulong[] suboutput = new ulong[output.Length - 1];
259 | Array.Copy(output, 1, suboutput, 0, output.Length - 1);
260 |
261 | uint ofs = unchecked(((uint)limit + (uint)output[0] - ((uint)seedStart % (uint)limit)) % (uint)limit);
262 | if (ofs != 0) seedStart += ofs; // advance 'seedStart' to first value in range that produces output[0] modulo 'limit'
263 |
264 | // pass 'limit' instead of 'seedIncrement' (1), skipping all seeds that don't (modulo 'limit') equal output[0]
265 | return base.RecoverSeed(seedStart, seedEnd, limit, suboutput, limit, wildcard, this.RecoverSeedCallback, progressInterval);
266 | } //unchecked
267 | } //PrngBsdLibc.RecoverSeed
268 |
269 | private RecoverSeedCallback _OriginalCallback;
270 |
271 | private void RecoverSeedCallback(RecoverSeedEventArgs args)
272 | {
273 | if (args.EventType == RecoverSeedEventType.SeedDiscovered)
274 | args.Seed = PreviousState(unchecked((uint)args.Seed));
275 |
276 | this._OriginalCallback(args);
277 | }
278 |
279 | } //class PrngBsdLibcOld
280 |
281 | } //namespace Cylance.Research.Prangster
282 |
--------------------------------------------------------------------------------
/PRNGs/PrngDotNet.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | using System;
32 |
33 | namespace Cylance.Research.Prangster
34 | {
35 |
36 | public sealed class PrngDotNet : PrngDotNetBase
37 | {
38 |
39 | public PrngDotNet()
40 | : base()
41 | {
42 | }
43 |
44 | public PrngDotNet(ulong seed)
45 | : base(seed)
46 | {
47 | }
48 |
49 | public override ulong Next(ulong limit) // Random.Next(int)
50 | {
51 | return unchecked((this.Next() * limit) / MBIG);
52 | }
53 |
54 | public override ulong Previous(ulong limit)
55 | {
56 | return unchecked((this.Previous() * limit) / MBIG);
57 | }
58 |
59 | } //class PrngDotNet
60 |
61 | } //namespace Cylance.Research.Prangster
62 |
--------------------------------------------------------------------------------
/PRNGs/PrngDotNetMod.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | using System;
32 |
33 | namespace Cylance.Research.Prangster
34 | {
35 |
36 | public sealed class PrngDotNetMod : PrngDotNetBase
37 | {
38 |
39 | public PrngDotNetMod()
40 | : base()
41 | {
42 | }
43 |
44 | public PrngDotNetMod(ulong seed)
45 | : base(seed)
46 | {
47 | }
48 |
49 | public override ulong Next(ulong limit)
50 | {
51 | ulong next = this.Next();
52 |
53 | if (limit != 0 && limit < MBIG)
54 | return unchecked(next % limit);
55 | else return next;
56 | }
57 |
58 | public override ulong Previous(ulong limit)
59 | {
60 | ulong prev = this.Next();
61 |
62 | if (limit != 0 && limit < MBIG)
63 | return unchecked(prev % limit);
64 | else return prev;
65 | }
66 |
67 | } //class PrngDotNetMod
68 |
69 | } //namespace Cylance.Research.Prangster
70 |
--------------------------------------------------------------------------------
/PRNGs/PrngGlibc3.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | // Based on GNU C Library (glibc) random_r.cs, which bears the following copyright notices and conditions:
32 | /*
33 | Copyright (C) 1995, 2005, 2009 Free Software Foundation
34 |
35 | The GNU C Library is free software; you can redistribute it and/or
36 | modify it under the terms of the GNU Lesser General Public
37 | License as published by the Free Software Foundation; either
38 | version 2.1 of the License, or (at your option) any later version.
39 |
40 | The GNU C Library is distributed in the hope that it will be useful,
41 | but WITHOUT ANY WARRANTY; without even the implied warranty of
42 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43 | Lesser General Public License for more details.
44 |
45 | You should have received a copy of the GNU Lesser General Public
46 | License along with the GNU C Library; if not, see
47 | . */
48 |
49 | /*
50 | Copyright (C) 1983 Regents of the University of California.
51 | All rights reserved.
52 |
53 | Redistribution and use in source and binary forms, with or without
54 | modification, are permitted provided that the following conditions
55 | are met:
56 |
57 | 1. Redistributions of source code must retain the above copyright
58 | notice, this list of conditions and the following disclaimer.
59 | 2. Redistributions in binary form must reproduce the above copyright
60 | notice, this list of conditions and the following disclaimer in the
61 | documentation and/or other materials provided with the distribution.
62 | 4. Neither the name of the University nor the names of its contributors
63 | may be used to endorse or promote products derived from this software
64 | without specific prior written permission.
65 |
66 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
67 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
68 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
69 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
70 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
71 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
72 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
73 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
74 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
75 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
76 | SUCH DAMAGE.
77 | */
78 |
79 | using System;
80 |
81 | namespace Cylance.Research.Prangster
82 | {
83 |
84 | public sealed class PrngGlibc3 : PrngBase
85 | {
86 |
87 | private readonly uint[] _State = new uint[31];
88 | private int _fptr;
89 | private int _rptr;
90 |
91 | private readonly uint[,] _NextMatrix;
92 | private readonly uint[,] _PreviousMatrix;
93 |
94 | public PrngGlibc3()
95 | {
96 | this._NextMatrix = GenerateNextMatrix();
97 | this._PreviousMatrix = GeneratePreviousMatrix();
98 | }
99 |
100 | public PrngGlibc3(ulong seed)
101 | : this()
102 | {
103 | this.Seed(seed);
104 | }
105 |
106 | public override ulong MinimumSeed
107 | {
108 | get
109 | {
110 | return 1;
111 | }
112 | }
113 |
114 | public override ulong MaximumSeed
115 | {
116 | get
117 | {
118 | return uint.MaxValue;
119 | }
120 | }
121 |
122 | public override void Seed(ulong seed)
123 | {
124 | unchecked // disable arithmetic checks for performance
125 | {
126 | this._State[0] = (uint)seed;
127 |
128 | for (int i = 1; i < 31; i++)
129 | {
130 | this._State[i] = (uint)((16807 * (ulong)this._State[i - 1]) % 2147483647);
131 | }
132 | }
133 |
134 | this._fptr = 3;
135 | this._rptr = 0;
136 |
137 | for (int i = 0; i < 310; i++)
138 | this.Next();
139 | }
140 |
141 | public override ulong Next()
142 | {
143 | unchecked // disable arithmetic checks for performance
144 | {
145 | uint next = (this._State[this._fptr] += this._State[this._rptr]);
146 |
147 | if (++this._fptr >= 31) this._fptr = 0;
148 | if (++this._rptr >= 31) this._rptr = 0;
149 |
150 | return (next >> 1);
151 | }
152 | }
153 |
154 | public override ulong Next(ulong limit)
155 | {
156 | unchecked // disable arithmetic checks for performance
157 | {
158 | uint next = (uint)this.Next();
159 |
160 | if (limit != 0 && limit <= 0x7FFFFFFF)
161 | next %= (uint)limit;
162 |
163 | return next;
164 | }
165 | }
166 |
167 | public override bool CanReverse
168 | {
169 | get
170 | {
171 | return true;
172 | }
173 | }
174 |
175 | public override ulong Previous()
176 | {
177 | unchecked // disable arithmetic checks for performance
178 | {
179 | if (--this._fptr < 0) this._fptr = 30;
180 | if (--this._rptr < 0) this._rptr = 30;
181 |
182 | uint current = this._State[this._fptr];
183 |
184 | this._State[this._fptr] -= this._State[this._rptr];
185 |
186 | return (current >> 1);
187 | }
188 | }
189 |
190 | public override ulong Previous(ulong limit)
191 | {
192 | unchecked // disable arithmetic checks for performance
193 | {
194 | uint current = (uint)this.Previous();
195 |
196 | if (limit != 0 && limit <= 0x7FFFFFFF)
197 | current %= (uint)limit;
198 |
199 | return current;
200 | }
201 | }
202 |
203 | public override bool CanSeek
204 | {
205 | get
206 | {
207 | return true;
208 | }
209 | }
210 |
211 | public override void SeekAhead(ulong offset)
212 | {
213 | if (offset < 31)
214 | {
215 | Step(unchecked((int)offset));
216 | return;
217 | }
218 |
219 | int steps;
220 | if (this._rptr != 0)
221 | {
222 | steps = (31 - this._rptr);
223 | Step(steps);
224 |
225 | offset -= unchecked((uint)steps);
226 | }
227 |
228 | ulong blockoffset = (offset / 31);
229 |
230 | steps = unchecked((int)(offset % 31));
231 | if (steps >= 16)
232 | {
233 | blockoffset++; // advance one more block and then go back to reduce the number of steps (although this could be slower due to more matrix multiplications)
234 | steps -= 31;
235 | }
236 |
237 | if (blockoffset != 0)
238 | {
239 | BlockSeek(blockoffset, this._NextMatrix);
240 | }
241 |
242 | Step(steps);
243 | }
244 |
245 | public override void SeekBack(ulong offset)
246 | {
247 | if (offset < 31)
248 | {
249 | Step(unchecked(-(int)offset));
250 | return;
251 | }
252 |
253 | int steps;
254 | if (this._rptr != 0)
255 | {
256 | steps = this._rptr;
257 | Step(-steps);
258 |
259 | offset -= unchecked((uint)steps);
260 | }
261 |
262 | ulong blockoffset = (offset / 31);
263 |
264 | steps = unchecked(-(int)(offset % 31));
265 | if (steps <= -16)
266 | {
267 | blockoffset++; // go back one more block and then advance to reduce the number of steps (although this could be slower due to more matrix multiplications)
268 | steps += 31;
269 | }
270 |
271 | if (blockoffset != 0)
272 | {
273 | BlockSeek(blockoffset, this._PreviousMatrix);
274 | }
275 |
276 | Step(steps);
277 | }
278 |
279 | private void Step(int offset)
280 | {
281 | if (offset < 0)
282 | {
283 | for (; offset != 0; offset++)
284 | Previous();
285 | }
286 | else
287 | {
288 | for (; offset != 0; offset--)
289 | Next();
290 | }
291 | }
292 |
293 | private void BlockSeek(ulong blockOffset, uint[,] matrix)
294 | {
295 | // compute 'absoffset'-th power of 'stepmatrix'
296 | uint[,] matrixa = (uint[,])(matrix.Clone());
297 | uint[,] matrixb = new uint[31, 31];
298 |
299 | uint[,] seekmatrixa = new uint[31, 31];
300 | uint[,] seekmatrixb = new uint[31, 31];
301 | for (int i = 0; i < 31; i++) // initialize seek matrix to identity matrix
302 | seekmatrixa[i, i] = 1;
303 |
304 | bool desta = false; // allocate two matrices and switch between them, instead of constantly allocating new matrices
305 | bool seekdesta = false;
306 |
307 | for (; ; )
308 | {
309 | if ((blockOffset & 1) != 0)
310 | {
311 | MultiplyMatrix((seekdesta ? seekmatrixa : seekmatrixb), (seekdesta ? seekmatrixb : seekmatrixa), (desta ? matrixb : matrixa));
312 | seekdesta = !seekdesta;
313 | }
314 |
315 | if ((blockOffset >>= 1) == 0)
316 | break;
317 |
318 | MultiplyMatrix((desta ? matrixa : matrixb), (desta ? matrixb : matrixa), (desta ? matrixb : matrixa)); // compute square of matrix
319 | desta = !desta;
320 | }
321 |
322 | // apply seek matrix to current state vector
323 | if (seekdesta)
324 | seekmatrixa = seekmatrixb; // if 'seekmatrixa' is set to be the next destination, then 'seekmatrixb' must contain the product last computed
325 |
326 | uint[] newstate = new uint[31];
327 |
328 | for (int i = 0; i < 31; i++)
329 | {
330 | uint accumulator = 0;
331 |
332 | for (int k = 0; k < 31; k++)
333 | {
334 | accumulator += unchecked((uint)((ulong)seekmatrixa[i, k] * (ulong)this._State[k]));
335 | }
336 |
337 | newstate[i] = accumulator;
338 | }
339 |
340 | Array.Copy(newstate, 0, this._State, 0, 31);
341 | }
342 |
343 | private static uint[,] GenerateNextMatrix()
344 | {
345 | uint[,] matrix = new uint[31, 31];
346 |
347 | for (int i = 0; i < 31; i++)
348 | for (int j = i; j >= 0; j -= 3)
349 | matrix[i, j] = 1;
350 |
351 | for (int i = 0; i < 3; i++)
352 | for (int j = 0; j < 31; j++)
353 | matrix[i, j] += matrix[i + 28, j];
354 |
355 | return matrix;
356 | }
357 |
358 | private static uint[,] GeneratePreviousMatrix()
359 | {
360 | uint[,] matrix = new uint[31, 31];
361 |
362 | for (int j = 0; j < 28; j++)
363 | {
364 | matrix[j, j] = 1;
365 | matrix[j + 3, j] = unchecked((uint)-1);
366 | }
367 |
368 | for (int j = 28; j < 31; j++)
369 | {
370 | matrix[j - 28, j] = unchecked((uint)-1);
371 | matrix[j - 25, j] = 1;
372 | matrix[j, j] = 1;
373 | }
374 |
375 | return matrix;
376 | }
377 |
378 | private static void MultiplyMatrix(uint[,] destination, uint[,] a, uint[,] b)
379 | {
380 | for (int i = 0; i < 31; i++)
381 | {
382 | for (int j = 0; j < 31; j++)
383 | {
384 | uint accumulator = 0;
385 |
386 | for (int k = 0; k < 31; k++)
387 | {
388 | accumulator += unchecked((uint)((ulong)a[i, k] * (ulong)b[k, j]));
389 | }
390 |
391 | destination[i, j] = accumulator;
392 | }
393 | }
394 | }
395 |
396 | } //class PrngGlibc3
397 |
398 | } //namespace Cylance.Research.Prangster
399 |
--------------------------------------------------------------------------------
/PRNGs/PrngJava.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | // Implements the algorithm of Oracle JDK 7 Random.java, which bears the following copyright notice:
32 | // Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
33 |
34 | using System;
35 |
36 | namespace Cylance.Research.Prangster
37 | {
38 |
39 | public sealed class PrngJava : PrngLcgBase
40 | {
41 |
42 | private const ulong _Multiplier = 0x5DEECE66D;
43 | private const ulong _Increment = 0xB;
44 | private const ulong _Modulus = 0x1000000000000; // & 0x0000FFFF`FFFFFFFF (48 bits)
45 | private const ulong _DiscardDivisor = 0x10000; // >> 16 for Next()
46 | private const ulong _DiscardDivisorForMod = 0x20000; // >> 17 for Next(ulong) where limit is not a power of two
47 | private const ulong _OutputDivisor = 0x100000000; // (32 bits)
48 |
49 | private const ulong _MultiplierInverse = 0xDFE05BCB1365; // multiplicative inverse of _Multiplier modulo _Modulus
50 |
51 | public PrngJava()
52 | {
53 | }
54 |
55 | public PrngJava(ulong seed)
56 | : this()
57 | {
58 | this.Seed(seed);
59 | }
60 |
61 | public override ulong MinimumSeed
62 | {
63 | get
64 | {
65 | return 0;
66 | }
67 | }
68 |
69 | public override ulong MaximumSeed
70 | {
71 | get
72 | {
73 | return (_Modulus - 1);
74 | }
75 | }
76 |
77 | public override ulong Multiplier
78 | {
79 | get
80 | {
81 | return _Multiplier;
82 | }
83 | }
84 |
85 | public override ulong Increment
86 | {
87 | get
88 | {
89 | return _Increment;
90 | }
91 | }
92 |
93 | public override ulong Modulus
94 | {
95 | get
96 | {
97 | return _Modulus;
98 | }
99 | }
100 |
101 | public override ulong DiscardDivisor
102 | {
103 | get
104 | {
105 | return _DiscardDivisor;
106 | }
107 | }
108 |
109 | public override ulong OutputDivisor
110 | {
111 | get
112 | {
113 | return _OutputDivisor;
114 | }
115 | }
116 |
117 | public override void Seed(ulong seed)
118 | {
119 | //if (seed > (_Modulus - 1))
120 | // throw new ArgumentOutOfRangeException("seed must be a non-negative 48-bit integer");
121 |
122 | unchecked // disable arithmetic checks for performance
123 | {
124 | this._LcgState = (seed ^ _Multiplier) & 0x0000FFFFFFFFFFFF;
125 | }
126 | }
127 |
128 | protected override ulong ValueFromRaw(ulong raw)
129 | {
130 | return (raw >> 16);
131 | }
132 |
133 | protected override ulong ValueFromRaw(ulong raw, ulong limit)
134 | {
135 | unchecked // disable arithmetic checks for performance
136 | {
137 | if ((limit & (limit - 1)) == 0) // special handling for power-of-two limits
138 | {
139 | return ((raw >> 17) * limit) >> 31; // keeps only most-significant bits
140 | }
141 | else
142 | {
143 | return (raw >> 17) % limit;
144 | }
145 | }
146 | }
147 |
148 | public override ulong Next() // Random.nextInt()
149 | {
150 | unchecked // disable arithmetic checks for performance
151 | {
152 | ulong next = ((this._LcgState * _Multiplier) + _Increment) & 0x0000FFFFFFFFFFFF;
153 | this._LcgState = next;
154 | return (next >> 16);
155 | }
156 | }
157 |
158 | public override ulong Next(ulong limit) // Random.nextInt(int)
159 | {
160 | //if (limit <= 0 || limit > int.MaxValue)
161 | // throw new ArgumentOutOfRangeException("limit must be a positive 32-bit integer");
162 |
163 | unchecked // disable arithmetic checks for performance
164 | {
165 | if ((limit & (limit - 1)) == 0) // special handling for power-of-two limits
166 | {
167 | ulong next = ((this._LcgState * _Multiplier) + _Increment) & 0x0000FFFFFFFFFFFF;
168 | this._LcgState = next;
169 |
170 | return ((next >> 17) * limit) >> 31; // keeps only most-significant bits
171 | }
172 | else
173 | {
174 | ulong next, value;
175 |
176 | do // loop to skip states that would otherwise slightly bias distribution toward the lowest (limit % Modulus) values
177 | {
178 | next = ((this._LcgState * _Multiplier) + _Increment) & 0x0000FFFFFFFFFFFF;
179 | this._LcgState = next;
180 |
181 | next >>= 17; // (48 - 17) = 31-bit (non-negative integer) result
182 | value = (next % limit);
183 | }
184 | while (next - value + (limit - 1) >= 0x80000000);
185 |
186 | return value;
187 | }
188 | }
189 | }
190 |
191 | public override bool CanReverse
192 | {
193 | get
194 | {
195 | return true;
196 | }
197 | }
198 |
199 | private static ulong PreviousState(ulong state)
200 | {
201 | unchecked // disable arithmetic checks for performance
202 | {
203 | ulong diff = (state - _Increment);
204 | return (diff * _MultiplierInverse) & 0x0000FFFFFFFFFFFF; // we can let multiplication overflow 64 bits because modulus is a power of two
205 | }
206 | }
207 |
208 | public override ulong Previous()
209 | {
210 | ulong current = this._LcgState;
211 |
212 | this._LcgState = PreviousState(this._LcgState);
213 |
214 | return (current >> 16);
215 | }
216 |
217 | public override ulong Previous(ulong limit)
218 | {
219 | //if (limit <= 0 || limit > int.MaxValue)
220 | // throw new ArgumentOutOfRangeException("limit must be a positive 32-bit integer");
221 |
222 | ulong current = this._LcgState;
223 |
224 | unchecked // disable arithmetic checks for performance
225 | {
226 | if ((limit & (limit - 1)) == 0) // special handling for power-of-two limits
227 | {
228 | this._LcgState = PreviousState(this._LcgState);
229 |
230 | return ((current >> 17) * limit) >> 31; // keeps only most-significant bits
231 | }
232 | else
233 | {
234 | ulong prev, value;
235 |
236 | do // loop to skip states that would otherwise slightly bias distribution toward the lowest (limit % Modulus) values
237 | {
238 | this._LcgState = PreviousState(this._LcgState);
239 |
240 | prev = (this._LcgState >> 17); // (48 - 17) = 31-bit (non-negative integer) result
241 | value = (prev % limit);
242 | }
243 | while (prev - value + (limit - 1) >= 0x80000000);
244 |
245 | return (current >> 17) % limit; // this shouldn't fall within the bias zone, but it could; currently we choose to ignore that case
246 | }
247 | }
248 | }
249 |
250 | public override ulong SeekSeedAhead(ulong seed, ulong offset)
251 | {
252 | return (base.SeekSeedAhead(seed ^ _Multiplier, offset) ^ _Multiplier);
253 | }
254 |
255 | public override ulong SeekSeedBack(ulong seed, ulong offset)
256 | {
257 | return (base.SeekSeedBack(seed ^ _Multiplier, offset) ^ _Multiplier);
258 | }
259 |
260 | protected override bool RecoverSeed(ulong seedStart, ulong seedEnd, ulong seedIncrement, ulong[] output, ulong limit, ulong wildcard, RecoverSeedCallback callback, ulong progressInterval)
261 | {
262 | if (output.Length < 2 || output[0] > (ulong.MaxValue / _OutputDivisor) || output[0] == wildcard || limit == 0 || limit > _OutputDivisor)
263 | return base.RecoverSeed(seedStart, seedEnd, seedIncrement, output, limit, wildcard, callback, progressInterval);
264 |
265 | if (seedStart > seedEnd || seedIncrement == 0)
266 | return false;
267 |
268 | if (unchecked(limit & (limit - 1)) == 0) // special handling for power-of-two limits
269 | {
270 | return this.RecoverSeedPowerOf2(seedStart, seedEnd, seedIncrement, output, limit, wildcard, callback, progressInterval);
271 | }
272 |
273 | RecoverSeedEventArgs args = new RecoverSeedEventArgs();
274 |
275 | unchecked // disable arithmetic checks for performance
276 | {
277 | // operate on output suffix of length N - 1 so we can fix middle portion of seed to output[0]
278 | ulong[] suboutput = new ulong[output.Length - 1];
279 | Array.Copy(output, 1, suboutput, 0, output.Length - 1);
280 |
281 | ulong seedtopincr = (uint)limit * _DiscardDivisorForMod;
282 |
283 | // Modulus is a power of 2, so GCD(limit, Modulus) is greatest power-of-two factor of limit
284 | ulong subgenoutputmask = ((uint)limit ^ ((uint)limit - 1)) >> 1;
285 |
286 | // fix bottom portion by brute-forcing subgenerator
287 | ulong subseed, subseedend;
288 | for (subseed = (output[0] & subgenoutputmask) * _DiscardDivisorForMod, subseedend = subseed + _DiscardDivisorForMod - 1; subseed != subseedend; subseed++)
289 | {
290 | if (subgenoutputmask != 0) // if limit is odd, we can't check this subgenerator seed against LSB(s) of output; we must test all possibilities below
291 | {
292 | this._LcgState = subseed; // don't use Seed() because it XORs by _Multiplier
293 |
294 | int i;
295 | for (i = 0; i < suboutput.Length; i++)
296 | {
297 | if ((this.Next(limit) & subgenoutputmask) != (suboutput[i] & subgenoutputmask) && suboutput[i] != wildcard)
298 | break;
299 | }
300 |
301 | if (i < suboutput.Length)
302 | continue;
303 | }
304 |
305 | // MSB(s) of subseed will contain LSB(s) of output[0], so | instead of + to keep duplicate bit(s) from interfering
306 | for (ulong seed = (output[0] * _DiscardDivisorForMod) | subseed; seed <= seedEnd; seed += seedtopincr)
307 | {
308 | this._LcgState = seed; // don't use Seed() because it XORs by _Multiplier
309 |
310 | int i;
311 | for (i = 0; i < suboutput.Length; i++)
312 | {
313 | if (this.Next(limit) != suboutput[i] && suboutput[i] != wildcard)
314 | break;
315 | }
316 |
317 | if (i == suboutput.Length) // invoke callback for seed discovery notification
318 | {
319 | args.EventType = RecoverSeedEventType.SeedDiscovered;
320 | args.Seed = (PreviousState(seed) ^ _Multiplier);
321 | // TO-DO TODO: estimate progress/total somehow?
322 | args.CurrentAttempts = 0;
323 | args.TotalAttempts = 0;
324 |
325 | callback(args);
326 |
327 | if (args.Cancel)
328 | return false;
329 | }
330 | } //for(seed<=seedEnd)
331 | } //for(subseed 1)
356 | {
357 | ulong offset = (rangestart - seedStart) % seedIncrement;
358 | if (offset != 0)
359 | rangestart += (seedIncrement - offset); // advance to the next multiple of 'seedIncrement' (relative to 'seedStart')
360 | }
361 |
362 | if (rangeend > seedEnd)
363 | rangeend = seedEnd;
364 |
365 | return base.RecoverSeed(rangestart, rangeend, seedIncrement, suboutput, limit, wildcard, this.RecoverSeedPowerOf2Callback, progressInterval);
366 | } //unchecked
367 | } //PrngJava.RecoverSeedPowerOf2
368 |
369 | private RecoverSeedCallback _OriginalCallback;
370 |
371 | private void RecoverSeedPowerOf2Callback(RecoverSeedEventArgs args)
372 | {
373 | if (args.EventType == RecoverSeedEventType.SeedDiscovered)
374 | args.Seed = PreviousState(args.Seed ^ _Multiplier) ^ _Multiplier;
375 |
376 | this._OriginalCallback(args);
377 | }
378 |
379 | } //class PrngJava
380 |
381 | } //namespace Cylance.Research.Prangster
382 |
--------------------------------------------------------------------------------
/PRNGs/PrngLcgBase.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | using System;
32 |
33 | namespace Cylance.Research.Prangster
34 | {
35 |
36 | ///
37 | /// Base class from which linear congruential generator (LCG)-based PRNGs are derived.
38 | ///
39 | public abstract class PrngLcgBase : PrngBase
40 | {
41 |
42 | ///
43 | /// Default 64-bit internal state.
44 | ///
45 | protected ulong _LcgState;
46 |
47 | public override ulong MinimumSeed
48 | {
49 | get
50 | {
51 | return 0;
52 | }
53 | }
54 |
55 | public override ulong MaximumSeed
56 | {
57 | get
58 | {
59 | return (this.Modulus - 1);
60 | }
61 | }
62 |
63 | public override void Seed(ulong seed)
64 | {
65 | this._LcgState = (seed % this.Modulus);
66 | }
67 |
68 | ///
69 | /// Computes the next state of the linear congruential generator.
70 | ///
71 | /// The current state, or seed, of the linear congruential generator.
72 | /// The linear congruential generator's multiplier parameter.
73 | /// The linear congruential generator's increment or addend parameter.
74 | /// The linear congruential generator's "modulus" parameter, or 0 if the modulus is 2**64.
75 | /// The next state, modulo .
76 | protected static ulong NextState(ulong state, ulong multiplier, ulong increment, ulong divisor)
77 | {
78 | ulong next = ((state * multiplier) + increment);
79 | if (divisor != 0)
80 | next %= divisor;
81 |
82 | return next;
83 | }
84 |
85 | ///
86 | /// Performs discard and modulus transformations on a raw value to produce output according to the PRNG's parameters.
87 | ///
88 | /// The raw bits to transform.
89 | /// A value suitable for output.
90 | protected virtual ulong ValueFromRaw(ulong raw)
91 | {
92 | if (this.DiscardDivisor != 0)
93 | raw /= this.DiscardDivisor;
94 |
95 | if (this.OutputDivisor != 0)
96 | raw %= this.OutputDivisor;
97 |
98 | return raw;
99 | }
100 |
101 | ///
102 | /// Performs discard, modulus, and/or take-from-top transformations on a raw value to produce output according to the PRNG's parameters.
103 | ///
104 | /// The raw bits to transform.
105 | /// The lowest positive integer greater than the maximum desired value.
106 | /// A value suitable for output.
107 | protected virtual ulong ValueFromRaw(ulong raw, ulong limit)
108 | {
109 | if (this.DiscardDivisor != 0)
110 | {
111 | raw /= this.DiscardDivisor;
112 |
113 | if (this.OutputDivisor != 0)
114 | raw %= this.OutputDivisor;
115 |
116 | return raw;
117 | }
118 | else
119 | {
120 | // TO-DO TODO: should we incorporate OutputDivisor somehow?
121 | MyUInt256 product = new MyUInt256(raw);
122 | product.Multiply(limit);
123 | product.Divide(this.Modulus);
124 |
125 | return (product.ToUInt64());
126 | }
127 | }
128 |
129 | public override ulong Next()
130 | {
131 | ulong next = NextState(this._LcgState, this.Multiplier, this.Increment, this.Modulus);
132 | this._LcgState = next;
133 |
134 | return ValueFromRaw(next);
135 | }
136 |
137 | public override ulong Next(ulong limit)
138 | {
139 | ulong next = NextState(this._LcgState, this.Multiplier, this.Increment, this.Modulus);
140 | this._LcgState = next;
141 |
142 | return ValueFromRaw(next, limit);
143 | }
144 |
145 | public override bool CanReverse
146 | {
147 | get
148 | {
149 | return true;
150 | }
151 | }
152 |
153 | protected static ulong GetMultiplicativeInverse(ulong multiplier, ulong divisor)
154 | {
155 | ulong mi;
156 |
157 | if (multiplier >= divisor && divisor != 0)
158 | return 0;
159 |
160 | if (unchecked((long)multiplier) < 0 || unchecked((long)divisor) <= 0)
161 | {
162 | mi = ModularMath.MultiplicativeInverse(unchecked((long)multiplier), unchecked((long)divisor));
163 | }
164 | else
165 | {
166 | MyUInt256 mibig = ModularMath.MultiplicativeInverse(new MyUInt256(multiplier), (divisor == 0 ? new MyUInt256(0, 1) : new MyUInt256(divisor)));
167 | mi = (mibig == null ? 0 : mibig.ToUInt64());
168 | }
169 |
170 | return mi;
171 | } //PrngLcgBase.GetMultiplicativeInverse
172 |
173 | ///
174 | /// Computes the previous state of the linear congruential generator.
175 | ///
176 | /// The current state, or seed, of the linear congruential generator.
177 | /// The multiplicative inverse of the linear congruential generator's multiplier parameter modulo .
178 | /// The linear congruential generator's increment or addend parameter.
179 | /// The linear congruential generator's "modulus" parameter, or 0 if the modulus is 2**64.
180 | /// The next state, modulo .
181 | protected static ulong PreviousState(ulong state, ulong multiplier, ulong increment, ulong divisor)
182 | {
183 | ulong mi = GetMultiplicativeInverse(multiplier, divisor);
184 |
185 | if (mi != 0)
186 | {
187 | unchecked
188 | {
189 | ulong prev = ((state - increment) * mi);
190 | if (divisor != 0)
191 | prev %= divisor;
192 | return prev;
193 | }
194 | }
195 | else
196 | {
197 | // guessing that modulus will be a multiple of period, in which case seeking ahead (modulus - 1) states will reverse to previous state
198 | return SeekState(state, unchecked(divisor - 1), multiplier, increment, divisor);
199 | }
200 | } //PrngLcgBase.PreviousState
201 |
202 | public override ulong Previous()
203 | {
204 | ulong current = this._LcgState;
205 |
206 | SeekBack(1);
207 | return ValueFromRaw(current);
208 | }
209 |
210 | public override ulong Previous(ulong limit)
211 | {
212 | ulong current = this._LcgState;
213 |
214 | SeekBack(1);
215 | return ValueFromRaw(current, limit);
216 | }
217 |
218 | ///
219 | /// When overwritten in a derived class, gets the multiplier constant of the linear congruential generator.
220 | ///
221 | public abstract ulong Multiplier
222 | {
223 | get;
224 | }
225 |
226 | ///
227 | /// When overwritten in a derived class, gets the increment (addend) constant of the linear congruential generator.
228 | ///
229 | public abstract ulong Increment
230 | {
231 | get;
232 | }
233 |
234 | ///
235 | /// When overwritten in a derived class, gets the modulus constant of the linear
236 | /// congruential generator, or 0 if the modulus is 2**64.
237 | ///
238 | public abstract ulong Modulus
239 | {
240 | get;
241 | }
242 |
243 | ///
244 | /// When overwritten in a derived class, gets the divisor used to divide the
245 | /// linear congruential generator's output to discard the least-significant portion,
246 | /// or 0 if the most-significant portion if the output is used instead.
247 | ///
248 | public abstract ulong DiscardDivisor
249 | {
250 | get;
251 | }
252 |
253 | ///
254 | /// When overwritten in a derived class, gets the divisor used to retain a remainder
255 | /// of the linear congruential generator's output after division by
256 | /// , or 0 if no modulo operation is to be performed.
257 | ///
258 | public virtual ulong OutputDivisor
259 | {
260 | get
261 | {
262 | return 0;
263 | }
264 | }
265 |
266 | public override bool CanSeek
267 | {
268 | get
269 | {
270 | return true;
271 | }
272 | }
273 |
274 | ///
275 | /// Computes the state at the specified position in the pseudorandom stream relative to a given initial state.
276 | ///
277 | /// The state at position zero in the stream.
278 | /// The number of states to skip.
279 | /// The linear congruential generator's multiplier constant, or its multiplicative inverse modulo to go backwards.
280 | /// The linear congruential generator's increment constant,
281 | /// or its additive inverse modulo multiplied by the multiplicative inverse to go backwards.
282 | /// The linear congruential generator's modulus constant.
283 | /// The state at position in the stream.
284 | protected static ulong SeekState(ulong state, ulong offset, ulong multiplier, ulong increment, ulong divisor)
285 | {
286 | // NewState = (Multiplier**Offset * OldState) + Increment * (Multiplier**Offset - 1) / (Multiplier - 1)
287 | // caller can substitute Multiplier**-1 and -Increment * Multiplier**-1 to go backwards
288 |
289 | if (offset == 0)
290 | return state;
291 |
292 | if (multiplier == 0)
293 | {
294 | return increment;
295 | }
296 | else if (multiplier == 1)
297 | {
298 | MyUInt256 product = new MyUInt256(increment);
299 | product.Multiply(offset);
300 | if (divisor != 0)
301 | product.Modulo(divisor);
302 | return product.ToUInt64();
303 | }
304 |
305 | MyUInt256 compdivisor = new MyUInt256(divisor);
306 | if (divisor == 0)
307 | compdivisor.Set(0, 1);
308 | compdivisor.Multiply(multiplier - 1);
309 |
310 | MyUInt256 aexpn = new MyUInt256(multiplier);
311 | aexpn.ExpMod(offset, compdivisor); // = Multiplier**Offset
312 |
313 | MyUInt256 fraction = new MyUInt256(aexpn);
314 | fraction.Subtract(1);
315 | fraction.Divide(multiplier - 1); // should always divide evenly; that's why divisor has to include (Multiplier - 1) factor though
316 | fraction.Multiply(increment); // = Increment * (Multiplier**Offset - 1) / (Multiplier - 1)
317 |
318 | MyUInt256 newstate = new MyUInt256(state);
319 | newstate.Multiply(aexpn); // = Multiplier**Offset * OldState
320 | newstate.Add(fraction); // = (Multiplier**Offset * OldState) + Increment * (Multiplier**Offset - 1) / (Multiplier - 1)
321 |
322 | if (divisor != 0)
323 | newstate.Modulo(divisor); // now that we've divided by (Multiplier - 1), we can go back to using 'divisor' instead of 'compdivisor'
324 |
325 | return newstate.ToUInt64();
326 | } //PrngLcgBase.SeekState
327 |
328 | public override void SeekAhead(ulong offset)
329 | {
330 | this._LcgState = SeekState(this._LcgState, offset, this.Multiplier, this.Increment, this.Modulus);
331 | }
332 |
333 | public override void SeekBack(ulong offset)
334 | {
335 | if (offset == 0)
336 | return;
337 |
338 | ulong multiplier = this.Multiplier;
339 | ulong increment = this.Increment;
340 | ulong divisor = this.Modulus;
341 |
342 | ulong mi = GetMultiplicativeInverse(multiplier, divisor);
343 |
344 | if (mi == 0)
345 | {
346 | // guessing that modulus is a multiple of period, in which case seeking ahead (modulus - offset) states will reverse by 'offset' states
347 | SeekAhead(unchecked(divisor - offset));
348 | return;
349 | }
350 |
351 | if (increment >= divisor && divisor != 0)
352 | increment %= divisor;
353 |
354 | if (increment != 0)
355 | {
356 | MyUInt256 incrinverse = new MyUInt256(unchecked(divisor - increment)); // negate increment (modulo divisor) to get additive inverse
357 | incrinverse.Multiply(mi);
358 |
359 | if (divisor != 0)
360 | incrinverse.Modulo(divisor);
361 |
362 | increment = incrinverse.ToUInt64();
363 | }
364 |
365 | this._LcgState = SeekState(this._LcgState, offset, mi, increment, divisor);
366 | } //PrngLcgBase.SeekBack
367 |
368 | public override bool CanSeekSeed
369 | {
370 | get
371 | {
372 | return true;
373 | }
374 | }
375 |
376 | public override ulong SeekSeedAhead(ulong seed, ulong offset)
377 | {
378 | return SeekState(seed, offset, this.Multiplier, this.Increment, this.Modulus);
379 | } //PrngLcgBase.SeekSeedAhead
380 |
381 | public override ulong SeekSeedBack(ulong seed, ulong offset)
382 | {
383 | if (offset == 0)
384 | return seed;
385 |
386 | ulong multiplier = this.Multiplier;
387 | ulong increment = this.Increment;
388 | ulong divisor = this.Modulus;
389 |
390 | ulong mi = GetMultiplicativeInverse(multiplier, divisor);
391 |
392 | if (mi == 0)
393 | {
394 | // guessing that modulus is a multiple of period, in which case seeking ahead (modulus - offset) states will reverse by 'offset' states
395 | return SeekSeedAhead(seed, unchecked(divisor - offset));
396 | }
397 |
398 | if (increment >= divisor && divisor != 0)
399 | increment %= divisor;
400 |
401 | if (increment != 0)
402 | {
403 | MyUInt256 incrinverse = new MyUInt256(unchecked(divisor - increment)); // negate increment (modulo divisor) to get additive inverse
404 | incrinverse.Multiply(mi);
405 |
406 | if (divisor != 0)
407 | incrinverse.Modulo(divisor);
408 |
409 | increment = incrinverse.ToUInt64();
410 | }
411 |
412 | return SeekState(this._LcgState, offset, mi, increment, divisor);
413 | } //PrngLcgBase.SeekSeedBack
414 |
415 | } //class PrngLcgBase
416 |
417 | } //namespace Cylance.Research.Prangster
418 |
--------------------------------------------------------------------------------
/PRNGs/PrngLehmerBase.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | using System;
32 |
33 | namespace Cylance.Research.Prangster
34 | {
35 |
36 | ///
37 | /// Base class from which Lehmer or Park-Miller PRNGs are derived.
38 | ///
39 | public abstract class PrngLehmerBase : PrngLcgBase
40 | {
41 |
42 | public override ulong MinimumSeed
43 | {
44 | get
45 | {
46 | return 1; // seed of 0 is unsupported, because it would cause the internal state to remain at 0 due to the lack of an addition (increment)
47 | }
48 | }
49 |
50 | public override ulong Increment
51 | {
52 | get
53 | {
54 | return 0; // Lehmer PRNG (multiplicative congruential method) differs from mixed congruential method in its lack of an addition.
55 | }
56 | }
57 |
58 | ///
59 | /// Computes the next state of the linear congruential generator.
60 | ///
61 | /// The current state, or seed, of the linear congruential generator.
62 | /// The linear congruential generator's multiplier parameter.
63 | /// The linear congruential generator's "modulus" parameter, or 0 if the modulus is 2**64.
64 | /// The next state, modulo .
65 | protected static ulong NextState(ulong state, ulong multiplier, ulong divisor)
66 | {
67 | return NextState(state, multiplier, 0, divisor);
68 | }
69 |
70 | ///
71 | /// Computes the previous state of the linear congruential generator.
72 | ///
73 | /// The current state, or seed, of the linear congruential generator.
74 | /// The multiplicative inverse of the linear congruential generator's multiplier parameter modulo .
75 | /// The linear congruential generator's "modulus" parameter, or 0 if the modulus is 2**64.
76 | /// The next state, modulo .
77 | protected static ulong PreviousState(ulong state, ulong multiplier, ulong divisor)
78 | {
79 | return PreviousState(state, multiplier, divisor);
80 | }
81 |
82 | ///
83 | /// Computes the state at the specified position in the pseudorandom stream relative to a given initial state.
84 | ///
85 | /// The state at position zero in the stream.
86 | /// The number of states to skip.
87 | /// The linear congruential generator's multiplier constant, or its multiplicative inverse modulo to go backwards.
88 | /// The linear congruential generator's modulus constant.
89 | /// The state at position in the stream.
90 | protected static ulong SeekState(ulong state, ulong offset, ulong multiplier, ulong divisor)
91 | {
92 | // NewState = (Multiplier**Offset * OldState)
93 | // caller can substitute Multiplier**-1 to go backwards
94 |
95 | if (offset == 0)
96 | return state;
97 |
98 | MyUInt256 fullmodulus = (divisor == 0 ? new MyUInt256(0, 1) : new MyUInt256(divisor));
99 |
100 | MyUInt256 aexpn = new MyUInt256(multiplier);
101 | aexpn.ExpMod(offset, fullmodulus);
102 | aexpn.Multiply(state);
103 |
104 | if (divisor != 0)
105 | aexpn.Modulo(fullmodulus);
106 |
107 | return aexpn.ToUInt64();
108 | } //PrngLehmerBase.SeekState
109 |
110 | public override void SeekAhead(ulong offset)
111 | {
112 | this._LcgState = SeekState(this._LcgState, offset, this.Multiplier, this.Modulus);
113 | } //PrngLehmerBase.SeekAhead
114 |
115 | public override void SeekBack(ulong offset)
116 | {
117 | if (offset == 0)
118 | return;
119 |
120 | ulong multiplier = this.Multiplier;
121 | ulong modulus = this.Modulus;
122 |
123 | ulong mi = GetMultiplicativeInverse(multiplier, modulus);
124 |
125 | if (mi == 0)
126 | {
127 | // guessing that (modulus - 1) is a multiple of period (-1 because zero state is excluded),
128 | // in which case seeking ahead (modulus - 1 - offset) states will reverse by 'offset' states
129 | SeekAhead(unchecked(modulus - 1 - offset));
130 | return;
131 | }
132 |
133 | this._LcgState = SeekState(this._LcgState, offset, mi, modulus);
134 | } //PrngLehmerBase.SeekBack
135 |
136 | public override ulong SeekSeedAhead(ulong seed, ulong offset)
137 | {
138 | return SeekState(this._LcgState, offset, this.Multiplier, this.Modulus);
139 | } //PrngLehmerBase.SeekSeedAhead
140 |
141 | public override ulong SeekSeedBack(ulong seed, ulong offset)
142 | {
143 | if (offset == 0)
144 | return seed;
145 |
146 | ulong multiplier = this.Multiplier;
147 | ulong modulus = this.Modulus;
148 |
149 | ulong mi = GetMultiplicativeInverse(multiplier, modulus);
150 |
151 | if (mi == 0)
152 | {
153 | // guessing that (modulus - 1) is a multiple of period (-1 because zero state is excluded),
154 | // in which case seeking ahead (modulus - 1 - offset) states will reverse by 'offset' states
155 | return SeekSeedAhead(seed, unchecked(modulus - 1 - offset));
156 | }
157 |
158 | return SeekState(this._LcgState, offset, mi, modulus);
159 | } //PrngLehmerBase.SeekSeedBack
160 |
161 | } //class PrngLehmerBase
162 |
163 | } //namespace Cylance.Research.Prangster
164 |
--------------------------------------------------------------------------------
/PRNGs/PrngMssql.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | using System;
32 |
33 | namespace Cylance.Research.Prangster
34 | {
35 |
36 | public sealed class PrngMssql : PrngBase
37 | {
38 |
39 | private const uint _Modulus = 2147483563;
40 | private const uint _Modulus1 = 2147483399;
41 |
42 | private const uint _Multiplier0 = 40014;
43 | private const uint _Multiplier1 = 40692;
44 |
45 | private const uint _Multiplier0Inverse = 2082061899; // multiplicative inverse of _Multiplier0 modulo _Modulus
46 | private const uint _Multiplier1Inverse = 1481316021; // multiplicative inverse of _Multiplier1 modulo _Modulus1
47 |
48 | private uint _State0, _State1;
49 |
50 | public PrngMssql()
51 | {
52 | }
53 |
54 | public PrngMssql(ulong seed)
55 | : this()
56 | {
57 | this.Seed(seed);
58 | }
59 |
60 |
61 | public override ulong MinimumSeed
62 | {
63 | get
64 | {
65 | return _Modulus1 + 1;
66 | }
67 | }
68 |
69 | public override ulong MaximumSeed
70 | {
71 | get
72 | {
73 | return ((ulong)_Modulus * (ulong)_Modulus1) - 1;
74 | }
75 | }
76 |
77 | public override void Seed(ulong seed)
78 | {
79 | unchecked // disable arithmetic checks for performance
80 | {
81 | uint state0, state1;
82 |
83 | SeedToStates(seed, out state0, out state1);
84 |
85 | if (state0 < 1 || state0 >= _Modulus)
86 | {
87 | //throw new ArgumentOutOfRangeException("seed must comprise two positive integers, the most significant being less than 2147483563");
88 | state0 = 12345;
89 | }
90 |
91 | if (state1 < 1)
92 | {
93 | //throw new ArgumentOutOfRangeException("seed must comprise two positive integers, the least significant being less than 2147483399");
94 | state1 = 67890;
95 | }
96 |
97 | this._State0 = state0;
98 | this._State1 = state1;
99 | }
100 | }
101 |
102 | private static void SeedToStates(ulong seed, out uint state0, out uint state1)
103 | {
104 | // we treat 'seed' as a composite of the two internal, 32-bit state variables;
105 | // (State0 * _Modulus1 + State1) is the more compact 64-bit representation,
106 | // but (State0 << 32 | State1) might be more machine-friendly
107 |
108 | state0 = unchecked((uint)(seed / _Modulus1));
109 | state1 = unchecked((uint)(seed % _Modulus1));
110 | }
111 |
112 | private static ulong SeedFromStates(uint state0, uint state1)
113 | {
114 | return unchecked(((ulong)state0 * _Modulus1) + (ulong)state1);
115 | }
116 |
117 | public void Seed32(uint seed)
118 | {
119 | if (seed == 0 || seed >= _Modulus)
120 | seed = 12345;
121 |
122 | unchecked // disable arithmetic checks for performance
123 | {
124 | Seed((ulong)seed * _Modulus1 + 67890);
125 | }
126 | }
127 |
128 | private static uint NextFromStates(uint state0, uint state1)
129 | {
130 | unchecked // disable arithmetic checks for performance
131 | {
132 | state0 = (uint)(((ulong)state0 * _Multiplier0) % _Modulus);
133 | state1 = (uint)(((ulong)state1 * _Multiplier1) % _Modulus1);
134 |
135 | int next = (int)(state0 - state1);
136 | if (next <= 0) next += (int)(_Modulus - 1);
137 |
138 | return (uint)next;
139 | }
140 | }
141 |
142 | private static uint NextFromStates(uint state0, uint state1, uint limit)
143 | {
144 | unchecked // disable arithmetic checks for performance
145 | {
146 | return (uint)((double)((ulong)NextFromStates(state0, state1) * (ulong)limit) / 2147483589.46728);
147 | }
148 | }
149 |
150 | public override ulong Next()
151 | {
152 | unchecked // disable arithmetic checks for performance
153 | {
154 | this._State0 = (uint)(((ulong)this._State0 * _Multiplier0) % _Modulus);
155 | this._State1 = (uint)(((ulong)this._State1 * _Multiplier1) % _Modulus1);
156 |
157 | int next = (int)(this._State0 - this._State1);
158 | if (next <= 0) next += (int)(_Modulus - 1);
159 |
160 | return (uint)next;
161 | }
162 | }
163 |
164 | public override ulong Next(ulong limit)
165 | {
166 | //if (limit <= 0 || limit > int.MaxValue)
167 | // throw new ArgumentOutOfRangeException("limit must be a positive 32-bit integer");
168 |
169 | unchecked // disable arithmetic checks for performance
170 | {
171 | return (ulong)((double)(this.Next() * limit) / 2147483589.46728);
172 | }
173 | }
174 |
175 | public override bool CanReverse
176 | {
177 | get
178 | {
179 | return true;
180 | }
181 | }
182 |
183 | public override ulong Previous()
184 | {
185 | unchecked // disable arithmetic checks for performance
186 | {
187 | int current = (int)(this._State0 - this._State1);
188 | if (current <= 0) current += (int)(_Modulus - 1);
189 |
190 | this._State0 = (uint)(((ulong)this._State0 * _Multiplier0Inverse) % _Modulus);
191 | this._State1 = (uint)(((ulong)this._State1 * _Multiplier1Inverse) % _Modulus1);
192 |
193 | return (uint)current;
194 | }
195 | }
196 |
197 | public override ulong Previous(ulong limit)
198 | {
199 | //if (limit <= 0 || limit > int.MaxValue)
200 | // throw new ArgumentOutOfRangeException("limit must be a positive 32-bit integer");
201 |
202 | unchecked // disable arithmetic checks for performance
203 | {
204 | return (ulong)((double)(this.Previous() * limit) / 2147483589.46728);
205 | }
206 | }
207 |
208 | public override bool CanSeek
209 | {
210 | get
211 | {
212 | return true;
213 | }
214 | }
215 |
216 | private const ulong _MaximumPeriod = ((ulong)_Modulus - 1) * ((ulong)_Modulus1 - 1);
217 |
218 | private static void SeekStateInternal(ref uint state0, ref uint state1, ulong offset, bool reverse)
219 | {
220 | if (offset >= _MaximumPeriod)
221 | offset %= _MaximumPeriod;
222 |
223 | if (offset == 0)
224 | return;
225 |
226 | {
227 | MyUInt256 aexpn = new MyUInt256(reverse ? _Multiplier0Inverse : _Multiplier0);
228 | aexpn.ExpMod(offset, new MyUInt256(_Modulus));
229 |
230 | state0 = unchecked((uint)((aexpn.ToUInt64() * state0) % _Modulus));
231 | }
232 |
233 | {
234 | MyUInt256 aexpn = new MyUInt256(reverse ? _Multiplier1Inverse : _Multiplier1);
235 | aexpn.ExpMod(offset, new MyUInt256(_Modulus1));
236 |
237 | state1 = unchecked((uint)((aexpn.ToUInt64() * state1) % _Modulus1));
238 | }
239 | }
240 |
241 | private void SeekInternal(ulong offset, bool reverse)
242 | {
243 | SeekStateInternal(ref this._State0, ref this._State1, offset, reverse);
244 | }
245 |
246 | public override void SeekAhead(ulong offset)
247 | {
248 | SeekInternal(offset, false);
249 | }
250 |
251 | public override void SeekBack(ulong offset)
252 | {
253 | SeekInternal(offset, true);
254 | }
255 |
256 | public override bool CanSeekSeed
257 | {
258 | get
259 | {
260 | return true;
261 | }
262 | }
263 |
264 | public override ulong SeekSeedAhead(ulong seed, ulong offset)
265 | {
266 | uint state0, state1;
267 | SeedToStates(seed, out state0, out state1);
268 |
269 | SeekStateInternal(ref state0, ref state1, offset, false);
270 |
271 | return SeedFromStates(state0, state1);
272 | }
273 |
274 | public override ulong SeekSeedBack(ulong seed, ulong offset)
275 | {
276 | uint state0, state1;
277 | SeedToStates(seed, out state0, out state1);
278 |
279 | SeekStateInternal(ref state0, ref state1, offset, true);
280 |
281 | return SeedFromStates(state0, state1);
282 | }
283 |
284 | protected override bool RecoverSeed(ulong seedStart, ulong seedEnd, ulong seedIncrement, ulong[] output, ulong limit, ulong wildcard, RecoverSeedCallback callback, ulong progressInterval)
285 | {
286 | if (output.Length < 2 || output[0] >= limit || output[0] == wildcard || limit == 0 || limit > _Modulus || seedIncrement != 1)
287 | return base.RecoverSeed(seedStart, seedEnd, seedIncrement, output, limit, wildcard, callback, progressInterval);
288 |
289 | if (seedStart < this.MinimumSeed)
290 | seedStart = this.MinimumSeed;
291 |
292 | if (seedEnd > this.MaximumSeed)
293 | seedEnd = this.MaximumSeed;
294 |
295 | if (seedStart > seedEnd)
296 | return false;
297 |
298 | ulong output1 = ((output.Length > 2) ? output[1] : wildcard);
299 |
300 | uint blocksize = (uint)(_Modulus / ((ulong)_Multiplier1 * limit));
301 | if (blocksize < 2) output1 = wildcard; // don't attempt improved attack if block size is too small
302 |
303 | RecoverSeedEventArgs args = new RecoverSeedEventArgs();
304 |
305 | unchecked // disable arithmetic checks for performance
306 | {
307 | // operate on output suffix of length N - 1 so we can fix bottom portion of seed to output[0]
308 | ulong[] suboutput = new ulong[output.Length - 1];
309 | Array.Copy(output, 1, suboutput, 0, output.Length - 1);
310 |
311 | // 2147483589.46728 rounded down is 2147483589 and rounded up is 2147483590; rounding outward ensures we won't exclude a viable candidate state
312 | uint difflo = (uint)(((2147483589 * output[0]) + limit - 1) / limit); // add (limit - 1) to round up, to make sure 'difflo' will (almost always) produce output[0]
313 | uint diffhi = (uint)(((2147483590 * (output[0] + 1)) + limit - 1) / limit) - 1; // lowest difference that produces (output[0] + 1), then - 1
314 |
315 | for (uint state0 = 1; state0 < _Modulus; state0++)
316 | {
317 | uint state1start = (state0 + _Modulus - diffhi); // State1 such that (State0 - State1) == diffhi; subtract 'diffhi' to get State1 lower bound
318 | if (state1start >= _Modulus) // _Modulus rather than _Modulus1 because difference is computed modulo _Modulus
319 | state1start -= _Modulus;
320 | if (state1start == 0 || state1start >= _Modulus1)
321 | state1start = 1; // skip impossible state1 values
322 |
323 | if (output1 != wildcard)
324 | {
325 | uint offset = NextFromStates(state0, state1start, (uint)limit); // determine how far off current output is from second output
326 | offset = offset + ((offset < output1) ? (uint)limit : 0) - (uint)output1; // compute (offset - output1) because State1 is subtracted from State0
327 |
328 | if (offset >= 2) // skip ahead very conservatively to vicinity of a block of consecutive states that will produce 'output1'
329 | state1start += (offset - 1) * blocksize - (_Modulus - _Modulus1 + 1); // don't let skipped states cause us to miss any viable candidates
330 |
331 | while (NextFromStates(state0, state1start, (uint)limit) != output1) // TO-DO TODO: binary seek, starting at +'blocksize'
332 | state1start++;
333 | }
334 |
335 | uint state1end = (state0 + _Modulus - difflo); // State1 such that (State0 - State1) == difflo; subtract 'difflo' to get State1 upper bound
336 | if (state1end >= _Modulus)
337 | state1end -= _Modulus;
338 | if (state1end == 0 || state1end >= _Modulus1)
339 | state1end = (_Modulus1 - 1); // stop short of impossible State1 values
340 |
341 | uint state1blockstart = state1start;
342 | uint state1blockend;
343 |
344 | for (; ; ) // blocks
345 | {
346 | if (output1 != wildcard)
347 | {
348 | state1blockend = state1blockstart + blocksize; // [state1blockstart..state1blockend] is (blocksize + 1) states, to accommodate rounding variations
349 | if (state1blockend >= _Modulus)
350 | state1blockend -= _Modulus;
351 | if (state1blockend == 0 || state1blockend >= _Modulus1)
352 | state1blockend = (_Modulus1 - 1); // stop short of impossible State1 values
353 | }
354 | else
355 | {
356 | state1blockstart = state1start;
357 | state1blockend = state1end;
358 | }
359 |
360 | for (; ; ) // pieces
361 | {
362 | // brute-force State1 in two passes if its range wraps around, so that we don't have to check for zero or _Modulus1 after each increment
363 | uint state1piecestart = state1blockstart;
364 | uint state1pieceend = ((state1blockstart < state1blockend) ? state1blockend : (_Modulus1 - 1));
365 |
366 | for (uint state1 = state1piecestart; ; state1++)
367 | {
368 | this._State0 = state0; // faster than converting states to seed and seed to states via Seed()
369 | this._State1 = state1;
370 |
371 | int i;
372 | for (i = 0; i < suboutput.Length; i++)
373 | {
374 | if (this.Next(limit) != suboutput[i] && suboutput[i] != wildcard)
375 | break;
376 | }
377 |
378 | if (i == suboutput.Length) // invoke callback for seed discovery notification
379 | {
380 | uint prevstate0 = (uint)(((ulong)state0 * _Multiplier0Inverse) % _Modulus);
381 | uint prevstate1 = (uint)(((ulong)state1 * _Multiplier1Inverse) % _Modulus1);
382 |
383 | args.EventType = RecoverSeedEventType.SeedDiscovered;
384 | args.Seed = SeedFromStates(prevstate0, prevstate1);
385 | // TO-DO TODO: estimate progress/total somehow? would be easy if not for skipped State1 candidates
386 | args.CurrentAttempts = 0;
387 | args.TotalAttempts = 0;
388 |
389 | callback(args);
390 |
391 | if (args.Cancel)
392 | return false;
393 | }
394 |
395 | if (state1 == state1pieceend) // check only after body of loop so that 'state1pieceend' will get tested
396 | break;
397 | } //for(state1)
398 |
399 | if (state1blockstart > state1blockend)
400 | state1blockstart = 1; // now brute-force the second (post-zero) piece
401 | else break;
402 | } //for(pieces)
403 |
404 | if (output1 != wildcard)
405 | {
406 | if (state1blockstart <= state1end && state1blockend >= state1end)
407 | break;
408 |
409 | state1blockstart = state1blockend + ((uint)(limit - 1) * blocksize); // skip ahead by a conservative underestimate
410 | if (state1blockend <= state1end && state1blockstart >= state1end)
411 | break;
412 | // 'state1blockend' will be set at the top of the loop body
413 |
414 | while (NextFromStates(state0, state1blockstart, (uint)limit) != output1) // TO-DO TODO: binary seek?
415 | state1blockstart++;
416 | }
417 | else break;
418 | } //for(blocks)
419 | } //for(state0)
420 | } //unchecked
421 |
422 | return true;
423 | } //PrngMssql.RecoverSeed
424 |
425 | } //class PrngMssql
426 |
427 | } //namespace Cylance.Research.Prangster
428 |
--------------------------------------------------------------------------------
/PRNGs/PrngMsvcrt.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | using System;
32 |
33 | namespace Cylance.Research.Prangster
34 | {
35 |
36 | public sealed class PrngMsvcrt : PrngMsvcrtBase
37 | {
38 |
39 | public PrngMsvcrt()
40 | : base()
41 | {
42 | }
43 |
44 | public PrngMsvcrt(ulong seed)
45 | : base(seed)
46 | {
47 | }
48 |
49 | public override ulong Next(ulong limit)
50 | {
51 | unchecked // disable arithmetic checks for performance
52 | {
53 | uint next = (uint)this.Next();
54 |
55 | if (limit != 0 && limit < _OutputDivisor)
56 | next %= (uint)limit;
57 |
58 | return next;
59 | }
60 | }
61 |
62 | public override ulong Previous(ulong limit)
63 | {
64 | unchecked // disable arithmetic checks for performance
65 | {
66 | uint current = (uint)this.Previous();
67 |
68 | if (limit != 0 && limit < _OutputDivisor)
69 | current %= (uint)limit;
70 |
71 | return current;
72 | }
73 | }
74 |
75 | protected override bool RecoverSeed(ulong seedStart, ulong seedEnd, ulong seedIncrement, ulong[] output, ulong limit, ulong wildcard, RecoverSeedCallback callback, ulong progressInterval)
76 | {
77 | if (output.Length < 2 || output[0] >= _OutputDivisor || output[0] == wildcard || seedStart != this.MinimumSeed || seedIncrement != 1 || limit == 0 || limit > _OutputDivisor)
78 | return base.RecoverSeed(seedStart, seedEnd, seedIncrement, output, limit, wildcard, callback, progressInterval);
79 |
80 | if (seedStart > seedEnd || seedIncrement == 0)
81 | return false;
82 |
83 | RecoverSeedEventArgs args = new RecoverSeedEventArgs();
84 |
85 | unchecked // disable arithmetic checks for performance
86 | {
87 | // operate on output suffix of length N - 1 so we can fix middle portion of seed to output[0]
88 | ulong[] suboutput = new ulong[output.Length - 1];
89 | Array.Copy(output, 1, suboutput, 0, output.Length - 1);
90 |
91 | uint seedtopincr = (uint)limit * _DiscardDivisor;
92 |
93 | // Modulus is a power of 2, so GCD(limit, Modulus) is greatest power-of-two factor of limit
94 | uint subgenoutputmask = ((uint)limit ^ ((uint)limit - 1)) >> 1;
95 | uint subgensize = (subgenoutputmask + 1) * _DiscardDivisor; // GCD(limit, Modulus) * DiscardDivisor
96 |
97 | // fix bottom portion by brute-forcing subgenerator
98 | uint subseed;
99 | for (subseed = 0; subseed < subgensize; subseed++)
100 | {
101 | if (subgenoutputmask != 0) // if limit is odd, we can't check this subgenerator seed against LSB(s) of output; we must test all possibilities below
102 | {
103 | this.Seed(subseed);
104 |
105 | int i;
106 | for (i = 0; i < suboutput.Length; i++)
107 | {
108 | // we can do Next() instead of Next(limit) for speed, since either way the remainder modulo power-of-two is preserved
109 | if ((this.Next(limit) & subgenoutputmask) != (suboutput[i] & subgenoutputmask) && suboutput[i] != wildcard)
110 | break;
111 | }
112 |
113 | if (i < suboutput.Length)
114 | continue;
115 | }
116 |
117 | // MSB(s) of subseed will contain LSB(s) of output[0], so | instead of + to keep duplicate bit(s) from interfering
118 | for (uint seed = ((uint)output[0] * _DiscardDivisor) | subseed; seed <= seedEnd; seed += seedtopincr)
119 | {
120 | this.Seed(seed);
121 |
122 | int i;
123 | for (i = 0; i < suboutput.Length; i++)
124 | {
125 | if (this.Next(limit) != suboutput[i] && suboutput[i] != wildcard)
126 | break;
127 | }
128 |
129 | if (i == suboutput.Length) // invoke callback for seed discovery notification
130 | {
131 | args.EventType = RecoverSeedEventType.SeedDiscovered;
132 | args.Seed = PreviousState(seed);
133 | // TO-DO TODO: estimate progress/total somehow?
134 | args.CurrentAttempts = 0;
135 | args.TotalAttempts = 0;
136 |
137 | callback(args);
138 |
139 | if (args.Cancel)
140 | return false;
141 | }
142 | } //for(seed<=seedEnd)
143 | } //for(subseed.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | // Based on Microsoft Visual Studio 2012 CRT rand.c, which bears the following copyright notice:
32 | // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
33 |
34 | using System;
35 |
36 | namespace Cylance.Research.Prangster
37 | {
38 |
39 | public abstract class PrngMsvcrtBase : PrngLcgBase
40 | {
41 |
42 | private uint _State;
43 |
44 | protected const uint _Multiplier = 214013;
45 | protected const uint _Increment = 2531011;
46 | protected const uint _Modulus = 0x80000000; // 31 bits (technically 32 bits, but MSB never influences output)
47 | protected const uint _OutputDivisor = 0x8000; // & 0x7FFF
48 | protected const uint _DiscardDivisor = 0x10000; // >> 16
49 |
50 | private const uint _MultiplierInverse = 968044885; // multiplicative inverse of _Multiplier modulo _Modulus
51 | private const uint _IncrementInverseMulInv = 561051201; // additive inverse of _Increment modulo _Modulus, multiplied by _MultiplierInverse
52 |
53 | public PrngMsvcrtBase()
54 | {
55 | }
56 |
57 | public PrngMsvcrtBase(ulong seed)
58 | : this()
59 | {
60 | this.Seed(seed);
61 | }
62 |
63 | public override ulong MinimumSeed
64 | {
65 | get
66 | {
67 | return 0;
68 | }
69 | }
70 |
71 | public override ulong MaximumSeed
72 | {
73 | get
74 | {
75 | return (_Modulus - 1);
76 | }
77 | }
78 |
79 | public override ulong Multiplier
80 | {
81 | get
82 | {
83 | return _Multiplier;
84 | }
85 | }
86 |
87 | public override ulong Increment
88 | {
89 | get
90 | {
91 | return _Increment;
92 | }
93 | }
94 |
95 | public override ulong Modulus
96 | {
97 | get
98 | {
99 | return _Modulus;
100 | }
101 | }
102 |
103 | public override ulong DiscardDivisor
104 | {
105 | get
106 | {
107 | return _DiscardDivisor;
108 | }
109 | }
110 |
111 | public override ulong OutputDivisor
112 | {
113 | get
114 | {
115 | return _OutputDivisor;
116 | }
117 | }
118 |
119 | public override void Seed(ulong seed)
120 | {
121 | //if (seed < 0 || seed > (_Modulus - 1))
122 | // throw new ArgumentOutOfRangeException("seed must be a 31-bit integer");
123 |
124 | unchecked // disable arithmetic checks for performance
125 | {
126 | this._State = ((uint)seed & 0x7FFFFFFF);
127 | }
128 | }
129 |
130 | protected static uint NextState(uint state)
131 | {
132 | return unchecked(((state * _Multiplier) + _Increment) & 0x7FFFFFFF);
133 | }
134 |
135 | protected static uint NextFromState(uint state)
136 | {
137 | return (PrngMsvcrtBase.NextState(state) >> 16); // & 0x7FFF
138 | }
139 |
140 | public override ulong Next()
141 | {
142 | uint next = PrngMsvcrtBase.NextState(this._State);
143 | this._State = next;
144 | return (next >> 16); // & 0x7FFF
145 | }
146 |
147 | public override bool CanReverse
148 | {
149 | get
150 | {
151 | return true;
152 | }
153 | }
154 |
155 | protected static uint PreviousState(uint state)
156 | {
157 | unchecked // disable arithmetic checks for performance
158 | {
159 | uint diff = (state - _Increment);
160 | return (diff * _MultiplierInverse) & 0x7FFFFFFF; // we can let multiplication overflow 32 bits because modulus is a power of two
161 | }
162 | }
163 |
164 | public override ulong Previous()
165 | {
166 | uint current = this._State;
167 | this._State = PreviousState(current);
168 | return (current >> 16); // & 0x7FFF
169 | }
170 |
171 | public override bool CanSeek
172 | {
173 | get
174 | {
175 | return true;
176 | }
177 | }
178 |
179 | public override void SeekAhead(ulong offset)
180 | {
181 | this._State = unchecked((uint)SeekState(this._State, offset, _Multiplier, _Increment, _Modulus));
182 | }
183 |
184 | public override void SeekBack(ulong offset)
185 | {
186 | this._State = unchecked((uint)SeekState(this._State, offset, _MultiplierInverse, _IncrementInverseMulInv, _Modulus));
187 | }
188 |
189 | public override ulong SeekSeedAhead(ulong seed, ulong offset)
190 | {
191 | return SeekState(seed, offset, _Multiplier, _Increment, _Modulus);
192 | }
193 |
194 | public override ulong SeekSeedBack(ulong seed, ulong offset)
195 | {
196 | return SeekState(seed, offset, _MultiplierInverse, _IncrementInverseMulInv, _Modulus);
197 | }
198 |
199 | } //class PrngMsvcrtBase
200 |
201 | } //namespace Cylance.Research.Prangster
202 |
--------------------------------------------------------------------------------
/PRNGs/PrngMsvcrtMul.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | using System;
32 |
33 | namespace Cylance.Research.Prangster
34 | {
35 |
36 | public sealed class PrngMsvcrtMul : PrngMsvcrtBase
37 | {
38 |
39 | public PrngMsvcrtMul()
40 | : base()
41 | {
42 | }
43 |
44 | public PrngMsvcrtMul(ulong seed)
45 | : base(seed)
46 | {
47 | }
48 |
49 | private static uint NextFromState(uint state, uint limit)
50 | {
51 | return unchecked((uint)(((ulong)(PrngMsvcrtBase.NextState(state) >> 16) * limit) / _OutputDivisor)); // & 0x7FFF after >> 16
52 | }
53 |
54 | public override ulong Next(ulong limit)
55 | {
56 | // disable arithmetic checks for performance
57 | return unchecked(this.Next() * limit / _OutputDivisor);
58 | }
59 |
60 | public override ulong Previous(ulong limit)
61 | {
62 | // disable arithmetic checks for performance
63 | return unchecked(this.Previous() * limit / _OutputDivisor);
64 | }
65 |
66 | protected override bool RecoverSeed(ulong seedStart, ulong seedEnd, ulong seedIncrement, ulong[] output, ulong limit, ulong wildcard, RecoverSeedCallback callback, ulong progressInterval)
67 | {
68 | if (output.Length < 2 || output[0] > (ulong.MaxValue / _OutputDivisor) || output[0] == wildcard || limit == 0 || limit > _OutputDivisor)
69 | return base.RecoverSeed(seedStart, seedEnd, seedIncrement, output, limit, wildcard, callback, progressInterval);
70 |
71 | if (seedStart > seedEnd || seedIncrement == 0)
72 | return false;
73 |
74 | unchecked // disable arithmetic checks for performance
75 | {
76 | // operate on output suffix of length N - 1 so we can fix top portion of seed to output[0]
77 | ulong[] suboutput = new ulong[output.Length - 1];
78 | Array.Copy(output, 1, suboutput, 0, output.Length - 1);
79 |
80 | ulong rangestart = ((_OutputDivisor * output[0]) + (uint)limit - 1) / (uint)limit; // add (limit - 1) to round up, to make sure 'rangestart' will produce output[0]
81 | rangestart *= _DiscardDivisor;
82 |
83 | ulong rangeend = (((_OutputDivisor * (output[0] + 1)) + (uint)limit - 1) / (uint)limit) - 1; // lowest seed that produces (output[0] + 1), then - 1
84 | rangeend = (rangeend * _DiscardDivisor) + (_DiscardDivisor - 1);
85 |
86 | if (rangestart <= seedStart)
87 | {
88 | rangestart = seedStart;
89 | }
90 | else if (seedIncrement > 1)
91 | {
92 | ulong incroffset = (rangestart - seedStart) % seedIncrement;
93 | if (incroffset != 0)
94 | rangestart += (seedIncrement - incroffset); // advance to the next multiple of 'seedIncrement' (relative to 'seedStart')
95 | }
96 |
97 | if (rangeend > seedEnd)
98 | rangeend = seedEnd;
99 |
100 | ulong output1 = ((output.Length > 2) ? output[1] : wildcard);
101 |
102 | uint blocksize = (uint)(_Modulus / ((ulong)_Multiplier * limit));
103 | if (blocksize < 2) output1 = wildcard; // don't attempt improved attack if block size is too small
104 |
105 | if (output1 == wildcard || seedIncrement != 1)
106 | {
107 | this._OriginalCallback = callback;
108 | return base.RecoverSeed(rangestart, rangeend, seedIncrement, suboutput, limit, wildcard, this.RecoverSeedCallback, progressInterval);
109 | }
110 |
111 | // otherwise, use second output to skip blocks of candidate states
112 |
113 | RecoverSeedEventArgs args = new RecoverSeedEventArgs();
114 |
115 | uint offset = NextFromState((uint)rangestart, (uint)limit); // determine how far off current output is from second output
116 | offset = (uint)output1 + ((output1 < offset) ? (uint)limit : 0) - offset;
117 |
118 | if (offset >= 2) // skip ahead conservatively to vicinity of a block of consecutive states that will produce 'output1'
119 | rangestart += (offset - 1) * blocksize;
120 |
121 | while (NextFromState((uint)rangestart, (uint)limit) != output1) // TO-DO TODO: binary seek, starting at +'blocksize'
122 | rangestart++;
123 |
124 | uint blockstart = (uint)rangestart;
125 | uint blockend;
126 |
127 | for (; ; )
128 | {
129 | blockend = blockstart + blocksize; // [blockstart..blockend] is (blocksize + 1) states, to accommodate rounding variations
130 | if (blockend >= rangeend) blockend = (uint)rangeend;
131 |
132 | for (uint state = blockstart; ; state++)
133 | {
134 | this.Seed(state);
135 |
136 | int i;
137 | for (i = 0; i < suboutput.Length; i++)
138 | {
139 | if (this.Next(limit) != suboutput[i] && suboutput[i] != wildcard)
140 | break;
141 | }
142 |
143 | if (i == suboutput.Length) // invoke callback for seed discovery notification
144 | {
145 | args.EventType = RecoverSeedEventType.SeedDiscovered;
146 | args.Seed = PreviousState(state);
147 | // TO-DO TODO: estimate progress/total somehow?
148 | args.CurrentAttempts = 0;
149 | args.TotalAttempts = 0;
150 |
151 | callback(args);
152 |
153 | if (args.Cancel)
154 | return false;
155 | }
156 |
157 | if (state == blockend) // check only after body of loop so that 'blockend' will get tested
158 | break;
159 | } //for(state)
160 |
161 | blockstart += ((uint)limit * blocksize);
162 | if (blockstart >= rangeend)
163 | break;
164 | // 'blockend' will be set at the top of the loop body
165 |
166 | while (NextFromState(blockstart, (uint)limit) != output1) // TO-DO TODO: binary seek?
167 | blockstart++;
168 | } //for(;;)
169 | } //unchecked
170 |
171 | return true;
172 | } //PrngMsvcrtMul.RecoverSeed
173 |
174 | private RecoverSeedCallback _OriginalCallback;
175 |
176 | private void RecoverSeedCallback(RecoverSeedEventArgs args)
177 | {
178 | if (args.EventType == RecoverSeedEventType.SeedDiscovered)
179 | args.Seed = PreviousState(unchecked((uint)args.Seed));
180 |
181 | this._OriginalCallback(args);
182 | }
183 |
184 | } //class PrngMsvcrtMul
185 |
186 | } //namespace Cylance.Research.Prangster
187 |
--------------------------------------------------------------------------------
/PRNGs/PrngMysql.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | // Based on MySQL sql/item_func.cc and mysys_ssl/my_rnd.cc, which bear the following copyright notice and license:
32 | /*
33 | Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
34 |
35 | This program is free software; you can redistribute it and/or modify
36 | it under the terms of the GNU General Public License as published by
37 | the Free Software Foundation; version 2 of the License.
38 |
39 | This program is distributed in the hope that it will be useful,
40 | but WITHOUT ANY WARRANTY; without even the implied warranty of
41 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
42 | GNU General Public License for more details.
43 |
44 | You should have received a copy of the GNU General Public License
45 | along with this program; if not, write to the Free Software
46 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
47 |
48 | using System;
49 |
50 | namespace Cylance.Research.Prangster
51 | {
52 |
53 | public sealed class PrngMysql : PrngBase
54 | {
55 |
56 | private const uint _Modulus = 0x3FFFFFFF; // = 3 * 3 * 7 * 11 * 31 * 151 * 331
57 |
58 | private uint _Seed1;
59 | private uint _Seed2;
60 |
61 | public PrngMysql()
62 | {
63 | }
64 |
65 | public PrngMysql(ulong seed)
66 | : this()
67 | {
68 | this.Seed(seed);
69 | }
70 |
71 | public override ulong MinimumSeed
72 | {
73 | get
74 | {
75 | return 0;
76 | }
77 | }
78 |
79 | public override ulong MaximumSeed
80 | {
81 | get
82 | {
83 | // _Modulus is divisible by 3, and Seed1 gets multiplied by 3 immediately,
84 | // so only Seed1 % (_Modulus / 3) matters; we restrict the seed space accordingly
85 | return ((ulong)_Modulus / 3 * (ulong)_Modulus) - 1;
86 | }
87 | }
88 |
89 | public void Seed32(uint seed) // Item_func_rand::seed_random
90 | {
91 | unchecked // disable arithmetic checks for performance
92 | {
93 | this._Seed1 = (seed * 0x10001 + 55555555) % _Modulus;
94 | this._Seed2 = (seed * 0x10000001) % _Modulus;
95 | }
96 | }
97 |
98 | public override void Seed(ulong seed) // randominit
99 | {
100 | // we treat 'seed' as a composite of the two internal, 32-bit state variables;
101 | // (Seed1 * _Modulus + Seed2) is the more compact 64-bit representation,
102 | // but (Seed1 << 32 | Seed2) might be more machine-friendly
103 |
104 | //if (seed < 0 || seed > ((ulong)_Modulus / 3 * (ulong)_Modulus) - 1)
105 | // throw new ArgumentOutOfRangeException("seed must comprise two integers each less than modulus");
106 |
107 | unchecked // disable arithmetic checks for performance
108 | {
109 | this._Seed1 = unchecked((uint)(seed / _Modulus));
110 | this._Seed2 = unchecked((uint)(seed % _Modulus));
111 | }
112 | }
113 |
114 | public override ulong Next() // my_rnd
115 | {
116 | unchecked // disable arithmetic checks for performance
117 | {
118 | // arithmetically safe, because (max * 3) + max = 0x3FFFFFFE * 4 = 0xFFFFFFF8
119 | uint next = ((this._Seed1 * 3) + this._Seed2) % _Modulus;
120 |
121 | this._Seed1 = next;
122 | this._Seed2 = (this._Seed2 + next + 33) % _Modulus;
123 |
124 | return next;
125 | }
126 | }
127 |
128 | public override ulong Next(ulong limit)
129 | {
130 | //if (limit <= 0 || limit > int.MaxValue)
131 | // throw new ArgumentOutOfRangeException("limit must be a positive 32-bit integer");
132 |
133 | unchecked // disable arithmetic checks for performance
134 | {
135 | return (this.Next() * limit) / _Modulus;
136 | }
137 | }
138 |
139 | public override bool CanReverse
140 | {
141 | get
142 | {
143 | // we can't reverse because * 3 and modulo destroy most-significant part of Seed1 (because _Modulus is divisible by 3),
144 | // and because we need that lost information to return correct take-from-top results
145 | return false;
146 | }
147 | }
148 |
149 | #if false
150 | public override ulong Previous()
151 | {
152 | uint current = this._Seed1;
153 |
154 | unchecked // disable arithmetic checks for performance
155 | {
156 | int prevseed2 = (int)(this._Seed2 - this._Seed1 - 33);
157 | while (prevseed2 < 0) prevseed2 += (int)_Modulus;
158 |
159 | int prevseed1 = (int)(this._Seed1 - prevseed2);
160 | if (prevseed1 < 0) prevseed1 += (int)_Modulus;
161 |
162 | if ((prevseed1 % 3) != 0)
163 | throw new InvalidOperationException("intermediate previous Seed1 must always be divisible by 3");
164 |
165 | this._Seed1 = (uint)(prevseed1 / 3);
166 | this._Seed2 = (uint)prevseed2;
167 |
168 | return current;
169 | }
170 | }
171 |
172 | public override ulong Previous(ulong limit)
173 | {
174 | //if (limit <= 0 || limit > int.MaxValue)
175 | // throw new ArgumentOutOfRangeException("limit must be a positive 32-bit integer");
176 |
177 | unchecked // disable arithmetic checks for performance
178 | {
179 | return (this.Previous() * limit) / _Modulus;
180 | }
181 | }
182 | #endif
183 |
184 | } //class PrngMysql
185 |
186 | } //namespace Cylance.Research.Prangster
187 |
--------------------------------------------------------------------------------
/PRNGs/PrngPureBasic.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | using System;
32 |
33 | namespace Cylance.Research.Prangster
34 | {
35 |
36 | ///
37 | /// PureBasic (RandomSeed and Random functions) PRNG.
38 | ///
39 | ///
40 | /// Appears to be based on Agner Fog's RANROT generator type B (see http://www.agner.org/random/discuss/read.php?i=138).
41 | ///
42 | public sealed class PrngPureBasic : PrngBase
43 | {
44 |
45 | private const int KK = 17;
46 |
47 | private readonly uint[] _RandBuffer1 = new uint[KK];
48 | private readonly uint[] _RandBuffer2 = new uint[KK];
49 | private int _p1, _p2;
50 |
51 | public PrngPureBasic()
52 | {
53 | }
54 |
55 | public PrngPureBasic(ulong seed)
56 | : this()
57 | {
58 | this.Seed(seed);
59 | }
60 |
61 | public override ulong MinimumSeed
62 | {
63 | get
64 | {
65 | return 0;
66 | }
67 | }
68 |
69 | public override ulong MaximumSeed
70 | {
71 | get
72 | {
73 | return uint.MaxValue;
74 | }
75 | }
76 |
77 | public override void Seed(ulong seed)
78 | {
79 | //if (seed > uint.MaxValue)
80 | // throw new ArgumentOutOfRangeException("seed must be a 32-bit integer");
81 |
82 | unchecked // disable arithmetic checks for performance
83 | {
84 | uint s = (uint)seed;
85 |
86 | for (int i = 0; i < KK; i++)
87 | {
88 | s = (s * 2891336453) + 1; // this multiplier has been attributed to Pierre L'Ecuyer
89 | this._RandBuffer1[i] = s;
90 | s = (s * 2891336453) + 1;
91 | this._RandBuffer2[i] = s;
92 | }
93 |
94 | this._p1 = 0;
95 | this._p2 = 10;
96 |
97 | for (int i = 0; i < 31; i++)
98 | this.Next();
99 | }
100 | }
101 |
102 | public override ulong Next()
103 | {
104 | unchecked // disable arithmetic checks for performance
105 | {
106 | uint x1 = this._RandBuffer1[this._p1];
107 | x1 = ((x1 >> 13) | (x1 << 19)) + this._RandBuffer1[this._p2];
108 |
109 | uint x2 = this._RandBuffer2[this._p1];
110 | x2 = ((x2 >> 5) | (x2 << 27)) + this._RandBuffer2[this._p2];
111 |
112 | this._RandBuffer1[this._p1] = x2;
113 | this._RandBuffer2[this._p1] = x1;
114 |
115 | this._p1 = (this._p1 == 0 ? KK : this._p1) - 1;
116 | this._p2 = (this._p2 == 0 ? KK : this._p2) - 1;
117 |
118 | return x1;
119 | }
120 | }
121 |
122 | public override ulong Next(ulong limit)
123 | {
124 | //if (limit <= 0 || limit > int.MaxValue)
125 | // throw new ArgumentOutOfRangeException("limit must be a positive 32-bit integer");
126 |
127 | return unchecked((this.Next() * limit) >> 32);
128 | }
129 |
130 | public override bool CanReverse
131 | {
132 | get
133 | {
134 | return true;
135 | }
136 | }
137 |
138 | public override ulong Previous()
139 | {
140 | unchecked // disable arithmetic checks for performance
141 | {
142 | if (++this._p1 == KK) this._p1 = 0;
143 | if (++this._p2 == KK) this._p2 = 0;
144 |
145 | uint x1 = this._RandBuffer2[this._p1];
146 | uint x2 = this._RandBuffer1[this._p1];
147 | uint current = x1;
148 |
149 | x1 -= this._RandBuffer1[this._p2];
150 | this._RandBuffer1[this._p1] = ((x1 << 13) | (x1 >> 19));
151 |
152 | x2 -= this._RandBuffer2[this._p2];
153 | this._RandBuffer2[this._p1] = ((x2 << 5) | (x2 >> 27));
154 |
155 | return current;
156 | }
157 | }
158 |
159 | public override ulong Previous(ulong limit)
160 | {
161 | //if (limit <= 0 || limit > int.MaxValue)
162 | // throw new ArgumentOutOfRangeException("limit must be a positive 32-bit integer");
163 |
164 | return unchecked((this.Previous() * limit) >> 32);
165 | }
166 |
167 | } //class PrngPureBasic
168 |
169 | } //namespace Cylance.Research.Prangster
170 |
--------------------------------------------------------------------------------
/PRNGs/PrngV8.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | // Implements the MWC algorithm from Google V8 v8.cc, which is subject to the following copyright and conditions:
32 | //
33 | // Copyright 2012 the V8 project authors. All rights reserved.
34 | // Redistribution and use in source and binary forms, with or without
35 | // modification, are permitted provided that the following conditions are
36 | // met:
37 | //
38 | // * Redistributions of source code must retain the above copyright
39 | // notice, this list of conditions and the following disclaimer.
40 | // * Redistributions in binary form must reproduce the above
41 | // copyright notice, this list of conditions and the following
42 | // disclaimer in the documentation and/or other materials provided
43 | // with the distribution.
44 | // * Neither the name of Google Inc. nor the names of its
45 | // contributors may be used to endorse or promote products derived
46 | // from this software without specific prior written permission.
47 | //
48 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
51 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
52 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
53 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
54 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
55 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
56 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
57 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
58 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59 |
60 | using System;
61 |
62 | namespace Cylance.Research.Prangster
63 | {
64 |
65 | public sealed class PrngV8 : PrngBase
66 | {
67 |
68 | private const uint _Multiplier0 = 18273;
69 | private const uint _Multiplier1 = 36969;
70 |
71 | private uint _State0, _State1;
72 |
73 | public PrngV8()
74 | {
75 | }
76 |
77 | public PrngV8(ulong seed)
78 | : this()
79 | {
80 | this.Seed(seed);
81 | }
82 |
83 | public override ulong MinimumSeed
84 | {
85 | get
86 | {
87 | // random_base depends on both state variables being non-zero,
88 | // although it doesn't appear to check the output of the entropy source;
89 | // yes, this minimum still allows the low uint to be zero for high uints > 1
90 | return 0x0000000100000001;
91 | }
92 | }
93 |
94 | public override ulong MaximumSeed
95 | {
96 | get
97 | {
98 | return ulong.MaxValue;
99 | }
100 | }
101 |
102 | public override void Seed(ulong seed)
103 | {
104 | //if ((seed & 0x00000000FFFFFFFFUL) == 0 || (seed & 0xFFFFFFFF00000000UL) == 0)
105 | // throw new ArgumentOutOfRangeException("seed must comprise two non-zero 32-bit integers");
106 |
107 | unchecked // disable arithmetic checks for performance
108 | {
109 | this._State0 = (uint)(seed >> 32);
110 | this._State1 = (uint)seed;
111 | }
112 | }
113 |
114 | public override ulong Next()
115 | {
116 | unchecked // disable arithmetic checks for performance
117 | {
118 | this._State0 = (_Multiplier0 * (this._State0 & 0xFFFF)) + (this._State0 >> 16);
119 | this._State1 = (_Multiplier1 * (this._State1 & 0xFFFF)) + (this._State1 >> 16);
120 |
121 | return (uint)((this._State0 << 14) + (this._State1 & 0x3FFFF));
122 | }
123 | }
124 |
125 | public override ulong Next(ulong limit)
126 | {
127 | //if (limit <= 0 || limit > int.MaxValue)
128 | // throw new ArgumentOutOfRangeException("limit must be a positive 32-bit integer");
129 |
130 | return unchecked((this.Next() * limit) >> 32);
131 | }
132 |
133 | public override bool CanReverse
134 | {
135 | get
136 | {
137 | return true;
138 | }
139 | }
140 |
141 | private static uint PreviousState0(uint state)
142 | {
143 | // many states have multiple possible previous states; we just do the best we can
144 |
145 | if (state >= (_Multiplier0 * 0x10000) - 1)
146 | {
147 | if (state <= (_Multiplier0 * 0xFFFF) + 0xFFFF)
148 | return unchecked(((state - (_Multiplier0 * 0xFFFF)) << 16) | 0xFFFF);
149 | else throw new ArgumentOutOfRangeException("No previous state exists.");
150 | }
151 |
152 | return unchecked(((state % _Multiplier0) << 16) | (state / _Multiplier0));
153 | }
154 |
155 | private static uint PreviousState1(uint state)
156 | {
157 | // many states have multiple possible previous states; we just do the best we can
158 |
159 | if (state >= (_Multiplier1 * 0x10000) - 1)
160 | {
161 | if (state <= (_Multiplier1 * 0xFFFF) + 0xFFFF)
162 | return unchecked(((state - (_Multiplier1 * 0xFFFF)) << 16) | 0xFFFF);
163 | else throw new ArgumentOutOfRangeException("No previous state exists.");
164 | }
165 |
166 | return unchecked(((state % _Multiplier1) << 16) | (state / _Multiplier1));
167 | }
168 |
169 | public override ulong Previous()
170 | {
171 | uint current0 = this._State0;
172 | uint current1 = this._State1;
173 |
174 | this._State0 = PreviousState0(current0);
175 | this._State1 = PreviousState1(current1);
176 |
177 | return (uint)((current0 << 14) + (current1 & 0x3FFFF));
178 | }
179 |
180 | public override ulong Previous(ulong limit)
181 | {
182 | //if (limit <= 0 || limit > int.MaxValue)
183 | // throw new ArgumentOutOfRangeException("limit must be a positive 32-bit integer");
184 |
185 | return unchecked((this.Previous() * limit) >> 32);
186 | }
187 |
188 | protected override bool RecoverSeed(ulong seedStart, ulong seedEnd, ulong seedIncrement, ulong[] output, ulong limit, ulong wildcard, RecoverSeedCallback callback, ulong progressInterval)
189 | {
190 | /// TO-DO TODO: make this more accurate in general, account for off-by-one (esp. in output[0] position), etc.
191 |
192 | if (output.Length < 2 || output[0] > uint.MaxValue || output[0] == wildcard || limit == 0 || limit > (ulong)uint.MaxValue + 1 || seedIncrement != 1)
193 | return base.RecoverSeed(seedStart, seedEnd, seedIncrement, output, limit, wildcard, callback, progressInterval);
194 |
195 | if (seedStart > seedEnd)
196 | return false;
197 |
198 | if (callback == null)
199 | progressInterval = 0;
200 |
201 | ulong output1 = ((output.Length > 2) ? output[1] : wildcard);
202 |
203 | uint blocksize = (uint)(0x100000000 / ((ulong)0x10000 * limit));
204 |
205 | RecoverSeedEventArgs args = new RecoverSeedEventArgs();
206 |
207 | unchecked // disable arithmetic checks for performance
208 | {
209 | // operate on output suffix of length N - 1 so we can fix middle portion of seed to output[0]
210 | ulong[] suboutput = new ulong[output.Length - 1];
211 | Array.Copy(output, 1, suboutput, 0, output.Length - 1);
212 |
213 | // lowstart..lowend define the range of values that the low 18 bits of State0 could have taken after producing the observed output[0]
214 | uint lowstart = (uint)((output[0] * 0x100000000 + (limit - 1)) / limit) >> 14;
215 | uint lowend = (uint)((((output[0] + 1) * 0x100000000 + (limit - 1)) / limit) - 1) >> 14;
216 |
217 | ulong totalcount = (ulong)(lowend - lowstart) * (((ulong)_Multiplier0 / 4) + 1);
218 | ulong totalcountdown = totalcount;
219 |
220 | ulong countdown = ((totalcountdown < progressInterval || progressInterval == 0) ? totalcountdown : progressInterval);
221 |
222 | int skip = (output1 == wildcard) ? -1 : 0;
223 | if (blocksize < 2) skip = -1; // don't attempt improved attack if block size is too small
224 |
225 | for (uint statelow = lowstart; statelow < lowend; statelow++)
226 | {
227 | ulong rangestart = ((ulong)statelow << 32) | 1;
228 | ulong rangeend = rangestart + (((ulong)_Multiplier0 / 4) << 50);
229 |
230 | for (ulong seed = rangestart; seed <= rangeend; )
231 | {
232 | uint rounds = (uint)(((rangeend - seed) >> 50) + 1);
233 | if (rounds > countdown) rounds = (uint)countdown;
234 |
235 | uint roundnum = 0;
236 |
237 | if (skip > 0)
238 | {
239 | if ((uint)skip >= rounds)
240 | {
241 | seed += 0x4000000000000 * (ulong)rounds;
242 | skip -= (int)(rounds - roundnum);
243 | roundnum = rounds;
244 | }
245 | else
246 | {
247 | roundnum = (uint)skip;
248 | seed += 0x4000000000000 * (ulong)(uint)skip;
249 | skip = 0;
250 | }
251 | }
252 |
253 | // we have the low 18 bits of State0 confined to a range, but we still need to brute-force the top 14 bits (up to Multiplier0 / 4)
254 | for (; roundnum < rounds; seed += 0x4000000000000, roundnum++)
255 | {
256 | this.Seed(seed);
257 |
258 | uint o1test = (uint)this.Next(limit);
259 | if (o1test != output1 && output1 != wildcard)
260 | {
261 | if (skip == 0)
262 | {
263 | uint diff = ((uint)output1 + (uint)limit - o1test) % (uint)limit;
264 | if (diff > 1)
265 | {
266 | skip = (int)((diff - 1) * blocksize);
267 |
268 | if ((uint)skip >= (rounds - roundnum))
269 | {
270 | seed += 0x4000000000000 * (ulong)(rounds - roundnum);
271 | skip -= (int)(rounds - roundnum);
272 | roundnum = rounds;
273 | break;
274 | }
275 |
276 | roundnum += (uint)(skip - 1);
277 | seed += 0x4000000000000 * (ulong)(uint)(skip - 1);
278 | skip = 0;
279 | }
280 | }
281 | continue;
282 | }
283 | else if (skip > 0) skip = 0;
284 |
285 | int i;
286 | for (i = 1; i < suboutput.Length; i++)
287 | {
288 | if (this.Next(limit) != suboutput[i] && suboutput[i] != wildcard)
289 | break;
290 | }
291 |
292 | if (i >= suboutput.Length) // invoke callback for seed discovery notification
293 | {
294 | args.EventType = RecoverSeedEventType.SeedDiscovered;
295 | args.Seed = unchecked(((ulong)PreviousState0((uint)(seed >> 32)) << 32) | PreviousState1((uint)seed));
296 | args.CurrentAttempts = (totalcount - totalcountdown + roundnum);
297 | args.TotalAttempts = totalcount;
298 |
299 | callback(args);
300 |
301 | if (args.Cancel)
302 | return false;
303 | }
304 | } //for(roundnum.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | using System;
32 |
33 | namespace Cylance.Research.Prangster
34 | {
35 |
36 | public sealed class PrngVbscript : PrngLcgBase
37 | {
38 |
39 | private uint _State;
40 |
41 | private const uint _Multiplier = 0x00FD43FD;
42 | private const uint _Increment = 0x00C39EC3;
43 | private const uint _Modulus = 0x01000000; // & 0x00FFFFFF (24 bits)
44 |
45 | private const uint _MultiplierInverse = 0x00093155; // multiplicative inverse of _Multiplier modulo _Modulus
46 | private const uint _IncrementInverseMulInv = 0x00CDF641; // additive inverse of _Increment modulo _Modulus, multiplied by _MultiplierInverse
47 |
48 | public PrngVbscript()
49 | {
50 | }
51 |
52 | public PrngVbscript(ulong seed)
53 | : this()
54 | {
55 | this.Seed(seed);
56 | }
57 |
58 | public override ulong MinimumSeed
59 | {
60 | get
61 | {
62 | return 0;
63 | }
64 | }
65 |
66 | public override ulong MaximumSeed
67 | {
68 | get
69 | {
70 | return (_Modulus - 1);
71 | }
72 | }
73 |
74 | public override ulong Multiplier
75 | {
76 | get
77 | {
78 | return _Multiplier;
79 | }
80 | }
81 |
82 | public override ulong Increment
83 | {
84 | get
85 | {
86 | return _Increment;
87 | }
88 | }
89 |
90 | public override ulong Modulus
91 | {
92 | get
93 | {
94 | return _Modulus;
95 | }
96 | }
97 |
98 | public override ulong DiscardDivisor
99 | {
100 | get
101 | {
102 | return 0;
103 | }
104 | }
105 |
106 | public override void Seed(ulong seed)
107 | {
108 | //if (seed < 0 || seed > (_Modulus - 1))
109 | // throw new ArgumentOutOfRangeException("seed must be a 24-bit integer");
110 |
111 | this._State = unchecked((uint)seed & 0x00FFFFFF);
112 | }
113 |
114 | public override ulong Next()
115 | {
116 | unchecked // disable arithmetic checks for performance
117 | {
118 | uint next = ((this._State * _Multiplier) + _Increment) & 0x00FFFFFF;
119 | this._State = next;
120 | return next;
121 | }
122 | }
123 |
124 | public override ulong Next(ulong limit)
125 | {
126 | //if (limit <= 0 || limit > int.MaxValue)
127 | // throw new ArgumentOutOfRangeException("limit must be a positive 32-bit integer");
128 |
129 | unchecked // disable arithmetic checks for performance
130 | {
131 | uint next = unchecked((uint)this.Next());
132 |
133 | // TO-DO TODO: emulate float rounding/imprecision instead of doing float conversion;
134 | // arises when 'limit' is not a power of two
135 | //return ((ulong)next * limit) >> 24;
136 | return (ulong)(((float)next * 0.000000059604645F) * (float)limit); // 1/16777216
137 | }
138 | }
139 |
140 | private static uint PreviousState(uint state)
141 | {
142 | return unchecked(((state - _Increment) * _MultiplierInverse) & 0x00FFFFFF);
143 | }
144 |
145 | public override ulong Previous()
146 | {
147 | uint current = (this._State & 0x00FFFFFF);
148 | this._State = PreviousState(current);
149 | return current;
150 | }
151 |
152 | public override ulong Previous(ulong limit)
153 | {
154 | unchecked // disable arithmetic checks for performance
155 | {
156 | uint current = unchecked((uint)this.Previous());
157 |
158 | // TO-DO TODO: emulate float rounding/imprecision instead of doing float conversion;
159 | // arises when 'limit' is not a power of two
160 | return (ulong)(((float)current * 0.000000059604645F) * (float)limit); // 1/16777216
161 | }
162 | }
163 |
164 | public override void SeekAhead(ulong offset)
165 | {
166 | this._State = unchecked((uint)SeekState(this._State, offset, _Multiplier, _Increment, _Modulus));
167 | }
168 |
169 | public override void SeekBack(ulong offset)
170 | {
171 | this._State = unchecked((uint)SeekState(this._State, offset, _MultiplierInverse, _IncrementInverseMulInv, _Modulus));
172 | }
173 |
174 | public override ulong SeekSeedAhead(ulong seed, ulong offset)
175 | {
176 | return unchecked((uint)SeekState(seed, offset, _Multiplier, _Increment, _Modulus));
177 | }
178 |
179 | public override ulong SeekSeedBack(ulong seed, ulong offset)
180 | {
181 | return unchecked((uint)SeekState(seed, offset, _MultiplierInverse, _IncrementInverseMulInv, _Modulus));
182 | }
183 |
184 | protected override bool RecoverSeed(ulong seedStart, ulong seedEnd, ulong seedIncrement, ulong[] output, ulong limit, ulong wildcard, RecoverSeedCallback callback, ulong progressInterval)
185 | {
186 | if (output.Length < 2 || output[0] > (ulong.MaxValue / 16777216) || output[0] == wildcard || limit == 0)
187 | return base.RecoverSeed(seedStart, seedEnd, seedIncrement, output, limit, wildcard, callback, progressInterval);
188 |
189 | if (seedStart > seedEnd || seedIncrement == 0)
190 | return false;
191 |
192 | unchecked // disable arithmetic checks for performance
193 | {
194 | // operate on output suffix of length N - 1 so we can fix top portion of seed to output[0]
195 | ulong[] suboutput = new ulong[output.Length - 1];
196 | Array.Copy(output, 1, suboutput, 0, output.Length - 1);
197 |
198 | // undershoot 'rangestart' and overshoot 'rangeend', to compensate for 1/16777216 < 0.000000059604645 < 1/16777215
199 | ulong rangestart = ((16777215 * output[0]) + (uint)limit - 1) / (uint)limit; // add (limit - 1) to round up some while remaining conservative
200 | ulong rangeend = (((16777216 * (output[0] + 1)) + (uint)limit - 1) / (uint)limit) - 1; // lowest seed that could produce (output[0] + 1), then - 1
201 |
202 | if (rangestart <= seedStart)
203 | {
204 | rangestart = seedStart;
205 | }
206 | else if (seedIncrement > 1)
207 | {
208 | ulong incroffset = (rangestart - seedStart) % seedIncrement;
209 | if (incroffset != 0)
210 | rangestart += (seedIncrement - incroffset); // advance to the next multiple of 'seedIncrement' (relative to 'seedStart')
211 | }
212 |
213 | if (rangeend > seedEnd)
214 | rangeend = seedEnd;
215 |
216 | this._OriginalCallback = callback;
217 | return base.RecoverSeed(rangestart, rangeend, seedIncrement, suboutput, limit, wildcard, this.RecoverSeedCallback, progressInterval);
218 | } //unchecked
219 | } //PrngVbscript.RecoverSeed
220 |
221 | private RecoverSeedCallback _OriginalCallback;
222 |
223 | private void RecoverSeedCallback(RecoverSeedEventArgs args)
224 | {
225 | if (args.EventType == RecoverSeedEventType.SeedDiscovered)
226 | args.Seed = PreviousState(unchecked((uint)args.Seed));
227 |
228 | this._OriginalCallback(args);
229 | }
230 |
231 | } //class PrngVbscript
232 |
233 | } //namespace Cylance.Research.Prangster
234 |
--------------------------------------------------------------------------------
/Prangster.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {4228600D-E7F4-4A99-B64E-DAA7675CA7F1}
8 | Exe
9 | Properties
10 | Cylance.Research.Prangster
11 | Prangster
12 | v2.0
13 | 512
14 |
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | true
26 |
27 |
28 | AnyCPU
29 | none
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
68 |
--------------------------------------------------------------------------------
/PrangsterApp.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
3 | For updates, please visit .
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by Cylance, Inc.
15 | 4. Neither the name of Cylance, Inc., nor the names of its contributors
16 | may be used to endorse or promote products derived from this software
17 | without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY CYLANCE, INC., ''AS IS'' AND ANY EXPRESS OR
20 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
22 | EVENT SHALL CYLANCE, INC., BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | using System;
32 | using System.Collections.Generic;
33 |
34 | namespace Cylance.Research.Prangster
35 | {
36 |
37 | public class PrangsterApp
38 | {
39 |
40 | private static string[] GetPrngNames()
41 | {
42 | List prngs = new List();
43 |
44 | foreach (Type prngtype in typeof(PrangsterApp).Assembly.GetTypes())
45 | {
46 | if (typeof(PrngBase).IsAssignableFrom(prngtype) && !prngtype.IsAbstract)
47 | prngs.Add(prngtype.Name);
48 | }
49 |
50 | prngs.Sort();
51 | return prngs.ToArray();
52 | } //PrangsterApp.GetPrngNames
53 |
54 | private static PrngBase GetPrng(string name)
55 | {
56 | try
57 | {
58 | Type prngtype = typeof(PrangsterApp).Assembly.GetType(
59 | typeof(PrngBase).Namespace + "." + name);
60 |
61 | if (!typeof(PrngBase).IsAssignableFrom(prngtype) || prngtype.IsAbstract)
62 | throw new ArgumentException();
63 |
64 | return (PrngBase)Activator.CreateInstance(prngtype, false);
65 | }
66 | catch (ArgumentException)
67 | {
68 | Console.Error.WriteLine("The specified PRNG does not exist.");
69 | }
70 |
71 | return null;
72 | } //PrangsterApp.GetPrng
73 |
74 | public static ulong[] ConvertSymbolsToNumbers(string symbols, string alphabet)
75 | {
76 | List numbers = new List(symbols.Length);
77 |
78 | for (int i = 0; i < symbols.Length; i++)
79 | {
80 | char ch = symbols[i];
81 |
82 | int j = alphabet.IndexOf(ch);
83 | if (j < 0)
84 | {
85 | if (Char.IsWhiteSpace(ch))
86 | continue;
87 |
88 | Console.Error.WriteLine("The input contains a symbol that is not in the alphabet.");
89 | return null;
90 | }
91 |
92 | if ((j + 1) < alphabet.Length && alphabet.IndexOf(ch, (j + 1)) >= 0)
93 | {
94 | Console.Error.WriteLine("Sorry, in this version the alphabet cannot contain duplicates of any symbol.");
95 | return null;
96 | }
97 |
98 | numbers.Add(unchecked((ulong)j));
99 | }
100 |
101 | return numbers.ToArray();
102 | } //PrangsterApp.ConvertSymbolsToNumbers
103 |
104 | private static void Usage()
105 | {
106 | Console.Error.WriteLine(
107 | @"Usage: {0} r
108 | {0} g
109 | {0} s
110 |
111 | Where: r recovers seeds that generate the output read from stdin
112 | (use ""echo xxx|"" or "" is positive, reproduces the next output
115 | symbol(s) generated after initiailziing to state ;
116 | if is negative, reproduces in forward order the previous
117 | - output symbol(s) generated before reaching state
118 |
119 | s seeks from by state(s) and displays the seed
120 | representing the new state; a negative seeks backward
121 |
122 | is one of the following PRNGs:
123 | {1}
124 |
125 | is a string that maps the symbols comprising the application's
126 | pseudorandom output to numbers, based on a given symbol's
127 | position in the string or the symbol at a given position",
128 | typeof(PrangsterApp).Assembly.ManifestModule.Name,
129 | String.Join("\r\n ", GetPrngNames()));
130 | } //PrangsterApp.Usage
131 |
132 | public static void Main(string[] args)
133 | {
134 | if (args.Length < 1 || String.IsNullOrEmpty(args[0]))
135 | {
136 | Usage();
137 | return;
138 | }
139 |
140 | switch (char.ToLowerInvariant(args[0][0]))
141 | {
142 | case 'r':
143 | {
144 | if (args.Length != 3 || String.IsNullOrEmpty(args[1]) || String.IsNullOrEmpty(args[2]) || !args[1].StartsWith("Prng"))
145 | {
146 | Usage();
147 | return;
148 | }
149 |
150 | PrngBase prng = GetPrng(args[1]);
151 |
152 | if (prng == null)
153 | return;
154 |
155 | string outputsymbols = Console.In.ReadToEnd();
156 |
157 | if (outputsymbols == null)
158 | {
159 | Console.Error.WriteLine("No pseudorandom output sample could be read.");
160 | return;
161 | }
162 |
163 | ulong[] outputnumbers = ConvertSymbolsToNumbers(outputsymbols, args[2]);
164 |
165 | if (outputnumbers == null)
166 | return;
167 |
168 | if (outputnumbers.Length < 1)
169 | {
170 | Console.Error.WriteLine("The pseudorandom output sample was too short.");
171 | return;
172 | }
173 |
174 | prng.RecoverSeed(
175 | outputnumbers,
176 | (ulong)args[2].Length, ulong.MaxValue,
177 | delegate(RecoverSeedEventArgs e)
178 | {
179 | if (e.EventType == RecoverSeedEventType.SeedDiscovered)
180 | Console.WriteLine(e.Seed);
181 | else Console.Error.Write('.');
182 | },
183 | 1000000);
184 | }
185 | break; //case 'r'
186 |
187 | case 'g':
188 | {
189 | ulong seed;
190 | int length;
191 |
192 | if (args.Length != 5 || String.IsNullOrEmpty(args[1]) || String.IsNullOrEmpty(args[2]) || !args[1].StartsWith("Prng") ||
193 | !ulong.TryParse(args[3], out seed) || !int.TryParse(args[4], out length) || length == 0 || (length < 0 && unchecked(-length) < 0))
194 | {
195 | Usage();
196 | return;
197 | }
198 |
199 | PrngBase prng = GetPrng(args[1]);
200 |
201 | if (prng == null)
202 | return;
203 |
204 | prng.Seed(seed);
205 |
206 | string alphabet = args[2];
207 | uint alphabetsize = (uint)alphabet.Length;
208 |
209 | char[] output;
210 |
211 | if (length >= 0)
212 | {
213 | output = new char[length];
214 |
215 | for (int i = 0; i < length; i++)
216 | output[i] = alphabet[unchecked((int)prng.Next(alphabetsize))];
217 | }
218 | else
219 | {
220 | if (!prng.CanReverse)
221 | {
222 | Console.Error.WriteLine("This PRNG does not support reversing.");
223 | return;
224 | }
225 |
226 | length = -length;
227 |
228 | output = new char[length];
229 |
230 | for (int i = length; i != 0; )
231 | output[--i] = alphabet[unchecked((int)prng.Previous(alphabetsize))];
232 | }
233 |
234 | Console.WriteLine(output);
235 | }
236 | break; //case 'g'
237 |
238 | case 's':
239 | {
240 | ulong seed;
241 | long offset;
242 |
243 | if (args.Length != 4 || String.IsNullOrEmpty(args[1]) || !args[1].StartsWith("Prng") ||
244 | !ulong.TryParse(args[2], out seed) || !long.TryParse(args[3], out offset))
245 | {
246 | Usage();
247 | return;
248 | }
249 |
250 | PrngBase prng = GetPrng(args[1]);
251 |
252 | if (prng == null)
253 | return;
254 |
255 | if (!prng.CanSeekSeed)
256 | {
257 | Console.Error.WriteLine("This PRNG does not support seed seeking.");
258 | return;
259 | }
260 |
261 | prng.Seed(seed);
262 |
263 | if (offset >= 0)
264 | seed = prng.SeekSeedAhead(seed, (ulong)offset);
265 | else seed = prng.SeekSeedBack(seed, unchecked((ulong)-offset));
266 |
267 | Console.WriteLine(seed);
268 | }
269 | break; //case 's'
270 |
271 | default:
272 | Usage();
273 | return;
274 | } //switch(args[0][0])
275 | } //PrangsterApp.Main
276 |
277 | } //class PrangsterApp
278 |
279 | } //namespace Cylance.Research.Prangster
280 |
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Prangster")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Cylance, Inc.")]
12 | [assembly: AssemblyProduct("Prangster")]
13 | [assembly: AssemblyCopyright("Copyright © 2013 Cylance, Inc.")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("53bff03e-c9e4-49d8-99fa-91d46542c52f")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | Prangster v1.0.0.0 (last updated 06/28/2013)
2 |
3 | Copyright (c) 2013 Cylance, Inc. All rights reserved.
4 | For updates, please visit .
5 |
6 |
7 | Prangster is being released in conjunction with the Black Hat USA 2013
8 | presentation "Black-Box Assessment of Pseudorandom Algorithms" by Derek Soeder,
9 | Christopher Abad, and Gabriel Acevedo of Cylance.
10 |
11 | Prangster is a utility for recovering information from pseudorandom application
12 | output generated using a pseudorandom number generator (PRNG) it recognizes.
13 | Its current functionality includes recovering an initial state or seed based on
14 | a sample of output (usually many orders of magnitude faster than naive brute-
15 | force), seeking to a future or previous state or seed, and generating the
16 | output that follows or precedes a given state or seed. For more information,
17 | please consult the presentation slides or white paper or the source code.
18 |
19 | Prangster is written in C# and targets the Microsoft .NET Framework 2.0. To
20 | build it on Windows, copy all of the source files (including the PRNGs and
21 | Properties subdirectories) into a directory, and either open the solution file
22 | (.sln) in Visual Studio 2012, or run the following command from the directory
23 | containing PrangsterApp.cs:
24 |
25 | \Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe /out:Prangster.exe *.cs PRNGs\*.cs Properties\*.cs
26 |
27 | Adjust the above path as necessary for your system; for example, the 64-bit
28 | .NET Framework (Framework64) or version 4.0 (v4.0.30319) will also work.
29 |
30 | To build Prangster with Mono, open the solution file in MonoDevelop or run the
31 | following command:
32 |
33 | /usr/bin/mcs -out:Prangster.exe *.cs PRNGs/*.cs Properties/*.cs
34 |
--------------------------------------------------------------------------------