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
  • 2 weeks later...
CodeExplorer
Posted (edited)

https://stackoverflow.com/questions/11946622/implementation-of-random-number-generator
https://stackoverflow.com/questions/37396278/how-to-generate-very-large-random-number-in-c/37396515

static unsigned int seed = 1;
void usrand (unsigned int newseed)
{
    seed = newseed; // & 0x7fffffffU
}

unsigned int urand(void) {
    seed = (seed * 1103515245U + 12345U);  //  & 0x7fffffffU
    return (unsigned int)seed;
}


// init random generator:
usrand(time(NULL));
srand(time(NULL));

But you are right, if seed is guessed all random values can be calculated.
One way may be to make seed harder to guess seed = seed^value
but don't know yet what to put as value.
 

 

Edited by CodeExplorer (see edit history)
  • Like 1
Link to post
Xyl2k
GenRandomNumbers	Proc uses ebx	pIn:DWORD,pLen:DWORD
	mov edi,pIn
	mov ebx,pLen
	.repeat
		invoke	Randomize
		mov ecx,32			; Change this number to a new Alphabet size if your gonna modify it
		xor edx,edx
		idiv ecx
		movzx eax,byte ptr [edx+B32Chars]
		stosb
		dec ebx
	.until zero?
	Ret
GenRandomNumbers endp

Randomize	Proc uses ecx
	invoke	GetTickCount
	add Rndm,eax
	add Rndm,eax
	add Rndm,'abcd'
	Rol Rndm,4
	mov eax,Rndm
;	imul eax,'seed'
	Ret
Randomize endp

not really random but do the job

numbers-letters.zip

  • Like 1
Link to post
sama
.data 
Seed dd 012345678h

RandomRange proc uses esi edi ebx _RangeLow:dword, _RangeHigh:dword
	
	mov 	esi,_RangeHigh 
	mov 	ebx,_RangeLow
	.if esi < ebx
		mov 	eax,ebx
		sub 	eax,esi
		call 	RandomInt
		add 	eax,esi
	.else
		mov 	eax,esi
		sub 	eax,ebx
		call 	RandomInt                      
		add 	eax,ebx
	.endif
	
	ret
RandomRange endp

RandomInt Proc uses ebx

	push 	ebx                             
	xor 	ebx,ebx
	imul 	edx,dword ptr[ebx+Seed],08088405h
	inc 	edx
	mov 	dword ptr[ebx+Seed],edx
	mul 	edx
	mov 	eax,edx
	pop 	ebx
	ret                                  
RandomInt endp

Randomize Proc 
	add 	esp,-8         
	push 	esp
	call 	QueryPerformanceCounter         
	test 	eax,eax
	je 	@F
       mov 	eax,dword ptr[esp]
       mov 	dword ptr[Seed],eax
	pop 	ecx
	pop 	edx
	ret
@@:
	call 	GetTickCount                    
	mov 	dword ptr[Seed],eax
	pop 	ecx
	pop 	edx
	Ret
Randomize endp 

maybe an alternative,

have a nice day

  • Like 1
Link to post
LCF-AT

Hi guys,

thanks for posting another example codes to generate some random numbers. :) At the moment I'am just generate & using random numbers for my listviews and every single entry to store them into a sturct in lparam.Some kind of unique ID to recognize the entry from any location which is needed if you work with X threads so then I just need to send the random ID / Handle / optional other info / with the threads.I thinks its a better method to do that instead sending visible entry infos like position or entry name etc which can be quickly changed by user itself durring the process.The random value is hidden and unique and in this case I just need to check the entire LV to find it each time if I wanna change / update some infos for that entry if the random value is still present.

Not sure whether its smart to G-alloc a struct of X bytes for every single LV & entry (+1000) but should be and is working fine so far.

greetz

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...