News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Function to create random strings

Started by Vortex, October 29, 2020, 07:20:20 AM

Previous topic - Next topic

Vortex

This is a function similar to Hutch's random string generator :

http://masm32.com/board/index.php?topic=8881.0

.386
.model flat,stdcall
option casemap:none

include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc
include     \masm32\include\user32.inc
include     \masm32\include\msvcrt.inc

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\user32.lib
includelib  \masm32\lib\msvcrt.lib

RandStr     PROTO :DWORD,:DWORD

.data?

buffer      db 64 dup(?)

.code

start:

    invoke  RandStr,ADDR buffer,64
    invoke  ExitProcess,0

RandStr PROC uses esi ebx string:DWORD,stringLen:DWORD

LOCAL _st:SYSTEMTIME

    invoke  GetSystemTime,ADDR _st
    movzx   ebx,SYSTEMTIME.wMilliseconds[_st]
@@:
    invoke  crt_rand
    sub     ebx,1
    jnz     @b

    mov     esi,string
    mov     edi,255
    mov     ebx,stringLen
@@:
    invoke  crt_rand
;   xor     edx,edx
;   div     edi
;   mov     BYTE PTR [esi],dl
    mov     BYTE PTR [esi],al
    add     esi,1
    sub     ebx,1
    jnz     @b
    mov     eax,string
    ret

RandStr ENDP

END start


Thanks to Hutch for the original PowerBASIC version.

jj2007

How does it work, Erol? With Masm32 "print" I get this:
¡¤ı░╩' ÏضM¶y'YB|£┴°═îç #d©ªçòL░ZìN-Öþ=▒`Ì▒ÇAÚgAÑıƒõ↑ƒ§B
  invoke  RandStr,ADDR buffer,64
  print addr buffer   
  invoke  ExitProcess,0


See also here.

hutch--

JJ,

That's what its supposed to do, generate random binary strings for things like window class names and private message strings. It is different each time the app starts which makes identifying a running app far more difficult.

jj2007

Quote from: hutch-- on October 29, 2020, 11:48:08 AMrandom binary strings for things like window class names and private message strings

Is it documented somewhere that all Windows versions tolerate non-Ascii (or non-Utf8) strings for such purposes?

If not, I would suggest something along these lines:
include \masm32\MasmBasic\MasmBasic.inc

Rand$Buffer db 21 dup(?) ; simple macro to generate random names
Rand$ MACRO
  push edi
  push ecx
  mov edi, offset Rand$Buffer
  xor ecx, ecx
  .Repeat
add Rand(26), 97 ; lowercase a-z
mov byte ptr [edi+ecx], al
inc ecx
  .Until ecx>=20
  xchg eax, edi
  pop ecx
  pop edi
  exitm <eax>
ENDM

  Init
  xor ecx, ecx
  .Repeat
PrintLine Str$(ecx), Tb$, Rand$()
inc ecx
  .Until ecx>=20
  MsgBox 0, "ok?", "Hi", MB_OK
EndOfCode


Output:
0       hgkdugsoymqlnuhekjrl
1       qjgllyaczfaqgytbcflt
2       jfpimsnesezizoxiqggj
3       uhzrgvbnekpucfixjywa
4       trmiqelwactabxvaewvf
5       jbmijqoeaiusqmijxjnf
6       ktyuyseayxfqrrnwlgfh
7       vmermmcpbnqisysjcodv
8       zbmpbvssfaalssgintim
9       vcfnbdixserndiupzhiy
10      qkqafqlkhpehfhuqxyvg
11      eztrbonqwnqtqsadmlgx
12      ivvriptscgynlspuztck
13      elzaubshhezywxceytmc
14      quflzoeqjuclbuvndeos
15      xvuirculozaoknzblxyk
16      wgsiohaskhbjuzoroatq
17      mvvxorhwgzimzhvtfwxf
18      lfmphjrukrhwtoaqcffr
19      mcogdlegsjmjfcibzkcj

jj2007

Btw all suggestions suffer from the fact that a clever coder can do an EnumWindows and find window names that contain non-Ascii characters. Even the one below is not safe in this respect: find a window whose name starts with "x", or any window containing multiple numbers, etc.

In pure Masm32 code:
include \masm32\include\masm32rt.inc
.686p

.data?
Rand$Buffer db 21 dup(?)

.code
Rand$ MACRO ; simple macro to generate random names
  rdtsc
  invoke lstrcpy, offset Rand$Buffer, str$(eax)
  mov byte ptr Rand$Buffer, "x"
  exitm <offset Rand$Buffer>
ENDM
start:
  xor ebx, ebx
  .Repeat
print str$(ebx), 9
print Rand$(), 13, 10
invoke Sleep, 100
inc ebx
  .Until ebx>=20
  MsgBox 0, "ok?", "Hi", MB_OK
  exit
end start


Output:
0       x034471557
1       x2009285427
2       x1754927414
3       x1501939927
4       x1245299944
5       x988643757
6       x731742907
7       x474656169
8       x218009469
9       x9105431
10      x96267723
11      x53192993
12      x10338773
13      x067610048
14      x324033156
15      x583438831
16      x840354643
17      x096978243
18      x1936173115
19      x1679015015


If I seriously wanted to hide my application, I would enum all active windows and randomly use one of the existing names.

hutch--

While discussing the algo type with a couple of the PB members, produced another version that produced variable length strings with numbers, upper and lower case characters excluded. I don't think it matters much, a simple one makes the window harder to find and reduced the possibility of tracking down private message strings. Note that the PB "RND" function is only a general purpose function and not suitable for encryption purposes.

' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

FUNCTION randstr() as STRING

    #REGISTER NONE

    LOCAL var  as DWORD
    LOCAL ccnt as DWORD
    LOCAL rnm  as DWORD

    ! db &H0F,&H31
    ! db &H0F,&HC8
    ! mov var, eax

    randomize var                       ' seed the PB rnd function

    src$ = ""                           ' allocate an empty basic string

    ccnt = rnd(11,71)                   ' make output variable length
    ! mov esi, ccnt

  lbl:
    rnm = rnd(1,255)

    If rnm > 47 and rnm < 58 Then       ' no numbers
      ! jmp lbl
    End If

    If rnm > 64 and rnm < 91 Then       ' no upper case
      ! jmp lbl
    End If

    If rnm > 96 and rnm < 123 Then      ' no lower case
      ! jmp lbl
    End If

    src$ = src$ + chr$(rnm)

    ! sub esi, 1
    ! jnz lbl

    FUNCTION = src$

End FUNCTION

' ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

TouEnMasm


I have used the GetSystemTime function to generate  adresses .It's a good soluce but the function
couldn't be recall  without problem's ,see microsoft.
To solve this,I have made a compound of two chains, one is given by GetSystemTime
and the oher by increment of the AAA chain.
new adress = getsystemTime chain + AA?

Fa is a musical note to play with CL

jj2007

GetSystemTime has a reasonable resolution, but rdtsc is even better:

include \masm32\include\masm32rt.inc
.686p

.data?
db ?
Rand$Buffer db 30 dup(?)

.code
Rand$ MACRO ; simple macro to generate random names
  rdtsc
  invoke lstrcpy, offset Rand$Buffer-1, str$(eax)
  rdtsc
  invoke lstrcpy, offset Rand$Buffer+8, hex$(eax)
  or dword ptr Rand$Buffer, 420042h
  and dword ptr Rand$Buffer, 0FFEFFFEFh
  or dword ptr Rand$Buffer+4, 420042h
  and dword ptr Rand$Buffer+4, 0FFEFFFEFh 
  exitm <offset Rand$Buffer>
ENDM

start:
.repeat
xor ebx, ebx
.Repeat
print str$(ebx), 9
print Rand$(), 13, 10
invoke Sleep, 40
inc ebx
.Until ebx>=20
inkey "press Ctrl C to exit"
.until 0
exit
end start


Output:
0       k5f7f0f5FA4F3148
1       b4f0g6B5004D0B01
2       b9g9g1g106885595
3       c4g7b8j90CCD2F61
4       c8c6b2g512F9DD0E
5       b0g4b3f419140F5B
6       b3j5j3c91F397BCB
7       b6c7g1j92555C449
8       c1c0c9c92B93CD29
9       c5k0c8f431D2EBDE
10      f0f5g6g6380E41C7
11      b4b9c9c03E2A07FF
12      c4g6f9j34467C7D3
13      b4k9k1f74A8165A7
14      c5b2c7g850993F0A
15      f5f6f6f856D2B51D
16      g5k3c9j85CF16098
17      f6g7b1b56348A3FB
18      g6j2j0f96965DDAF
19      j7b7k0f26F820893


The problem remains that a clever coder can do the enum and search for the pattern, in this case: "starts with a lowercase character, followed by a number". Non-Ascii characters are even easier to spot.

Vortex

Hi Jochen,

Here is another version creating strings with mixed case :

include     RandStr.inc

BUFF_SIZE   equ 64

.data?

buffer      db BUFF_SIZE dup(?)

.code

start:

    invoke  RandStr,ADDR buffer,BUFF_SIZE
    invoke  StdOut,ADDR buffer
    invoke  ExitProcess,0

RandStr PROC uses esi edi ebx string:DWORD,stringLen:DWORD

LOCAL _st:SYSTEMTIME

    invoke  GetSystemTime,ADDR _st
    movzx   ebx,SYSTEMTIME.wMilliseconds[_st]
@@:
    invoke  crt_rand
    sub     ebx,1
    jnz     @b

    mov     esi,string
    mov     edi,26
    mov     ebx,stringLen
@@:
    invoke  crt_rand
    xor     edx,edx
    div     edi
    and     eax,1
    shl     eax,5
    lea     edx,[edx+eax+65]
    mov     BYTE PTR [esi],dl
    add     esi,1
    sub     ebx,1
    jnz     @b
    mov     eax,string
    ret

RandStr ENDP

END start


Output sample :

RandStr.exe
mGNkEuFdXOtOgbgXpEyaNFetCukePZSHKlJuGgGekjdqzJeNpevQgxiEpjSrDZjA

RandStr.exe
MwzoBiWybxDUUnFSkSrsrtEKmqDCyZjEeUHMsrQCOZijIPfioNeedDpSZrNAvYmm

RandStr.exe
yLfPBNPljVRVipYamyehwQnqrqPMxUjjlOOvAOwUxwHMsNCBXCOksfzkVATXdKNl

RandStr.exe
wKbJzwucWljfrimPMYHchzRIWKBarxBgFcBceyhjUgIXWTBvTrEhbBcPXIfBxvFB

RandStr.exe
tlyhNkOaUGzqRCDDIUTeiojwayyzpVScMpSajlfVgUBfAAOvlZYlNTrKdCpwSRtE

hutch--

JJ,

If you use BSWAP EAX directly after RDTSC you get a much faster and wider change to the output number.

jj2007

@Erol: works fine :thumbsup:
@Hutch: as an attacker, you would concentrate on byte #4 then

hutch--

Byte 4 will not give you the other 3 and this is where the difficulty lies for the attacker. If you were worried about it you multi-sample then do whatever you want to make it more complex. It 64 but you simply take 2 samples and write the to the low and high DWORD respectively.

jj2007

Very nice, Nidud :thumbsup:

However, I'd prefer a runtime name generator, for obvious reasons ;-)

Vortex

Here is another version with the cryptographic functions :

include     \masm32\include\masm32rt.inc
include     \masm32\include\advapi32.inc
includelib  \masm32\lib\advapi32.lib

RandomBytes PROTO :DWORD,:DWORD

.data

.data?

buffer      db 64 dup(?)


.code

start:

    call    main
    invoke  StdOut,ADDR buffer
    invoke  ExitProcess,0

main PROC uses esi edi ebx

    invoke  RandomBytes,64,ADDR buffer

    mov     esi,OFFSET buffer
    mov     edi,26
    mov     ebx,64
@@:
    movzx   eax,BYTE PTR [esi]
    xor     edx,edx
    div     edi
    and     eax,1
    shl     eax,5
    lea     edx,[edx+eax+65]
    mov     BYTE PTR [esi],dl
    add     esi,1   
    sub     ebx,1
    jnz     @b
    ret

main ENDP

RandomBytes PROC dwLength:DWORD,pBuffer:DWORD

LOCAL hProvider:HANDLE

    invoke  CryptAcquireContext,ADDR hProvider,0,0,\
            PROV_RSA_FULL,CRYPT_VERIFYCONTEXT or CRYPT_SILENT
    invoke  CryptGenRandom,hProvider,dwLength,pBuffer
    invoke  CryptReleaseContext,hProvider,0
    ret

RandomBytes ENDP

END start

LiaoMi

Hi,

in my macro, I need to get random values, which will always be different within the macro run. There is a similar example, but the code does not want to be assembled in UASM, where can there be an error? Thanks!

;qmMDFcgHjiU2y96o@vs93fuiJodNZso4FJRyrHUZmfSZs4TxxKz7Ce4cc1@u4mix
;TeDDsTXjffOecOT4jH5NuPnufXgt@J8TA18jX1xLZptpuSgVyre48IXBxFwECW9V
;Q2Fq57gbwFV9?StZIB?QQtWGZBZyM1pZ_@q9K0Ey_T?xWwLDITLXcOpxa72iZEdz
;piPeuTB?eehJDWf3md_4QKz_xXXa_9_SqbfU7EX_50Dg0@6Jzkf@1Fe2Xe93cQF2
;KZIxs_UkQVuhWwbekgzxTEpwGXz8jbs1tYccZamaNPO2bLZsak7QtubswbYVnJau
;Hp?4uWdXf5NV1GSYs0ZbdOBDu4X9qT5M_y3DCb3ZoXEMvcoJTn?K9XAgzxXssEwN
;8iyQi8E1C3Dj_SM@FJg?t@Z9oEPnLIy1XLau0qG1NEi61ztAWQ2mgU6atY_cI_zf
;Yr4MEGWNNyFMiBsTIN5Mm_@RTs9LGnHkwppVacyC5O4ahwaX?skB2sEFMjJA1H2B
;fGxqaR@mmxsADxc8C7oz?CshpyqQbr2RtWc@Xe8v418JvCn5rnOOTyOq3g2A2bzW
;qhrY?hy066pGsN9yy2jp7Ugh6rTPYTGaH45qvqV_ZK1VwP2OAyv3RRpZ1c5QzJtN
;AM0dHg3EVX_zsA6GMlfW1rOcRK15YqzHty1vPrgdkpfbLp2vj6dJ5z4FYt@IjrqH
;fzW3ouXCudgvj3r015C7ygxvSGFVhT4p2T4CsaZDAReBlxX1XG12X?Oy9sNj8@pa
;KVbCXwEaM?5nCpwMtX9sSaqyx3VCI6epa2yct4rKBxsW3T1gJzPRTv@_JYqW04n0
;cYQ3lSEvJj97NQtpBzfnlKNY4N5Xh5rw3pp_GWoTawKNYT_wFd_ag7UT66lXsOCM
;RG9JpXoBu7LzB_As5GxeLorO9zbdUiI8CWdK3IQYpt3Bk7dEas1HvMtfQf6yymSr
;?9VmqRADSiGDlMgq8vrObibbcmR@T5ToWTPvZZljc3gV7cd@Bp_rTkvAZZDC9u7W



PCG32_STATE = 0x853c49e6748fea9b ;+ @SubStr(%@Time,7,2)

__randa macro

  local r, t, x

    PCG32_STATE = PCG32_STATE * 6364136223846793005 + 0xda3e39cb94b95bdb

    t = PCG32_STATE
    r = ( ( ( t sar 18 ) xor t ) sar 27 )
    x = t shr 59
    t = r shr x
    r = r shl ( -x and 31 )
    r = r or t
    r = r and 0x7F

    exitm<r>
    endm

__randc macro

  local a

    a = __randa()
    while a gt 'z' or \
          a lt '0' or \
          a ge ':' and a le '>' or \
          a ge '[' and a le '`' and a ne '_'
        a = __randa()
        endm

    exitm<a>
    endm

__rands macro n

  local string

    .data
    string label byte
    repeat n
      db __randc()
      endm
      db 0
    .code
    exitm<string>
    endm

    .code

main proc

    repeat 16
        printf("%s\n", &__rands(64))
        endm
    ret

main endp

    end main