2009-08-27 31 views
5

Tôi đã có một ứng dụng giao diện C++ không được quản lý trong đó tôi đang sử dụng srand() và rand(). Tôi không cần điều này để giải quyết một vấn đề cụ thể, nhưng tò mò: là hạt giống ban đầu được truyền cho srand() được lưu trữ ở đâu đó trong bộ nhớ mà tôi có thể truy vấn? Có cách nào để tìm ra hạt giống là gì không?Tìm hiểu xem một trình tạo số ngẫu nhiên được tạo hạt giống như thế nào trong C++

Trả lời

7

Hạt giống không bắt buộc phải được lưu trữ, chỉ số ngẫu nhiên cuối cùng được trả về là.

Dưới đây là các ví dụ từ manpage:

 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

Về mặt lý thuyết, không - giá trị hạt giống được sử dụng để tính toán các giá trị ngẫu nhiên tiếp theo và giá trị đó là (theo lý thuyết) được sử dụng để gieo rắc các số ngẫu nhiên tiếp theo và vân vân .

Bảo mật khôn ngoan, có thể nhìn vào hạt giống (cho dù ban đầu hay cái mới) là một vấn đề bảo mật nghiêm trọng vì vậy tôi hy vọng bạn không thể nhìn vào nó mặc dù nó phải được lưu trữ ở đâu đó .

+1

Tôi giả định rằng 'nên' được cho là 'không nên' (vì nó không có ý nghĩa gì nhiều) –

+0

Tôi không biết hàm rand() của bạn sử dụng cái gì, nhưng hầu hết những thứ tốt đều duy trì sự xáo trộn bảng, không chỉ là trạng thái 'hiện tại'. – Justin

+0

@Dan: đúng, đã sửa. – Guss

3

Nếu bạn có một đơn giản phát congruential tuyến tính, mà bạn có nhiều giá trị này mang lại một hệ phương trình:

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

Nếu bạn biết giá trị đầu tiên, bạn có thể đi ngược theo trình tự:

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

Bạn không biết hạt giống duy nhất, bạn chỉ biết nó mod m (thường là tốt vì (0 < seed < m) anyways) Nếu v1 - b là số âm bạn cần thêm m cho đến khi tích cực lại .

Bạn cũng có thể xem Chinese Remainder Theorem, mặc dù nó không phải là kết hợp chính xác.

+1

Bạn vừa nói "chỉ cần thử tất cả các hạt 64 bit"? Bạn có tốc độ máy tính nhanh như thế nào? : D –

+2

Hãy thử tất cả các hạt 64 bit? Đó là 18.446.744.073,709,551,616 khả năng khác nhau - một chút vượt quá khả thi. – Eclipse

+3

Những gì bạn có thể làm với một chút thông tin về nơi hạt giống đến từ đâu, hãy thử một vài triệu đoán. Thường thì srand là hạt giống với thời gian hiện tại. Nếu bạn biết gần như khi máy phát điện được gieo mầm lần đầu tiên, bạn có thể đoán được giá trị của thời gian() tại thời điểm đó. – Eclipse

0

Tôi không biết mức độ thành thạo lắp ráp của bạn là gì hoặc bạn có quyền truy cập vào mã nguồn/biểu tượng gỡ lỗi cho ứng dụng không được quản lý hay không, nhưng không có cách nào khả thi để xác định giá trị hạt giống ban đầu. Toàn bộ điểm của các trình tạo số ngẫu nhiên là đưa ra một cách để cung cấp cho bạn các con số không thể đoán trước được - mối quan hệ giữa hai cuộc gọi được gọi tới rand() không nên được khấu trừ. Trong các máy phát số giả ngẫu nhiên mã hóa mạnh, nó sẽ được coi là một lỗ hổng nghiêm trọng để có thể đoán hạt giống dựa trên một số ngẫu nhiên được tạo ra.

Cách dễ nhất để làm điều đó, là khởi động ứng dụng dưới trình gỡ lỗi và đặt điểm ngắt trong đó srand() được gọi - sau đó chỉ cần nhìn vào tham số đã truyền.

Tiếp theo là để tháo rời ứng dụng và tìm hiểu các trường hợp của cuộc gọi thương hiệu. Nó hoàn toàn có thể là nó được gieo với thời gian hiện tại - sau đó bạn có thể thử một loạt các dự đoán (bạn có thể thu hẹp xuống còn vài nghìn) và xem liệu có bất kỳ chuỗi số ngẫu nhiên nào giống như ứng dụng đang sử dụng hay không . (Tất nhiên điều này giả định bạn có một số cách để biết những gì các giá trị ngẫu nhiên được tạo ra). Nó cũng có thể là hạt giống là một cái gì đó câm như '0' tất cả các thời gian.

+0

-1. rand() không an toàn về mặt mã hóa; nó hầu như luôn luôn trả về các bit bậc cao của một LCG. Đầu ra của một vài cuộc gọi đến rand() nói chung là đủ để suy ra trạng thái hiện tại và do đó làm việc ngược. –

Các vấn đề liên quan