2009-08-27 8 views
5

gesetzt wurde Ich habe eine nicht verwaltete C++ - Konsolenanwendung, in der ich srand() und rand() verwende. Ich brauche das nicht um ein bestimmtes Problem zu lösen, sondern war neugierig: Wird der ursprüngliche Seed an srand() irgendwo im Speicher abgelegt, den ich abfragen kann? Gibt es eine Möglichkeit, herauszufinden, was der Samen war?Finden Sie heraus, was ein Zufallszahlengenerator in C++

Antwort

7

Der Seed muss nicht gespeichert werden, nur die letzte zurückgegebene Zufallszahl ist.

Hier ist das Beispiel aus der Man-Page:

 static unsigned long next = 1; 

     /* RAND_MAX assumed to be 32767 */ 
     int myrand(void) { 
      next = next * 1103515245 + 12345; 
      return((unsigned)(next/65536) % 32768); 
     } 

     void mysrand(unsigned seed) { 
      next = seed; 
     } 
0

Theoretisch nicht - der Keimwert den nächsten zufälligen Wert und dieser Wert zu berechnen ist (theoretisch) verwendet, um die nächste Zufallszahl an Samen und so weiter .

Sicherheitshalber, in der Lage zu sein, in den Samen (ob das Original oder ein neues) zu sehen ist ein ernstes Sicherheitsproblem, so dass ich nicht in der Lage sein sollte, in es zu suchen, obwohl es irgendwo gespeichert werden muss .

+1

Ich nehme an, dass 'sollte' sollte 'sollte nicht' (da es ist es macht nicht viel Sinn) –

+0

Ich weiß nicht, was Ihre Rand() -Funktion verwendet, aber die meisten guten halten eine Shuffle Tabelle, nicht nur ein "aktueller" Zustand. – Justin

+0

@Dan: richtig, behoben. – Guss

3

Wenn Sie einen einfachen Kongruenzgenerator haben, für die Sie mehrere Werte ergibt dies ein Gleichungssystem:

v1 = (seed * a + b) % m 
v2 = ( v1 * a + b) % m; 
v3 = ( v2 * a + b) % m; 
... 

Wenn Sie den ersten Wert kennen, können Sie in der Reihenfolge rückwärts gehen:

seed = (v1 - b)/a (mod m) 

Sie wissen nicht, den Samen einzigartig, Sie wissen es mod m (die da in der Regel in Ordnung ist (0 < Samen < m) sowieso) Wenn v1 - b negativ ist, müssen Sie Ms, bis seine positive wieder hinzufügen .

Sie könnten sich auch die Chinese Remainder Theorem ansehen, obwohl es keine exakte Übereinstimmung ist.

+1

Haben Sie gerade gesagt "einfach alle 64-Bit-Samen ausprobieren"? Wie schnell hast du einen Computer? : D –

+2

Versuchen Sie alle 64-Bit-Samen? Das sind 18.446.744.073.709.551.616 verschiedene Möglichkeiten - ein bisschen jenseits von machbar. – Eclipse

+3

Was Sie mit ein wenig Information darüber tun könnten, woher der Samen kam, ist ein paar Millionen Versuche. Oft wird srand mit der aktuellen Zeit ausgesät. Wenn Sie ungefähr wissen, wann der Generator zum ersten Mal gesetzt wurde, können Sie ziemlich genau abschätzen, was der Wert von time() zu diesem Zeitpunkt war. – Eclipse

0

Ich weiß nicht, wie hoch Ihre Assemblierungskenntnisse sind, oder ob Sie Zugriff auf die Quellcode-/Debugsymbole für die nicht verwaltete App haben, aber außerhalb dieser Art von Tricks gibt es keinen gangbaren Weg, die ursprünglicher Startwert Der ganze Sinn von Zufallszahlengeneratoren ist es, Ihnen unvorhersehbare Zahlen zu geben - die Beziehung zwischen zwei beliebigen Aufrufen von rand() sollte nicht nachvollziehbar sein. In kryptographisch starken Pseudozufallszahlengeneratoren würde es als ein schwerwiegender Fehler angesehen werden, den Startwert basierend auf einer erzeugten Zufallszahl erraten zu können.

Am einfachsten wäre es, die Anwendung unter einem Debugger zu starten und einen Haltepunkt zu setzen, wo srand() aufgerufen wird - dann schauen Sie sich einfach den übergebenen Parameter an.

Als nächstes wäre die App zu zerlegen und herauszufinden, die Umstände der srand Anruf. Es ist durchaus möglich, dass es mit der aktuellen Zeit gesetzt wird - dann können Sie eine Reihe von Vermutungen versuchen (Sie können es wahrscheinlich auf ein paar tausend oder so eingrenzen) und sehen, ob irgendwelche die gleiche Folge von Zufallszahlen geben, die die App verwendet . (Dies setzt natürlich voraus, dass Sie wissen, wie die Zufallswerte erzeugt werden). Es ist auch möglich, dass der Samen die ganze Zeit wie "0" ist.

+0

-1. rand() ist nicht kryptographisch sicher; es gibt fast immer die höherwertigen Bits einer LCG zurück. Die Ausgabe einiger Aufrufe von rand() reicht in der Regel aus, um den aktuellen Zustand abzuleiten und somit rückwärts zu arbeiten. –

Verwandte Themen