comment %
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
                                   PEUNLOCK-NT
            decrypter for PELOCK-NT (all version known) by mARQUIS [uCF]
                         coded by xOANINO [UCF] (c) 1999
 
               (version supported are : v2.01, v2.02b, v2.03, v2.04)
 
 if someone have other versions or if this decrypter should not work for any
 reason (ie: decrypt wrong) please mail me at xoanon@popmail.com and i'll try
 to fix it.

          Cmon Marq, kick our ass again with another kewl pecrypter now !
      (and come on IRC to say hello to your UCF buddies sometimes... ehehe!)
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
%

.386P
Locals
Jumps

.model Flat, StdCall

Extrn           ExitProcess	: PROC
Extrn           CreateFileA	: PROC                
Extrn           GetFileSize     : PROC                
Extrn		SetFilePointer	: PROC
Extrn           SetEndOfFile    : PROC
Extrn		CloseHandle	: PROC
Extrn		ReadFile	: PROC
Extrn		WriteFile	: PROC
Extrn		GetCommandLineA : PROC
Extrn           MessageBeep     : PROC
Extrn           VirtualAlloc    : PROC
Extrn           VirtualFree     : PROC

.data

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
        filenamesize    dd 0
        filesize        dd 0
        filehandle      dd 0
        toread          dd 0
        headeroffset    dd 0
        lastobjoffset   dd 0
        lastobjsize     dd 0
        lastobjvirtsize dd 0
        PELOCKdirectoryoffset dd 0
        version         db 0
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
        decrsections    db 0
        decrlayer       db 0
        layers          db 0
        magicbyte       db 0
        magickey        dd 0
        EIP             dd 0
        objsize         dd 0
        objrva          dd 0
        objoffset       dd 0
        imgbase         dd 0
        importsize      dd 0
        importRVA       dd 0
        baserelocsize   dd 0
        baserelocRVA    dd 0
        objdisplacement dd 0
        objnum          dd 0

; the below values contains RVAs and sizes of IT, IAT, RSRC and TLS .
; these parts must be handled different during decryption (must be skipped)

        value1a         dd 0
        value1b         dd 0
        value2a         dd 0
        value2b         dd 0
        value3a         dd 0
        value3b         dd 0
        value4a         dd 0
        value4b         dd 0
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
        filename        db 128 dup (0)
        buffer          dd 0
        PELOCKbuf       db 4000h dup (0)
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

        logo            db 0dh,0ah
                        db "PEUNLOCK-NT úaLL VERSIONS!ú",0dh,0ah
                        db "(c) xOANINO [UCF] 1999",0dh,0ah
                        db 0dh,0ah
        logosize        EQU $-logo

        errormsg        db "ERROR: "
        errormsgsize    EQU $-errormsg

        error1          db "Usage: PEUNLCK filename.EXE",0dh,0ah
                        db "              PEUNLCK filename.DLL",0dh,0ah
        error1size      EQU $-error1

        error2          db "not found !!",0dh,0ah
        error2size      EQU $-error2
                             
        error3          db "is not encrypted with PELOCK-NT !!",0dh,0ah
        error3size      EQU $-error3

        version201      db "þ PELOCK-NT Version v2.01 found!",0d,0ah
        version201size  EQU $-version201

        version202b     db "þ PELOCK-NT Version v2.02b found!",0d,0ah
        version202bsize EQU $-version202b

        version203      db "þ PELOCK-NT Version v2.03 found!",0d,0ah
        version203size  EQU $-version203

        version204      db "þ PELOCK-NT Version v2.04 found!",0d,0ah
        version204size  EQU $-version204

        unknownver      db "!! This version of PELOCK-NT is not supported !! (send me!!!)",0d,0ah
        unknownversize  EQU $-unknownver

        infos1          db "þ Decrypting PELOCK-NT layer           : "
        infos1size      EQU $-infos1

        infos2          db "þ File succesfully decrypted and PE rebuilded !",0dh,0ah
        infos2size      EQU $-infos2

        infos3          db "þ Magic decryption key                 : "
        infos3size      EQU $-infos3

        infos4          db "þ Original entrypoint RVA in this layer: "
        infos4size      EQU $-infos4

        infos5          db "þ Sections decrypted in this layer     : "
        infos5size      EQU $-infos5

        carriage        db 0dh,0ah

        hex             db "h"


;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

.code
        Include Console.inc     ; thanx to Acpizzo :)
        Include Numbers.inc     ; thanx to Stone :)
        include Imghdr.inc      ; thanx to NetWalker, modified by me :)
        include Myinc.inc       ; brutally ripped from w32.inc

Main:

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                       Get commandline and stuff
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

     CALL       Init_Console                    ; initialize console output
     Write_Console <offset logo> <logosize>     ; show lil' logo :)
     CALL       GetCommandLineA
     mov edi, eax                               ; edi points to commandline
     push edi                                   ; save commandline for later usage
     mov ecx, -1                                ; calculate length
     mov al, 0
     repnz scasb
     not ecx                                    ; ecx = length of commandline
     pop edi                                    ; get back commandline
     mov al, 20h                                ; hunt for spaces
     repnz scasb
     cmp byte ptr [edi], 0                      ; does an argument is passed ?
     jz NoCommandLine                           
     push edi                                   ; save offset
     mov ecx, -1                                ; get argument length
     mov al, 0
     repnz scasb
     not ecx                                    ; ecx = filename length
     mov [filenamesize],ecx                     ; store for (eventual) errormessage
     pop edi                                    ; restore offset
     mov esi, edi
     mov edi, offset filename                   ; get filename
     repnz movsb

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                       Open file in read/write mode
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Begin:
     mov dword ptr [objnum], 0                  ; set them to zero
     mov dword ptr [objdisplacement], 0         ; (for multiple layers )
     mov byte ptr [decrsections], 0  

     push 0                                     ; push the required attributes
     push FILE_ATTRIBUTE_NORMAL
     push OPEN_EXISTING
     push 0
     push FILE_SHARE_READ
     push GENERIC_READWRITE                     ; read and write enabled        
     push offset filename
     CALL       CreateFileA                     ; check for file existance
     cmp eax, -1
     jz         FileNotFound
     mov [filehandle], eax                      ; store filehandle

     push offset filesize
     push eax
     CALL GetFileSize                           ; get size of file

     mov [filesize], eax                        ; store filesize

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                       gather infos from the PE header
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

     push FILE_BEGIN                            ; position file to the start
     push 0
     push 03ch                                  ; to the offset to PE header ($3c)
     push filehandle
     CALL       SetFilePointer

     push 0
     push offset toread
     push 4
     push offset headeroffset                   ; this contains the offset to PE header
     push filehandle
     CALL       ReadFile                      

     push FILE_BEGIN                            ; beginning of file again
     push 0
     push headeroffset                          ; to the offset of PE header
     push filehandle
     CALL       SetFilePointer

     push 0
     push offset toread
     push 0f8h                                  ; size of "main" header w/o objtable and stuff
     push offset PEheader                       ; read here
     push filehandle
     CALL       ReadFile                      

     cmp word ptr [PEheader+0f6h], 1000h   ; check if its PELOCKNT-ed, this
     jnz NoPELock                          ; is a propertary flag for PELOCK-NT  

     movzx eax, word ptr [PEheader+0f4h]   ; layers of encryption    
     mov [layers],al                       ; store # of layers
     inc byte ptr [decrlayer]              ; increment number of layers decrypted

     push 0
     push offset toread                         ; now we read the rest of the header
     push 04000h                                ; $4000 bytes to be sure
     push offset obj&stuff                      ; we read object table and stuff
     push filehandle
     CALL       ReadFile

     mov edi, offset obj&stuff                  ; objects table here
     movzx eax, [NumberOfSections]              ; get number of sections
     sub eax, 1                                 ; .PELOCKNT object
     mov edx, IMAGE_SIZEOF_SECTION_HEADER
     mul edx                                    
     add edi, eax                               ; beginning of last object
     mov [PELOCKdirectoryoffset], edi           ; store this (to delete object entry at the end)
     mov ecx, [edi+14h]
     mov [lastobjoffset],ecx                    ; get last object offset
     mov ecx, [edi+10h]                         ; get last object raw size
     mov [lastobjsize], ecx
     mov ecx, [edi+8]
     mov [lastobjvirtsize], ecx                 ; get last object virtualsize

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                       Read .PELOCKNT object     
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

     push FILE_BEGIN                            ; beginning of file again
     push 0
     push lastobjoffset                         ; .PELOCKNT offset 
     push filehandle
     CALL       SetFilePointer

     push 0
     push offset toread
     push lastobjsize                           ; size of .PELOCKNT object
     push offset PELOCKbuf                      ; read whole object here
     push filehandle
     CALL       ReadFile                      

     mov esi, offset PELOCKbuf
     cmp dword ptr [esi+8], 0EB01EB1Eh         ; check if PELOCK-NT v2.01
     jz isv201
     cmp dword ptr [esi+8], 01EBEB20h          ; check if PELOCK-NT v2.02b
     jz isv202
     cmp dword ptr [esi+8], 0EB9CC720h         ; check if PELOCK-NT v2.03
     jz isv203
     cmp dword ptr [esi+8], 09CEA20CDh         ; check if PELOCK-NT v2.04
     jz isv204
     jmp unknownversion                         ; version not supported (does it exists ??)

isv201:
     mov byte ptr [version],1                   ; v2.01
     mov eax, offset version201
     mov ecx, version201size
     jmp showversioninfo

isv202:
     mov byte ptr [version],2                   ; v2.02b
     mov eax, offset version202b
     mov ecx, version202bsize
     jmp showversioninfo

isv203:
     mov byte ptr [version],3                   ; v2.03
     mov eax, offset version203
     mov ecx, version203size
     jmp showversioninfo

isv204:
     mov byte ptr [version],4                   ; v2.04 
     mov eax, offset version204
     mov ecx, version204size
     jmp showversioninfo

showversioninfo:
     Write_Console <eax> <ecx>                  ; show version infos :)

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;   Decrypt PELOCKNT loader to obtain the magic key and the original EIP
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

     Write_Console <offset infos1> <infos1size> ; show layer # during decryption
     movzx eax, decrlayer
     call Hex2Dec   
     Write_Console <offset carriage> <2>

     mov esi, offset PELOCKbuf
     xor eax,eax

     cmp byte ptr [version],1           ; check if version 2.01
     jz v201part1
     cmp byte ptr [version],2           ; check if version 2.02b
     jz v202part1
     cmp byte ptr [version],3           ; check if version 2.03
     jz v203part1
     cmp byte ptr [version],4           ; check if version 2.04
     jz v204part1

v201part1:
     movzx edx, byte ptr [esi+07ah]     ; first magic value for v2.01
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 0a1h                      ; first part to be decrypted start here 
     mov edi, esi
     mov ecx, 1f53h                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp FirstStep

v202part1:
     movzx edx, byte ptr [esi+07ah]     ; first magic value for v2.02b
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 0a6h                      ; first part to be decrypted start here 
     mov edi, esi
     mov ecx, 246eh                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp FirstStep

v203part1:
     movzx edx, byte ptr [esi+06ch]     ; first magic value for v2.03
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 09fh                      ; first part to be decrypted start here 
     mov edi, esi
     mov ecx, 25d8h                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp FirstStep

v204part1:
     movzx edx, byte ptr [esi+06fh]     ; first magic value for v2.04
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 09ch                      ; first part to be decrypted start here 
     mov edi, esi
     mov ecx, 260bh                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp FirstStep

FirstStep:
     lodsb                              ; load 1 byte in AL
     xor al,ah                          ; decrypt
     xor al,cl                          
     stosb                              ; store it back
     dec ecx                    
     jnz FirstStep

     mov esi, offset PELOCKbuf
     xor eax,eax

     cmp byte ptr [version],1           ; check if version 2.01
     jz v201part2
     cmp byte ptr [version],2           ; check if version 2.02b
     jz v202part2
     cmp byte ptr [version],3           ; check if version 2.03
     jz v203part2
     cmp byte ptr [version],4           ; check if version 2.04
     jz v204part2

v201part2:
     movzx edx, byte ptr [esi+0e8h]     ; another magic value for v2.01 
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 103h                      ; another part to be decrypted
     mov edi, esi
     mov ecx, 1ef1h                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp SecondStep

v202part2:
     movzx edx, byte ptr [esi+0105h]    ; another magic value for v2.02b
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 130h                      ; another part to be decrypted
     mov edi, esi
     mov ecx, 23e4h                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp SecondStep

v203part2:
     movzx edx, byte ptr [esi+0fah]     ; another magic value for v2.03
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 125h                      ; another part to be decrypted
     mov edi, esi
     mov ecx, 2552h                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp SecondStep

v204part2:
     movzx edx, byte ptr [esi+0f9h]     ; another magic value for v2.04
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 124h                      ; another part to be decrypted
     mov edi, esi
     mov ecx, 2583h                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp SecondStep

SecondStep:
     lodsb                              ; load 1 byte in AL
     xor al,ah                          ; decrypt
     xor ah,cl
     stosb                              ; store it back
     dec ecx                    
     jnz SecondStep

     mov esi, offset PELOCKbuf
     xor eax,eax

     cmp byte ptr [version],1           ; check if version 2.01b
     jz v201part3
     cmp byte ptr [version],2           ; check if version 2.02b
     jz v202part3
     cmp byte ptr [version],3           ; check if version 2.03
     jz v203part3
     cmp byte ptr [version],4           ; check if version 2.04
     jz v204part3

v201part3:
     movzx edx, byte ptr [esi+01f6h]    ; another magic value for 2.01 
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 212h                      ; another part to be decrypted
     mov edi, esi
     mov ecx, 1de2h                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp ThirdStep

v202part3:
     movzx edx, byte ptr [esi+0223h]    ; another magic value for 2.02b
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 24ch                      ; another part to be decrypted
     mov edi, esi
     mov ecx, 22c8h                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp ThirdStep

v203part3:
     movzx edx, byte ptr [esi+020dh]    ; another magic value for 2.03
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 23bh                      ; another part to be decrypted
     mov edi, esi
     mov ecx, 243ch                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp ThirdStep

v204part3:
     movzx edx, byte ptr [esi+0207h]    ; another magic value for v2.04
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 232h                      ; another part to be decrypted
     mov edi, esi
     mov ecx, 2475h                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp ThirdStep

ThirdStep:
     lodsb                              ; load 1 byte in AL
     xor al,ah                          ; decrypt
     xor ah,cl
     stosb                              ; store it back
     dec ecx                    
     jnz ThirdStep

     mov esi, offset PELOCKbuf
     xor eax,eax
     xor ebx, ebx                       ; this time we set EBX to 0 :)

     cmp byte ptr [version],1           ; check if version 2.01
     jz v201part4
     cmp byte ptr [version],2           ; check if version 2.02b
     jz v202part4
     cmp byte ptr [version],3           ; check if version 2.03
     jz v203part4
     cmp byte ptr [version],4           ; check if version 2.04
     jz v204part4

v201part4:
     movzx edx, byte ptr [esi+027ah]    ; another magic value for v2.01 
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 2a0h                      ; another part to be decrypted
     mov edi, esi
     mov ecx, 1d54h                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp FourthStep

v202part4:
     movzx edx, byte ptr [esi+02c2h]    ; another magic value for v2.02b
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 30ah                      ; another part to be decrypted
     mov edi, esi
     mov ecx, 220ah                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp FourthStep

v203part4:
     movzx edx, byte ptr [esi+02a9h]    ; another magic value for v2.03 
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 2efh                      ; another part to be decrypted
     mov edi, esi
     mov ecx, 2388h                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp FourthStep

v204part4:
     movzx edx, byte ptr [esi+0296h]    ; another magic value for v2.04
     mov byte ptr [magicbyte], dl       ; store it
     add esi, 2dah                      ; another part to be decrypted
     mov edi, esi
     mov ecx, 23cdh                     ; this many bytes to be decrypted
     mov ah, magicbyte                  ; using this value
     jmp FourthStep

FourthStep:
     lodsb                              ; load 1 byte in AL
     xor al, ah                         ; decrypt
     mov bh, cl
     and cl, 7
     ror al, cl
     mov cl, bh
     xor ah, cl
     stosb                              ; store it back
     loop FourthStep

     mov esi, offset PELOCKbuf
     push esi                           ; save address

     cmp byte ptr [version],1           ; check if version 2.01
     jz getenckeyv201
     cmp byte ptr [version],2           ; check if version 2.02b
     jz getenckeyv202
     cmp byte ptr [version],3           ; check if version 2.03
     jz getenckeyv203
     cmp byte ptr [version],4           ; check if version 2.04
     jz getenckeyv204

getenckeyv201:
     mov ebx, [esi+215fh]               ; get the encrypted magic key for v2.01 
     add esi, 2d9h                      ; now we decrypted the whole object, go for the last loop
     mov ecx, 7a1h                      ; this many times
     jmp LastLayer

getenckeyv202:
     mov ebx, [esi+267fh]               ; get the encrypted magic key for v2.02b
     add esi, 345h                      ; now we decrypted the whole object, go for the last loop
     mov ecx, 8ceh                      ; this many times
     jmp LastLayer

getenckeyv203:
     mov ebx, [esi+27e2h]               ; get the encrypted magic key for v2.03
     add esi, 32ah                      ; now we decrypted the whole object, go for the last loop
     mov ecx, 92eh                      ; this many times
     jmp LastLayer

getenckeyv204:
     mov ebx, [esi+2812h]               ; get the encrypted magic key for v2.04
     add esi, 313h                      ; now we decrypted the whole object, go for the last loop
     mov ecx, 93fh                      ; this many times
     jmp LastLayer

LastLayer:
     lodsd                              ; get dword
     xor ebx, eax                       ; compute magic key
     loop LastLayer
     shr ebx, 16h
     pop esi                            ; restore begin of PELOCKNT object

     cmp byte ptr [version],1           ; check if version 2.01 
     jz getrealkeyv201
     cmp byte ptr [version],2           ; check if version 2.02b
     jz getrealkeyv202
     cmp byte ptr [version],3           ; check if version 2.03
     jz getrealkeyv203
     cmp byte ptr [version],4           ; check if version 2.04
     jz getrealkeyv204

getrealkeyv201:
     add esi, 1c2ah                     ; here is the real decryption key for v2.01
     jmp storerealkey

getrealkeyv202:
     add esi, 211fh                     ; here is the real decryption key for v2.02b
     jmp storerealkey

getrealkeyv203:
     add esi, 2175h                     ; here is the real decryption key for v2.03
     jmp storerealkey

getrealkeyv204:
     add esi, 21a5h                     ; here is the real decryption key for v2.04
     jmp storerealkey

storerealkey:
     add [esi],ebx                      ; hmm... seems never used (ebx always 0)
     mov eax, [esi]
     mov [magickey], eax                ; store the real magic key !!

     Write_Console <offset infos3> <infos3size> ; show the magic key :)
     CALL       Hex2Dec
     Write_Console <offset hex> <1>
     Write_Console <offset carriage> <2>

; ***************************************************************************
; THESE LINES DOES EXISTS, ARE EXECUTED.. BUT THE VALUE OBTAINED IS USELESS ? 
; (could be some sort of integrity check, i think... i havent checked further)

; (values here are for v2.04)
;
;    mov esi, offset PELOCKbuf          ; hunt for the original EIP now
;    mov ecx, 0759h                     ; loop repeated this many times
;    mov ebx, [esi+219dh]               ; using this key
;    add esi, 0439h                     ; starting from this offset
;
; EIPHunt1:
;    lodsd
;    xor ebx,eax                        ; compute another "magic" key
;    loop EIPHunt1
; *************************************************************************** 
        
     mov esi, offset PELOCKbuf          ; hunt for the original EIP now
     push esi                           ; save address

     cmp byte ptr [version],1           ; check if version 2.01
     jz getEIPv201
     cmp byte ptr [version],2           ; check if version 2.02b
     jz getEIPv202
     cmp byte ptr [version],3           ; check if version 2.03
     jz getEIPv203
     cmp byte ptr [version],4           ; check if version 2.04
     jz getEIPv204

getEIPv201:
     mov ecx, 113ch                     ; this many bytes decrypted for v2.01
     jmp EIPHunt2

getEIPv202:
     mov ecx, 13adh                     ; this many bytes decrypted for v2.02b
     jmp EIPHunt2

getEIPv203:
     mov ecx, 1422h                     ; this many bytes decrypted for v2.03
     jmp EIPHunt2

getEIPv204:
     mov ecx, 144dh                     ; this many bytes decrypted for v2.04
     jmp EIPHunt2

EIPHunt2:
     xor [esi], cl                      ; using the counter as key
     inc esi
     loop EIPHunt2

     pop esi                            ; restore address

     cmp byte ptr [version],1           ; check if version 2.01 
     jz decryptEIPv201
     cmp byte ptr [version],2           ; check if version 2.02b
     jz decryptEIPv202
     cmp byte ptr [version],3           ; check if version 2.03
     jz decryptEIPv203
     cmp byte ptr [version],4           ; check if version 2.04
     jz decryptEIPv204

decryptEIPv201:
     add esi, 1ef3h
     mov eax, [esi]                     ; get this value for v2.01
     xor eax, 19982356h                 ; eax = ORIGINAL EIP !!!
     mov [EIP], eax                     ; store original entrypoint
     jmp continue  

decryptEIPv202:
     add esi, 2413h
     mov eax, [esi]                     ; get this value for v2.02b
     xor eax, 4a932397h                 ; eax = ORIGINAL EIP !!!
     mov [EIP], eax                     ; store original entrypoint
     jmp continue  

decryptEIPv203:
     add esi, 2576h
     mov eax, [esi]                     ; get this value for v2.03
     xor eax, 4b932397h                 ; eax = ORIGINAL EIP !!!
     mov [EIP], eax                     ; store original entrypoint
     jmp continue  

decryptEIPv204:
     add esi, 25a6h
     mov eax, [esi]                     ; get this value for v2.04
     xor eax, 03b962597h                ; eax = ORIGINAL EIP !!!
     mov [EIP], eax                     ; store original entrypoint
     jmp continue  


continue:

     Write_Console <offset infos4> <infos4size> ; show the EIP :)
     CALL       Hex2Dec
     Write_Console <offset hex> <1>
     Write_Console <offset carriage> <2>

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;    Get other interesting stuff such as imagebase, import info, etc...
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

     mov esi, offset PELOCKbuf

     cmp byte ptr [version],1           ; check if version 2.01
     jz getimportinfosv201
     cmp byte ptr [version],2           ; check if version 2.02b
     jz getimportinfosv202
     cmp byte ptr [version],3           ; check if version 2.03
     jz getimportinfosv203
     cmp byte ptr [version],4           ; check if version 2.04
     jz getimportinfosv204

getimportinfosv201:
     add esi, 1eb2h                     ; infos are here in v2.01
     jmp getimportinfos

getimportinfosv202:
     add esi, 23d2h                     ; infos are here in v2.02b
     jmp getimportinfos

getimportinfosv203:
     add esi, 2535h                     ; infos are here in v2.03
     jmp getimportinfos

getimportinfosv204:
     add esi, 2565h                     ; infos are here in v2.04
     jmp getimportinfos

getimportinfos:
     mov eax, [esi]
     mov [imgbase], eax                 ; get file original imagebase
     mov eax, [esi+4]
     mov [importRVA], eax               ; get ImportTable RVA
     mov eax, [esi+8]
     sub eax, dword ptr [importRVA]
     mov [importsize], eax              ; this is the ImportTable size
     mov eax, [esi+0ch]
     mov [baserelocRVA], eax            ; base relocations RVA
     mov eax, [esi+10h]
     sub eax, dword ptr [baserelocRVA]
     mov [baserelocsize], eax           ; this is base relocations size

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;           Allocate memory and setup stuff for proper decryption
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

     push PAGE_READWRITE
     push MEM_COMMIT 
     push filesize                              ; size of memory to allocate (size of file)
     push 0
     call VirtualAlloc                          ; allocate memory for the decryption
     mov [buffer], eax                          ; save address

; compute Virtual Addresses of parts to be skipped, from RVA to VA
; note : "buffer" is our bogus imagebase during decryption !

     mov ebx, eax                       ; save buffer address
     mov esi, offset PELOCKbuf

     cmp byte ptr [version],1           ; check if version 2.01
     jz getotherinfosv201
     cmp byte ptr [version],2           ; check if version 2.02b
     jz getotherinfosv202
     cmp byte ptr [version],3           ; check if version 2.03
     jz getotherinfosv203
     cmp byte ptr [version],4           ; check if version 2.04
     jz getotherinfosv204

getotherinfosv201:
     add esi, 1ec6h                             ; other infos are here in v2.01
     jmp getotherinfos

getotherinfosv202:
     add esi, 23e6h                             ; other infos are here in v2.02b
     jmp getotherinfos

getotherinfosv203:
     add esi, 2549h                             ; other infos are here in v2.03
     jmp getotherinfos

getotherinfosv204:
     add esi, 2579h                             ; other infos are here in v2.04
     jmp getotherinfos
                                
getotherinfos:
     add eax, [esi]
     mov [value4a], eax                         ; get value4a+imagebase

     mov eax, ebx
     add eax, [esi+4]
     mov [value4b], eax                         ; get value4b+imagebase

     mov eax, ebx
     add eax, [esi+08h]
     mov [value3b], eax                         ; get value3b+imagebase

     mov eax, ebx
     add eax, [esi+0ch]
     mov [value3a], eax                         ; get value3a+imagebase

     mov eax, ebx
     add eax, [esi+010h]
     mov [value1b], eax                         ; get value1b+imagebase

     mov eax, ebx
     add eax, [esi+014h]
     mov [value1a], eax                         ; get value1a+imagebase

     mov eax, ebx
     add eax, [esi+020h]
     mov [value2a], eax                         ; get value2a+imagebase

     mov eax, ebx
     add eax, [esi+024h]
     mov [value2b], eax                         ; get value2b+imagebase


;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                               Decrypt objects
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

GoForNextObject:
     mov edx, objnum
     mov esi, offset PELOCKbuf

     cmp byte ptr [version],1           ; check if version 2.01
     jz locateobjectsv201
     cmp byte ptr [version],2           ; check if version 2.02b
     jz locateobjectsv202
     cmp byte ptr [version],3           ; check if version 2.03
     jz locateobjectsv203
     cmp byte ptr [version],4           ; check if version 2.04
     jz locateobjectsv204

locateobjectsv201:
     add esi, 1efch                     ; object table is here in v2.01
     jmp objecttablefound

locateobjectsv202:
     add esi, 241ch                     ; object table is here in v2.02b
     jmp objecttablefound

locateobjectsv203:
     add esi, 257fh                     ; object table is here in v2.03
     jmp objecttablefound

locateobjectsv204:
     add esi, 25afh                     ; object table is here in v2.04
     jmp objecttablefound

objecttablefound:
     add esi, objdisplacement   ; displacement to next object
     mov eax, [esi]             ; encrypted object RVA
     mov [objrva], eax          ; save object RVA
     mov edi, offset obj&stuff  ; this is the object table
     add edi, edx               ; add displacement

ScanForObject:
     mov ebx, [edi+0ch]         ; RVA of object from the object table
     cmp ebx, 00000000h         ; if RVA is 0, then we've already decrypted all objects
     jz Fine
     cmp eax, ebx               ; is it the encrypted object ?
     jz ObjectFound
     add edi, 028h              ; search in the next object
     jmp ScanForObject
        
ObjectFound:

     inc byte ptr [decrsections] ; increment number of decrypted sections
     mov eax, [edi+10h]         ; object raw size
     mov [objsize], eax
     mov eax, [edi+14h]         ; object offset
     mov [objoffset], eax

     push FILE_BEGIN            ; beginning of file 
     push 0
     push eax                   ; current object offset
     push filehandle
     CALL       SetFilePointer

     push 0
     push offset toread
     push objsize                               ; number of bytes to be read
     push buffer                                ; read here
     push filehandle
     CALL       ReadFile                      

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
     pushad
     mov eax, objsize                           ; objectsize
     xor edx, edx
     mov ecx, 4
     div ecx                                    ; compute size for decryption                               
     mov ecx, eax                               ; loop repeated ECX times

     xor edx, edx
     mov ebx, [imgbase]                         ; file imagebase
     add ebx, [objrva]                          ; EBX = base+RVA of object
     mov esi, buffer                            ; encrypted buffer
     mov edi, esi
     push ebp                                   ; save EBP
     mov ebp, esi
     add ebp, [objrva]                          ; our bogus imgbase+rva

; check for parts to be skipped (IAT,IT,TLS,RSRC)

Check:
     cmp ecx, 0
     jz Finished
     cmp ebp, [value1a]
     jge OkValue1
     cmp ebp, [value1b]
     jl  OkValue1
     jmp SkipThis

OkValue1:
     cmp ebp, [value2a]
     jl OkValue2
     cmp ebp, [value2b]
     jge OkValue2
     jmp SkipThis

OkValue2:
     cmp ebp, [value3a]
     jge OkValue3
     cmp ebp, [value3b]
     jl OkValue3
     jmp SkipThis

OkValue3:
     cmp ebp, [value4a]
     jl Decryption
     cmp ebp, [value4b]
     jge Decryption

SkipThis:
     add edi, 4                                 ; do not decrypt!
     add esi, 4
     add ebp, 4
     dec ecx
     jmp Check                                  ; check next dword

Decryption:
     lodsd
     xchg ah, al
     xor eax, ecx
     test ecx, 00000004h
     jz SkipMul
     imul ebx, ecx, 1268h
     xor eax, ebx

SkipMul:
     rol eax, cl
     xor eax, magickey
     xchg ah, al
     xor edx, eax       
     stosd
     add ebp, 4
     loop Check

Finished:
     pop ebp
     popad

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

    push FILE_BEGIN                            ; beginning of file
    push 0
    push objoffset                             ; current offset during decryption
    push filehandle
    CALL       SetFilePointer

    push 0
    push offset toread
    push objsize                               ; number of bytes to be read
    push buffer                                ; read from here
    push filehandle                            ; write to the file
    CALL       WriteFile

    add objdisplacement, 8                      ; add displacement to next object
    add [objnum], 28h                           ; next object
    jmp GoForNextObject                         ; go for the next object

Fine:

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                               Update PE header
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

    mov esi, offset PEheader
    mov eax, [EIP]
    mov [esi+28h], eax                         ; store back original entrypoint 
    dec word ptr [NumberOfSections]            ; decrease number of sections (-1)
    mov eax, [lastobjvirtsize]                 ; last object virtualsize
    mov ecx, [SectionAlignment]                ; memory alignment
    xor edx, edx
    div ecx                                    ; lastobject virtualsize must be aligned 
    cmp edx, 0                                 ; check if its aligned 
    jz Aligned
    inc eax                                    ; no, it isnt... let's fix it 
Aligned:
    mul ecx                                    ; ok, its aligned now 
    sub dword ptr [esi+50h], eax               ; decrease size of image by aligned virtualsize of last object
    mov eax, [importRVA]
    mov [esi+80h], eax                         ; store back original import RVA
    mov eax, [importsize]
    mov [esi+84h], eax                         ; and original importsize
    mov eax, [baserelocRVA]
    mov [esi+0a0h], eax                        ; store back original base relocations RVA
    mov eax, [baserelocsize]
    mov [esi+0a4h], eax                        ; and original base relocations size
    dec word ptr [esi+0f4h]                    ; decrease number of layers
    mov edi, PELOCKdirectoryoffset             ; offset of last object in objects table
    xor eax,eax                                ; we have to zeropad it 
    mov ecx, 028h                              ; length of section header
    rep stosb                                  ; zero pad :)

    mov edi, headeroffset               
    add edi, 0f8h                              ; this is the offset of objtable in the file 

    push FILE_BEGIN                            ; beginning of file again
    push 0
    push edi                                   ; to the offset of objtable 
    push filehandle
    CALL       SetFilePointer

    mov ebx, eax                               ; calculate raw offset of last directory entry in objtable 
    movzx eax, NumberOfSections
    mov ecx, 028h                              ; length of section directory entry
    xor edx, edx
    mul ecx
    add ebx, eax                               ; EBX=current filepointer, we add the calculated offset 
    mov eax, ebx                               ; here it is in eax again!

    push FILE_BEGIN                            ; beginning of file again
    push 0
    push eax                                   ; to the offset of last object
    push filehandle
    CALL       SetFilePointer

    push 0
    push offset toread
    push 028h                                  ; number of bytes to be read
    push PELOCKdirectoryoffset                 ; read from here (all zeroed)
    push filehandle                            ; delete directory entry in objtable  
    CALL       WriteFile

    push FILE_BEGIN                            ; beginning of file again
    push 0
    push headeroffset                          ; to the offset of PE header
    push filehandle
    CALL       SetFilePointer

    push 0
    push offset toread
    push 0f8h                                  ; number of bytes to be read
    push offset PEheader                       ; read from here
    push filehandle                            ; write the main PE header (no objtbl)
    CALL       WriteFile

    
    push FILE_BEGIN                            ; beginning of file again
    push 0
    push lastobjoffset                         ; .PELOCKNT offset (last object)
    push filehandle
    CALL        SetFilePointer

    push filehandle
    CALL        SetEndOfFile                   ; dirty way to remove last object :)

    push MEM_DECOMMIT
    push filesize
    push buffer         
    CALL        VirtualFree                     ; free allocated memory

    push filehandle
    CALL       CloseHandle                      ; close file

    movzx eax, [decrsections]                   ; show # of decrypted sections
    Write_Console <offset infos5> <infos5size>
    CALL       Hex2Dec
    Write_Console <offset carriage> <2>
    Write_Console <offset carriage> <2>

    dec byte ptr [layers]                       ; decrease number of analyzed layers
    cmp byte ptr [layers], 0                    ; is there another layer ?
    jnz Begin

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                     Remove PELOCK-NT flag from the header
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

    mov word ptr [PEheader+0f6h], 0000h        ; file is not PELOCK-NTed anymore :)

    push 0                                     ; push the required attributes
    push FILE_ATTRIBUTE_NORMAL
    push OPEN_EXISTING
    push 0
    push FILE_SHARE_READ
    push GENERIC_READWRITE                     ; read and write enabled        
    push offset filename
    CALL       CreateFileA                     ; check for file existance
    mov [filehandle], eax

    push FILE_BEGIN                            ; beginning of file again
    push 0
    push headeroffset                          ; to the offset of PE header
    push filehandle
    CALL       SetFilePointer

    push 0
    push offset toread
    push 0f8h                                  ; size of "main" header w/o objtable and stuff
    push offset PEheader                       ; read here
    push filehandle
    CALL       WriteFile                     

    push filehandle
    CALL       CloseHandle                      ; close file.. THE END!

    Write_Console <offset infos2> <infos2size>  ; file decrypted :)
    
    call       ExitProcess
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                               error messages                
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

NoCommandLine:
     Write_Console <offset errormsg> <errormsgsize>
     Write_Console <offset error1> <error1size>
     CALL       ExitProcess
FileNotFound:
     Write_Console <offset errormsg> <errormsgsize>
     Write_Console <offset filename> <filenamesize>
     Write_Console <offset error2> <error2size>
     CALL       ExitProcess
NoPELock:
     Write_Console <offset errormsg> <errormsgsize>
     Write_Console <offset filename> <filenamesize>
     Write_Console <offset error3> <error3size>
     CALL       ExitProcess
unknownversion:
     Write_Console <offset errormsg> <errormsgsize>
     Write_Console <offset unknownver> <unknownversize>
     CALL       ExitProcess

end Main



