For newbies Only
Written by Christal
Published by Tsehp Dec 2001

Gregory Braun's

Battle Star 32
Blowfish
Card base
Crypto

Software Design

Font Show
FX Edit
Mirv 2000
Icon Extractor

Gregory Braun is an old knowledge of many crackers...

One characteristic of this developer is to propose always basic protections, without great renewal in his method

Currently, its site abounds in a plethora of its small programs having apparently, for those which I could test, ALL the same protection.
Sothat I have almost bad consciousness by writing this text Ö

In short, if one of these programs tries you, buy it, it deserves it well since time...

Last small thing, before starting.
Greg proposes two programs of cryptography on his site. One is BlowFish, and the other is Crypto on the subject of which Casimir had written a splendid tutor on the way
  of reversing the encrypted files.


Battle Star 32

The great classic, against SoftWare Designís programs, is to look for a string like:

String Resource ID=00998: "Register BattleStar 2000"
String Resource ID=05000: " Register BattleStar 2000"
String Resource ID=05001: "Software registration was successfully completed.
"After a 30 day trial you are required "
"Code"
"Company"
"Register"
"Registered User"
"This software is distributed as "
"This Software is Registered To:"
"UNREGISTERED USER"
"You have been using an unregistered "

By taking the first string, everything is already said Ö

:00406DBB 8B0D40D54100  mov  ecx, dword ptr [0041D540]
:00406DC1 85C9          test ecx, ecx
:00406DC3 7503          jne  00406DC8
:00406DC5 33C0          xor  eax, eax
:00406DC7 C3            ret

* Possible Reference to String Resource ID=00998: "Register BattleStar 2000"

[ 0041D540 ] will be used as Flag which, put at 01, shoed to you a user AD Vitam Eternam...

What is however surprising, it is that display while playing on this flag which is nowhere initialized (with 0 or other), will be different from the display of a user registered via the normal way

The Item " Register " disappeared once 01 was placed in the Flag [ 0041D540 ]. It is then enough to take a hexadecimal editor, to seek address 0041D540 and to place 01 there.

At the first launching, the software informed the base of registry by putting in the following information of recording:

[HKEY_CURRENT_USER\Software\Software by Design\BattleStar for Windows 95/NT\Registration]
"Splash"=dword:00000001
"Organization"=""
"User"=""
@="30-Day Shareware Trial Evaluation"
"Code"=dword:00000000

After that, the base of registry will display:

[HKEY_CURRENT_USER\Software\Software by Design\BattleStar for Windows 95/NT\Registration]
"Splash"=dword:00000000
"Organization"="Free"        > this two information was recovered in 
"User"="Christal"            > the base of registry, and corresponds to those
                             > which you entered at the installation of Windows
@="Registered User"
"Code"=dword:abaddeed        > we shall return on this "code" later

We could there stay here, but the next step can be funny...

The generator of Code:

The entry in the program can be done by a very classic GetDlgItemTextA:

* Reference To: USER32.GetDlgItemTextA, Ord:0104h
                                  |
:0040E15B Call dword ptr [00416290]
:0040E161 pop edi
:0040E162 pop esi
:0040E163 mov eax, 00000001
:0040E168 pop ebx
:0040E169 ret

The informations in the three fields of the Reg Box  will all be read in this routine and you will land here:

:00407852 call 0040E130                   > Get it
bla bla bla...
:0040786C cmp eax, 0119A792               > Hey, that could be a serial ...
:00407871 jne 0040788B

* Reference To: KERNEL32.lstrcpyA, Ord:0302h
:00407873 mov ebx, dword ptr [00416088]   > compares the name entered with

* Possible StringData Ref from Data Obj  ->"Gregory Braun"
:00407879 push 00418528
:0040787E push esi
:0040787F call ebx

* Possible StringData Ref from Data Obj ->"Software Design"
:00407881 push 00418518

In fact, Gregory Braun has his small personal routine...
But as it is not its name that you wish to register, I imagine that this routine interests you only moderately.

The interesting part will start here:

:0040789E push edi                            compagny entered
:0040789F push esi                            name entered
:004078A0 call 0040DD90                       entry of the generator
:004078A5 add  esp, 00000008                  restore the stack
:004078A8 cmp  ebx, eax                       serial entered and serial generated
:004078AA pop  edi                            recovers EDI on the stack
:004078AB je   004078CA                       jump Good Boy/Bad Boy
:004078AD push 0000EACF                       -> " Register BattleStar 2000"

 A visit in the call 0040DD90 is essential:

0040DD90  MOV       EAX,[ESP+04]              eax = name entered
0040DD94  PUSH      ESI                       esi = 0
0040DD95  MOV       ESI,[0041D58C]            esi = constant1 (ABADDEED)

ABADDEED is a constant placed at address:

004063CB  MOV       DWORD PTR [0041D58C],ABADDEED

And if you remember it well, it is it which is placed in the base of registry if the Flag [ 0041D540 ] is put at 01.

0040DD9B  PUSH      EAX                       push the address of the name on the stack
0040DD9C  OR        ESI,00000378              ESI becomes ABADDFFD (easy way!)
0040DDA2  CALL      0040E0C0                  routine of the generator  

The generator:


  0040E0F4  MOVSX     EBX,BYTE PTR [ECX+ESI]  EBX = 1 char of the 2ème string (7C)
  0040E0F8  MOVSX     EBP,[EDX+EAX+41A274]    EBP = 1 char of the fste string (7C)
  0040E100  IMUL      EBX,EBP                 EBX x EBP (7C x 7C = 3C10) 
  0040E103  LEA       EBP,[ECX+EDI]           EBP plays here the role of pointer
                                              1, 2, 3, 4... until concurence of the number
                                              of characters composing the size of the name
  0040E106  IMUL      EBX,EBP                 3C10 x 1
  0040E109  MOVSX     EBP,BYTE PTR [ECX]      1 char of the name (for ex: 63 for "c")
  0040E10C  IMUL      EBX,EBP                 3C10 x 63 = 173A30 -> in EBX
  0040E10F  MOV       EBP,[ESP+10]            stock the previous result in EBP
  0040E113  ADD       EBP,EBX                 add previous result to result EBX
  0040E115  INC       EDX                     inc the pointer
  0040E116  INC       ECX                     points on the next character of the name 
  0040E117  CMP       EDX,EAX                 pointer = size of the name?                  
  0040E119  MOV       [ESP+10],EBP            result calculated above is saved
  0040E11D  JL        0040E0F4                loops to start again on the following char
  0040E11F  MOV       EAX,EBP                 EAX = first calculated (in hexadecimal)
  0040E121  POP       EDI                     registers are restored
  0040E122  POP       EBP
  0040E123  POP       ESI
  0040E124  POP       EBX
  0040E125  POP       ECX
  0040E126  RET                               and here took out...

0040DDA7  MOV       ECX,[ESP+10]              to arrive here
0040DDAB  ADD       ESI,EAX                   EAX = serial + ESI = constant2 (ABADDFFD)
0040DDAD  PUSH      ECX                       ECX = compagny (if entered)
0040DDAE  CALL      0040E0C0                  second loop in the routine for the compagny
0040DDB3  ADD       ESP,08   
0040DDB6  ADD       EAX,ESI                   EAX = good serial in hexa
0040DDB8  POP       ESI                       BINGO! 
0040DDB9  RET

Itís just enough any more to enter the good serial converted into decimal, and it is Glop! Glop!

The two strings which are used for coding are:

1st chain
0041A27C 7C 6D 66 4D 31 2F 35 28-21 73 64 24 4D 71 2E 7B  |mfM1/5(!sd$Mq.{
0041A28C 73 5D 2B 73 46 6A 74 4B-70 7A 53 64 74 7A 6F 58  s]+sFjtKpzSdtzoX
0041A29C 71 6D 62 5E 41 6C 40 64-76 3A 73 3F 78 2F 00 00  qmb^Al@dv:s?x/..

2d chain
0041A2AC 7C 62 21 70 7A 2A 6C 73-3B 72 6E 7C 6C 66 24 76  |b!pz*ls;rn|lf$v
0041A2BC 69 5E 41 78 70 65 29 72-78 35 61 69 63 26 39 2F  i^Axpe)rx5aic&9/
0041A2CC 32 6D 35 6C 73 69 34 40-30 64 6D 5A 77 39 34 63  2m5lsi4@0dmZw94c
0041A2DC 6D 71 70 66 68 77 00 00-4D 41 50 49 53 65 6E 64  mqpfhw..MAPISend

Yet, it is only a trivial serial fishing...

Having downloading another of his productions, I realized that except for the constant ( the magic Number), the routine implanted in this target state identical to that of Battle stars

Icon Extractor

Except for the addresses which change, the plan is dentique as Battle stars:

:00407D8E  PUSH      EDI               EDI = compagny entered
:00407D8F  PUSH      ESI               ESI = name entered
:00407D90  CALL      0040D7C0          generator
:00407D95  ADD       ESP,08
:00407D98  CMP       EBX,EAX           comparison HEXA between serial entered and good serial
:00407D9A  POP       EDI
:00407D9B  JZ        00407DBA          jump good boy/bad boy

What have we then in variants?

And well not large thing!
The two chains of coding are identical to those of BSTAR32 and state in 0041B628
The only difference relates to the magic number:

:0040D7C0  MOV       EAX,[ESP+04]
:0040D7C4  PUSH      ESI
:0040D7C5  MOV       ESI,[00420144]    constant = ED0990DE
:0040D7CB  PUSH      EAX               initialised in 0040420B
:0040D7CC  OR        ESI,00000378      which becomes ED00993FE
:0040D7D2  CALL      0040DDC0          generator

Itís a copy/paste of the previous plan.

So that I had an idea (itís arrive to me, but not often...)

The magic figure is initialized so in BSTAR:

:004063C5 68E8030000              push 000003E8
:004063CA 50                      push eax
:004063CB C7058CD54100EDDEADAB    mov dword ptr [0041D58C], ABADDEED

And so in Icon Extractor:

:00404205 68E8030000              push 000003E8
:0040420A 50                      push eax
:0040420B C70544014200DE9009ED    mov dword ptr [00420144], ED0990DE

You see blow coming if all the last generation of Gregory's programs uses:

-The same routine of generation
-The same character strings
-The same
  68E803000050C7

??????????????????????????????????????????????????????????????????????????

Almost in a case, the chain 68E803000050C705 is common to all the programs

By looking on another piece of code

:0040DD90 8B442404                mov eax, dword ptr [esp+04]
:0040DD94 56                      push esi
:0040DD95 8B358CD54100            mov esi, dword ptr [0041D58C] > addess of Magic Number
:0040DD9B 50                      push eax
:0040DD9C 81CE78030000            or esi, 00000378

The same combination is found in EVERY case:

90 8B 44 24 04 56 8B 35

Leaving from there, it is enough to go to read the value of the magic number at the time of its initialization, then to realize a KeyMaker by using the Magic Number returned, to obtain a little programm applicable to all the Gregory Braun's softwares...

To create the dialogBox, I used Regenerator, a tool founded on Titi's site. Due to the lack of artistic sense, time, (and equipped with a laziness so big), I used a part of the handwritting Regenerator.

I know, it is bad...

Synopsis

- Open the target file
- Gets back the size of the file and creates an image in memory of it (
  MAP)
- Verify that it is the feasible, and that another file is not opened already.
- Look for the string 90 8B 44 24 04 56 8B 35 by a scan of the file beginning with the value90 h.
- If one 90h is found, verifies the validity of the next 7 values.
- If not Good, begins again the scan
- If Good, gets back the address where is initialized Magic Number
- Scan again the file in search of this address
- Control that found address is well preceded by C705
C705 (Mov Dword) 44014200 (address) DE9009E (magic Number)
- Get back the Magic Number
- UnMap the file
- Close the handle of the file
- Get the first field ( Name)
- Get the second field ( Compagny)

- Generate the serial:
- Convert the serial generated to hexa in decimal not signed
( FFFFFFFF Is as well equal to 4294967295 as to-1)
- Show the serial

.386
.MODEL flat,stdCALL

option casemap:none
assume fs:nothing

      INClude \masm32\INClude\windows.INC
      INClude \masm32\INClude\user32.INC
      INClude \masm32\INClude\kernel32.INC
      INClude \masm32\INClude\gdi32.INC
      INClude \masm32\INClude\comdlg32.INC 
      INClude \masm32\INClude\masm32.INC
      INClude \masm32\INClude\comctl32.INC
      INClude \MASM32\INCLUDE\shell32.INC
      INClude \masm32\INClude\PDBS.INC


      INCludelib \masm32\lib\user32.lib
      INCludelib \masm32\lib\kernel32.lib
      INCludelib \masm32\lib\gdi32.lib
      INCludelib \masm32\lib\comdlg32.lib 
      INCludelib \MASM32\LIB\Comctl32.lib
      INCludelib \masm32\lib\masm32.lib
      INCludelib \MASM32\LIB\shell32.lib

      DlgProc           PROTO :DWORD,:DWORD,:DWORD,:DWORD
      Aboutproc         PROTO :DWORD,:DWORD,:DWORD,:DWORD
      OpenPEFile        PROTO :DWORD,:DWORD
      ClosePEFile       PROTO :DWORD
      UnmapFiLEAndHold  PROTO :DWORD
      MapFile           PROTO :DWORD


.DATA
      Buttclass      db  "BUTTON",0
      EDItclass      db  "EDIT",0
      RGN            db  "RGN",0
      RGN1           db  "RGN1",0
      ID_Exit        equ  2086
      ID_About       equ  2087
      ID_Gen         equ  2088
      ID_Copy        equ  2084

      caption        db "Gregory Braun's Universal KeyMaker",0
      No_Name        db "Minimum one character !",0
      not_pe         db "Not a valid PE file",0
      error_open     db "No file loaded",0
      not_found      db "No Key founded",0
      PasGlop        db "Magic Number not active",0
      Found_magic    db "Magic Number founded",0
      FilterString   db "Executables Files",0,"*.exe",0
                     db "All Files",0,"*.*",0,0

      format         db "%u",0                               ; conversion in decimal not signed

string1  db 23h, 73h, 65h, 72h, 42h, 26h, 6Eh, 7Ah
         db 7Ch, 6Dh, 66h, 4Dh, 31h, 2Fh, 35h, 28h, 21h, 73h, 64h, 24h, 4Dh, 71h, 2Eh, 7Bh
         db 73h, 5Dh, 2Bh, 73h, 46h, 6Ah, 74h, 4Bh, 70h, 7Ah, 53h, 64h, 74h, 7Ah, 6Fh, 58h
         db 71h, 6Dh, 62h, 5Eh, 41h, 6Ch, 40h, 64h, 76h, 3Ah, 73h, 3Fh, 78h, 2Fh, 00     

string2  db 7Ch, 62h, 21h, 70h, 7Ah, 2Ah, 6Ch, 73h, 3Bh, 72h, 6Eh, 7Ch, 6Ch, 66h, 24h, 76h 
         db 69h, 5Eh, 41h, 78h, 70h, 65h, 29h, 72h, 78h, 35h, 61h, 69h, 63h, 26h, 39h, 2Fh 
         db 32h, 6Dh, 35h, 6Ch, 73h, 69h, 34h, 40h, 30h, 64h, 6Dh, 5Ah, 77h, 39h, 34h, 63h  
         db 6Dh, 71h, 70h, 66h, 68h, 77h, 00                                                

magic    db 8Bh, 44h, 24h, 04h, 56h, 8Bh, 35h, 00            ; chain to be founded

        key_tmp        DWORD 0
        buffer_tmp     DWORD 0
        Flag_PE        DWORD 0
        maphandle      DWORD 0
        map_ptr        DWORD 0
        size_of_file   DWORD 0
        entry          DWORD 0
        ImageBase      DWORD 0
        magic_nb       DWORD 0
        size_of_name   DWORD 0

; structure

        ofn            OPENFILENAME <>                       
        
        PEFILE struct
            pBase       DWORD     ?
            hFile       HANDLE    ?
            hMap        HANDLE    ?
        PEFILE ends

.DATA?
      
      @name          dd  80 dup (?)
      @comp          dd  80 dup (?)
      Key            dd  80 dup (?)
      Directory      db 512 dup (?)
      PE_File        db 512 dup (?)      
      
      temp           dd ?
      compteur       db ?
      desktopDC      dd ?
      isCapture      db ?
      hEDIt          dd ?
      hEDItDC        dd ?
      hEDItDC2       dd ?
      hInst          dd ?
      hRGN           dd ?
      hRGN2          dd ?
      hRGN4          dd ?
      hRGN6          dd ?
      hResource      dd ?
      ResourcESIze   dd ?
      
      CursorPos      POINT <?>
      CursorPos2     POINT <?>
      RectRgn        RECT  <?>


.CODE
start:
      INVOKE GetModuleHandle, 0
      MOV    hInst, EAX
      INVOKE DialogBoxParam,EAX, 100, 0, DlgProc,0

      INVOKE ExitProcess, 0


DlgProc proc hDlg:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD

LOCAL stEnum[8]:BYTE    ; 4 for RVA, 4 for RETurn value

      .IF uMsg==WM_COMMAND
          MOV EAX,wParam

        .IF ax==6001
              INVOKE DialogBoxParam,hInst, 102, 0, Aboutproc,0
        .ENDIF

        .IF ax==6002

             CALL   OpenDialog 

               .IF EAX == 0
                   INVOKE SetDlgItemText,hDlg,103,OFFSET error_open
                   RET
               .ENDIF  

             PUSHAD             
             INVOKE CreateFile, ADDR Directory, GENERIC_READ/
             or GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL
             PUSHAD
             INVOKE GetFileSize,EAX,NULL
             MOV    DWORD PTR [size_of_file], EAX
             POPAD
             INVOKE OpenPEFile,ADDR Directory,ADDR PE_File
             CMP    EAX,0
             JE     not_valid_pe
              
             .IF    EAX == 2
                    INVOKE SetDlgItemText,hDlg,103,OFFSET not_found
                    POPAD
                    RET
             .ENDIF
                    
             POPAD           
             MOV    BYTE PTR [Flag_PE],01
             INVOKE SetDlgItemText,hDlg,103,OFFSET Found_magic
             RET       
            
not_valid_pe:
             POPAD
             INVOKE SetDlgItemText,hDlg,103,OFFSET not_pe
             MOV    BYTE PTR [Flag_PE],00
             XOR    EAX,EAX

        .ENDIF

        .IF ax==6003
            .IF [Flag_PE] == 01
                PUSHAD

                MOV    DWORD PTR [key_tmp],0
                INVOKE RtlZeroMemory,OFFSET @name,1264
                
                INVOKE GetDlgItemText,hDlg,102,OFFSET @name,80  ; Get 80 char maxi
                MOV    DWORD PTR[size_of_name],EAX

                CMP     EAX, 00                                 ; name minimum one character
                JLE     no_gen
                LEA     EBX, OFFSET @name
                CALL    generator

                INVOKE GetDlgItemText,hDlg,104,OFFSET @comp,80
                MOV    DWORD PTR[size_of_name],EAX

                CMP    EAX,0                                    ; field "compagny" empty ?
                JE     no_comp                
                LEA    EBX, OFFSET @comp
                CALL   generator                                
no_comp:                  
                INVOKE wsprintfA,ADDR Key,ADDR format,DWORD PTR [key_tmp]   ; conversion HEX 2 ASCII

                  .IF EAX == 0
                        INVOKE SetDlgItemText,hDlg,103,OFFSET PasGlop
                  .ELSE
                        INVOKE SetDlgItemText,hDlg,103,OFFSET Key
                  .ENDIF 

                POPAD
                RET
no_gen:
                INVOKE SetDlgItemText,hDlg,103,OFFSET No_Name
            .ELSE
                INVOKE SetDlgItemText,hDlg,103,OFFSET PasGlop    
            .ENDIF 
 
        .ENDIF

        .IF ax==6004        
              INVOKE ExitProcess,NULL
        .ENDIF

;-------- Gestion des déplacements de la DialogBox -----------
;--------     Extrait d'un source de Libthium      -----------
    
      .ELSEIF uMsg==WM_MOUSEMOVE
      
          .IF isCapture==TRUE
              INVOKE InvertRgn,desktopDC,hRGN2
              INVOKE DeleteObject,hRGN2
              INVOKE CreateRectRgn,0,0,1,1
              MOV    hRGN2,EAX
              INVOKE CombineRgn,EAX,hRGN,EAX,5
              INVOKE GetCursorPos,OFFSET CursorPos2
              MOV    EAX,CursorPos2.x
              SUB    EAX,CursorPos.x
              MOV    EDX,CursorPos2.y
              SUB    EDX,CursorPos.y
              INVOKE OffsetRgn,hRGN2,EAX,EDX
              INVOKE InvertRgn,desktopDC,hRGN2
          .ENDIF
        
    .ELSEIF uMsg==WM_LBUTTONUP
    
          .IF isCapture==TRUE
              INVOKE InvertRgn,desktopDC,hRGN2
              INVOKE GetRgnBox,hRGN2,OFFSET RectRgn
              SUB    RectRgn.left,5
              SUB    RectRgn.top,38
              INVOKE MoveWindow,hDlg,RectRgn.left,RectRgn.top,400,350,1
              INVOKE DeleteObject,hRGN2
              INVOKE ReleaseCapture
              MOV    isCapture,FALSE
          .ENDIF
     
    .ELSEIF uMsg==WM_CTLCOLOREDIT
    
          INVOKE SetTextColor,wParam,0C0C0C0h
          INVOKE SetBkColor,wParam,Black
          INVOKE GetStockObject,BLACK_BRUSH
          RET
      
    .ELSEIF uMsg==WM_LBUTTONDOWN
    
          INVOKE UpdateWindow,hDlg
          INVOKE GetCursorPos,OFFSET CursorPos
          INVOKE CreateRectRgn,0,0,1,1
          MOV    hRGN2,EAX
          INVOKE CombineRgn,EAX,hRGN,EAX,5
          INVOKE GetDesktopWindow
          INVOKE GetWindowDC,EAX
          MOV    desktopDC,EAX
          INVOKE InvertRgn,desktopDC,hRGN2
          MOV    isCapture,TRUE
          INVOKE SetCapture,hDlg

    .ELSEIF uMsg==WM_CLOSE
    
          INVOKE PostQuitMessage,0
        
    .ELSEIF uMsg==WM_INITDIALOG    
; création des boutons
          INVOKE BmpButton,hDlg,287, 30,200,203,6001 ; About
          INVOKE BmpButton,hDlg,318, 83,202,201,6002 ; Search
          INVOKE BmpButton,hDlg,320,140,204,205,6003 ; Serial
          INVOKE BmpButton,hDlg, 58,118,206,207,6004 ; Exit
  
          INVOKE FindResource, 0, 170, OFFSET RGN
          MOV    hRGN, EAX
          INVOKE LoadResource, 0, EAX
          MOV    hResource, EAX
          INVOKE SizeofResource, 0, hRGN
          MOV    ResourcESIze, EAX
          INVOKE LockResource, hResource
          MOV    hResource, EAX
          INVOKE ExtCreateRegion, 0, ResourcESIze, hResource
          MOV    hRGN, EAX
          INVOKE SetWindowRgn, hDlg, hRGN, TRUE
          INVOKE SendDlgItemMessage,hDlg,102,EM_LIMITTEXT,21,0
        
    .ELSE
        XOR EAX,EAX
        RET
    .ENDIF
    
@endmsg:
      or EAX,-1    
      RET
DlgProc endp

;---------------affichage de la boite ABOUT----------------------

Aboutproc proc hwin:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
      .IF uMsg==WM_COMMAND
      
          MOV EAX,wParam
          
          .IF ax==6005
               INVOKE EndDialog,hwin,0 
               RET
          .ENDIF
    
    .ELSEIF uMsg==WM_CLOSE
        INVOKE PostQuitMessage,0
        
    .ELSEIF uMsg==WM_INITDIALOG

        INVOKE BmpButton,hwin,85,108,208,209,6005 ; Exit
        INVOKE FindResource, 0, 171, OFFSET RGN
        MOV    hRGN4, EAX
        INVOKE LoadResource, 0, EAX
        MOV    hResource, EAX
        INVOKE SizeofResource, 0, hRGN4
        MOV    ResourcESIze, EAX
        INVOKE LockResource, hResource
        MOV    hResource, EAX
        INVOKE ExtCreateRegion, 0, ResourcESIze, hResource
        MOV    hRGN4, EAX
        INVOKE SetWindowRgn, hwin, hRGN4, TRUE
        
    .ELSE
        XOR    EAX,EAX
        RET
    .ENDIF
@endmsg:
    or EAX,-1
    RET
Aboutproc endp

;---------------------Generateur de code-------------------------

generator proc

      MOV       DWORD PTR [buffer_tmp],0        ; erase memory
      MOV       ESI, DWORD PTR [magic_nb]       ; stock magic number
      CMP       ESI, 00
      JE        no_magic
      or        ESI,00000378h                   ; beginning of the generator
      PUSH      ESI
      PUSH      EBP
      LEA       ESI, OFFSET string2             
      XOR       EDX,EDX
      XOR       EDI,EDI
      INC       EDI
      SUB       ESI,EBX
      MOV       ECX,EBX
      SUB       EDI,EBX
      
loop1:
      
      MOVSX     EBX,BYTE PTR [ECX+ESI]          ; EBX = 1 char of the 2d chain
      MOVSX     EBP,BYTE PTR [EDX+EAX+string1]  ; EBP = 1 char of the 1st chain
      IMUL      EBX,EBP                         ; EBX x EBP (7C x 7C = 3C10) 
      LEA       EBP,[ECX+EDI]                   ; EBP is a pointer
      IMUL      EBX,EBP                         ; 3C10 x 1
      MOVSX     EBP,BYTE PTR [ECX]              ; 1 char of the name entered
      IMUL      EBX,EBP                         ; 3C10 x 63 = 173A30 -> in EBX
      MOV       EBP,DWORD PTR [buffer_tmp]      ; previous result in EBP
      ADD       EBP,EBX                         ; add previous result at EBX
      INC       EDX                             ; Inc the pointer
      INC       ECX                             ; next character of the name 
      CMP       EDX,EAX                         ; pointer = size of name ?                  
      MOV       DWORD PTR [buffer_tmp],EBP      ; résult calculated above is stored
      JL        loop1                           ; loop on next character
      MOV       EAX,EBP                         ; EAX = 1st serial calculated (in hexdécimal)
      POP       EBP
      POP       ESI
      CMP       DWORD PTR [@comp],0             ; if the field "compagny" is empty
      JNE       no_ADD                          ; magic number not added a 2d time
      ADD       EAX,ESI                   
no_ADD:      
      ADD       DWORD PTR [key_tmp],EAX
      
      XOR EAX, EAX
      INC EAX
RET

no_magic:
      XOR EAX, EAX

RET
generator endp

;---------------------------- Brownse ----------------------------------- 

OpenDialog    PROC hWin:DWORD

        INVOKE RtlZeroMemory,OFFSET key_tmp,80h     ; erase memory

        CMP    DWORD PTR [Directory],0              ; if a file is already open
        JE     @F
        INVOKE ClosePEFile, ADDR PE_File            ; UnMap the file
        MOV    DWORD PTR [Flag_PE], 0

 @@:    MOV    [Directory],00                       ; erase memory

        MOV  ofn.lStructSize, SIZEOF ofn
        MOV  ofn.lpstrFilter, OFFSET FilterString
        MOV  ofn.lpstrFile,   OFFSET Directory
        MOV  ofn.nMaxFile,    512
        MOV  ofn.Flags, OFN_FILEMUSTEXIST or \
                        OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
                        OFN_EXPLORER or OFN_HIDEREADONLY

        INVOKE    GetOpenFileName, OFFSET ofn       ; open the box "OpenFile"
        CMP       EAX, FALSE                        ; stores info in structure ofn
        JNZ       EndOD
        XOR       EAX,EAX
        RET
EndOD:
    RET
OpenDialog    ENDP

;--------------contrôle que le fichier est un exécutable------------------

OpenPEFile proc szName:DWORD, pPEFile:DWORD

LOCAL stEnum[8]:BYTE    ; 4 for RVA, 4 for RETurn value
    
    .IF ( EAX == INVALID_HANDLE_VALUE )       ; no handle returned by OpenFileName
       XOR EAX,EAX
       RET
    .ENDIF

    MOV    ECX, pPEFile
    MOV    (PEFILE ptr [ECX]).hFile, EAX
    INVOKE MapFile, pPEFile
    
    .IF ( !EAX )
        XOR EAX,EAX
        RET
    .ENDIF
    
    MOV    EAX, DWORD PTR [pPEFile]
    MOV    ECX, [EAX]
    
    .IF ( WORD PTR [ECX] != 'ZM' )            ; DOS header?
       XOR EAX,EAX
       RET
    .ENDIF

    MOV    EDI, ECX
    MOV    DWORD PTR [entry],EDI
    PUSH   EDI                                ; push beginning address of the target
    
    MOV    EAX, pPEFile
    MOV    EAX, (PEFILE ptr [EAX]).pBase
    ADD    EAX, (IMAGE_DOS_HEADER ptr [EAX]).e_lfanew
    
    .IF ( WORD PTR [EAX] != 'EP' )            ; PE header?
        XOR EAX,EAX
        RET
    .ENDIF

; recherche de la combinaison
; ---------------------------

      MOV    ECX, DWORD PTR [size_of_file]    ; size of target file
      POP    EDI                              ; beginning address of the target
      MOV    al, 90h                          ; 1st value to found 
loop2:
      REPNZ  SCASB
      TEST   ECX, ECX                         ; si ECX =0 -> all the file as been seen
      JNE    found1
     
      MOV    EAX,2                            ; and the value not founded
      RET                                     ; SCAS as found a 90h
      
found1:      
      XOR    EDX,EDX                          ; pointer = 0
loop3:
      MOV    bl, BYTE PTR [magic+EDX]         ; pointe on next value of the chain searched
      CMP    BYTE PTR [EDI+EDX],bl            ; if not egual EDI+pointer
      JNE    loop2                            ; found a other value 90h
      INC    EDX                              ; inc pointer
      CMP    EDX,07                           ; all value have been seen ?
      JNE    loop3                            ; verify next value


; récupération de l'adresse
;--------------------------

      ADD    EDI,  07                         ; pointe on the @ where the magic number is initialized
      MOV    ESI,  DWORD PTR [EDI]            ; get back the adresse
      MOV    DWORD PTR [buffer_tmp], ESI      ; remember the address
      
      MOV    ECX, DWORD PTR [size_of_file]    ; beguin again a scan
      MOV    EDI, DWORD PTR [entry]           ; in search of this address in the target
      MOV    al,  BYTE PTR [buffer_tmp]            
loop4:
      REPNZ  SCASB
      TEST   ECX, ECX
      JNE    found2      
      XOR    EAX,EAX
      RET      
found2:      
      XOR    EDX,EDX
loop5:
      MOV    bl,  BYTE PTR [buffer_tmp+1+EDX]
      CMP    BYTE PTR [EDI+EDX],bl
      JNE    loop4
      INC    EDX
      CMP    EDX, 03
      JNE    loop5
      
      CMP    WORD PTR [EDI-3], 05C7h          ; verify that it is indeed about the good line
      JNE    loop4

; récupération de la clé
;-----------------------

      MOV    EAX, DWORD PTR [EDI+3]           ; get back the magic number
      MOV    DWORD PTR [magic_nb],EAX         ; remember it
      MOV    EAX,1

RET
OpenPEFile endp

;-------------------------------------------------------------------------

ClosePEFile proc pPEFile:DWORD

    INVOKE UnmapFiLEAndHold, pPEFile
    MOV    EAX, pPEFile
    INVOKE CloseHandle, (PEFILE ptr [EAX]).hFile    ; close the Handle of the current target file
    RET

ClosePEFile endp

;-------------------------------------------------------------------------

UnmapFiLEAndHold proc pPEFile:DWORD

    MOV    ECX, pPEFile
    INVOKE UnmapViewOfFile, DWORD PTR [ECX]        ; UnMap the target file 
    MOV    ECX, pPEFile
    INVOKE CloseHandle, (PEFILE ptr [ECX]).hMap
    RET

UnmapFiLEAndHold endp

;-------------------------------------------------------------------------

MapFile proc pPEFile:DWORD

    MOV    EAX, pPEFile
    MOV    EAX, (PEFILE ptr [EAX]).hFile
    INVOKE CreateFileMapping, EAX, NULL, PAGE_READWRITE, 0, 0, NULL
    
    .IF ( !EAX )
        MOV    EAX, pPEFile
        INVOKE CloseHandle, (PEFILE ptr [EAX]).hFile
        RET
    .ENDIF
    
    MOV    ECX, pPEFile
    MOV    (PEFILE ptr [ECX]).hMap, EAX
    MOV    maphandle,EAX

    INVOKE MapViewOfFile, EAX, FILE_MAP_READ or FILE_MAP_WRITE, 0, 0, 0
    
    .IF ( !EAX )
        MOV    EAX, pPEFile
        INVOKE CloseHandle, (PEFILE ptr [EAX]).hMap
        INVOKE CloseHandle, (PEFILE ptr [EAX]).hFile
        RET
    .ENDIF
    
    MOV    ECX, pPEFile
    MOV    (PEFILE ptr [ECX]).pBase, EAX
    MOV    map_ptr,EAX
    
    RET

MapFile endp

end start

Have a good day

Christal