├── 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 | --------------------------------------------------------------------------------