Score:1

How did the VB6 PRNG generate a byte output from a specific seed, and how to replicate in C?

bo flag

I'm hoping to get some help regarding an old problem that has eluded me. I'm trying to figure out how the VB6 PRNG was used to generate a byte output from the two byte seed that the Randomize() function provided it. I'm trying to replicate the code in C and seed it with my own 2 bytes, something like 0x12FF.

I'm looking to create an 8 byte output, derived from 8x one byte outputs (as opposed to one 8-byte output) from the PRNG with a specific seed. The output would preferably be hexadecimal, as an example: FF1A2B3C4D5E6F1A

I understand that the VB6 PRNG has a massive flaw, my experiment is designed to demonstrate the flaw and replicate it to illustrate why a PRNG such as that should not be used in cryptography as it has repeatable outputs.

The only documentation I can seem to find is how to generate an integer output, which isn't useful to me unless the integer output was somehow used to generate a byte output. I'm not familiar with the outputs and would appreciate any help I can get.

The integer output example I have (taken from a Microsoft KB article, edited to include stdio.h) is below:

#include <math.h>

int main(int argc, char* argv[])
{
unsigned long       rndVal;

rndVal = 0x50000L;
int i;
float rndFloat;

for (i=0;i<8;i++)
    {
    rndVal = (rndVal * 0x43fd43fdL + 0xc39ec3L) & 0xffffffL;
    rndFloat = (float)rndVal / (float)16777216.0;
    printf("Value is %.15f\n",rndFloat);
    }
return 0;
}

And my version of the above is:

#include <stdio.h>
#include <math.h>

int main(int argc, char* argv[])
{
    int rndOut, irnd, i;
    
    const int inc = 0x01;
    
    float rndFloat;
    
    unsigned int rndVal = 0x0000;
    
    for (irnd = 0; irnd < 65536; irnd ++)
        {
        for (i=0;i<8;i++)
            {
            rndVal = (rndVal * 0x43fd43fdL + 0xc39ec3L) & 0xffffffL;
            rndFloat = (float)rndVal / (float)16777216.0;
            rndOut = (0xff * rndFloat) + 0x00;
            printf("%02X",rndOut);
            }
        printf("\n");
        rndVal += inc;
        }
return 0;
}

However, without knowing the how the VB6 PRNG did the byte output, I am unable to get seemingly similar results. I have a list of around 500 outputs from the VB6 one that I can't get to seem to match.

Any help would be greatly appreciated.

fgrieu avatar
ng flag
`rndOut = (0xff * rndFloat) + 0x00;` does not generate uniformly distributed integers in [0, 255]: the 254 bytes in [1, 254] each have probablity 1/255 rather than 1/256 as intended; while 0 and 255 share the remaining 1/255 in a manner depending on rounding mode. The canonical method to generate a byte would be `rndOut = rndVal>>16;` (without declaring or computing `rndFloat`), because `rndVal`is a 24-bit uniformly-distributed integer. As a minor aside, what `rndVal += inc;` attempts to achieve is unclear, but what it actually does is _not_ seeding the RNG with incremental values.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.