Jump to content
Tuts 4 You

How to generate random values?


LCF-AT

Recommended Posts

LCF-AT

Hi again,

short question.I wanna create random values (0 till -1h) and found 2 C++ function called rand and srand.

https://www.cplusplus.com/reference/cstdlib/rand/

https://www.cplusplus.com/reference/cstdlib/srand/

So if I check it right then I have to call first srand with any value X as paramter and then calling rand right after.If I do that to call srand first with same value like 10h then I get a results of 5Ah back from rand function.So is it just to prevent creating same random values?Should I call it like this below each time if I need to create a random value?

.data
holder  dd FALSE


	invoke crt_srand, holder
	invoke crt_rand
	inc holder

or

	invoke crt_srand, holder
	invoke crt_rand
	mov holder, eax

Something like this?Of course I dont wanna get the same random values back.Just wanna be sure to get always diffrent values anyway how much I call the functions in a running process you know.So what do you say?

greetz

Link to post
kao

It's all explained in the document you linked to: https://www.cplusplus.com/reference/cstdlib/rand/

This algorithm uses a seed to generate the series, which should be initialized to some distinctive value using function srand.

and later in the example:

  /* initialize random seed: */
  srand (time(NULL));

  /* generate secret number between 1 and 10: */
  iSecret = rand() % 10 + 1;

That's the most common approach - initializing random number generator with the current time or output of rdtsc instruction.

 

Using counter like you suggested is not a good idea. Instead, you could call srand() just once at the beginning of your program - it's perfectly fine for simple things (but don't use it to generate password for your bank..)

  • Like 3
Link to post
LCF-AT

Hi,

still not sure how you do mean it how I should do it.

So you mean I should just call srand only once with NULL and later if I need for example diffrent random values I should just call rand alone each time?How can i be sure that I always get diffrent random values out after calling rand for x thousend times?

greetz

Link to post
kao
30 minutes ago, LCF-AT said:

I should just call srand only once with NULL

Don't call srand with zero, that will give you always the same sequence of numbers.

As I already wrote:

26 minutes ago, kao said:

That's the most common approach - initializing random number generator with the current time or output of rdtsc instruction.

 

 

15 minutes ago, LCF-AT said:

How can i be sure that I always get diffrent random values out after calling rand for x thousend times?

If you don't want to study the math behind it, just accept that as a fact. In case of generator in msvcrt.dll, it returns values between 0 and 32767, so you should get 32k different numbers out of it.

spacer.png

 

  • Like 2
Link to post
Progman

Using modulo on the RNG result introduces statistical bias.   Trimming bits is okay though.

Such RNG are not cryptographically secure either and lead to security flaws.

Seeding was traditionally done with the time(null) call as number of seconds since Jan1 1970 is practically speaking always changing at a fast enough rate.  Other sources of entropy are possible but less trivial to gather e.g. heat values from motherboard or mouse movement

  • Like 1
Link to post
fearless
include bcrypt.inc
includelib bcrypt.lib

GenRandom PROTO


GenRandom PROC    
    LOCAL dwRandom:DWORD
    
    mov dwRandom, 0
    Invoke BCryptGenRandom, NULL, Addr dwRandom, 4, BCRYPT_USE_SYSTEM_PREFERRED_RNG ;0x00000002
    mov eax, dwRandom
    ret
GenRandom ENDP

 

  • Like 3
Link to post
ToMKoL

Here is old example from WiteG site:

 

rand        proc    nBits:DWORD
    push    ebx
    push    esi
    push    ecx
    push    edx
    
    mov    ebx, nBits        ;how many bits in result: 1 to 32
    xor    esi, esi
_rand_loop:
    call    GetTickCount        ; pseudo-random
    add    eax, seed

    imul    eax, 343FDh        ; standardowa C function
    add     eax, 269EC3h        ; rand()
    mov     seed, eax        ;
    shr     eax, 10h        ;
    and     eax, 7FFFh        ;

    mov     ecx, eax        ; guess;)
    xor     edx, edx        ;
    imul    eax, ecx        ;
    imul    eax, ecx        ;
    div     dword ptr [const]    ;

    and     edx, 1            ; get zero bit

    shl    esi, 1
    or      esi, edx        ; and save as next bit in result

    dec     ebx
    jnz     _rand_loop

    mov     eax, esi

    pop    edx
    pop    ecx
    pop    esi
    pop    ebx
    ret

const    dd 0D76D7249h
seed    dd 0
rand        endp

Usage:
push 1 ;to 32
call rand

  • Like 1
Link to post
Progman

That is a linear congruential generator LCG with period of 2^16 per birthday theorem.  The multiplication addition though is fast and simple.  Generally modern contexts should have 2^64 period minimum.

Better is the famous Mersenne Twister algorithm.  I've not seen it in hand written assembler but it would be too difficult.   2^19337-1 proven periodicity though is impressive.

Not for security still.  Windows API is easiest if a secure one is needed.

 

If you need a value between 0 and x.  Determine log2 by finding the bit size.  If number from RNG truncated to bit size is still bigger than x, get another random number otherwise use it.  Now you dont cause statistical bias due to modulo.  On average 1-2 calls to get a random number depending on how far x is from Rounding up to nearest power of 2.

Edited by Progman (see edit history)
  • Like 1
Link to post
Teddy Rogers
12 hours ago, fearless said:

include bcrypt.inc
includelib bcrypt.lib

GenRandom PROTO


GenRandom PROC    
    LOCAL dwRandom:DWORD
    
    mov dwRandom, 0
    Invoke BCryptGenRandom, NULL, Addr dwRandom, 4, BCRYPT_USE_SYSTEM_PREFERRED_RNG ;0x00000002
    mov eax, dwRandom
    ret
GenRandom ENDP

 

+1 for BCryptGenRandom or the older CryptGenRandom (RtlGenRandom) API - though these older API's are now deprecated...

Ted.

  • Like 1
Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...