1.2  1.病毒的重定位技术

  病毒的重定位技术应该也算是最基本和最有用的技术之一了,其实重定位技术只要是对外壳开发比较熟悉的朋友都应该很熟悉了。重定位顾名思义重新定位地址。上篇文章中我们已经讲解到了由于我们被感染对象的不同,我们部分定义的变量被插入的地址也不同。所以这就需要我们重新定位,也就是今天的主题重定位技术。

  首先我们来看

假如我们定义一段变量  
    
  szText  db 'Virus Dels Demo', 0

  假设我们这个变量在我们病毒体的地址是00403201h, 那么我们插入到被感染对象后这个变量的地址是00408602h。那么我们如何能让我们的病毒体代码在运行时期来计算到被插入被感染对象后变量的地址呢?
  
  我们思索下是否能找到一些固定的地方。有时候换位思考是很不错的,我们病毒体既然被插入的地址是不固定的,那么病毒体的一些绝对偏移它相对病毒体的偏移肯定是固定的吧。
  
  假设一个病毒的起始位置是00400021h,那么它插入到被感染对象后的位置是00500021h, 那么我们是不是只要知道一个变量相对于我们病毒起始位置的偏移就可以求得这个变量插入后的位置了?

  比如我们的szText变量相对于病毒起始位置的偏移是9h, 那么只要通过求得病毒插入到被感染对象后的病毒起始位置 + 这个变量相对病毒起始位置的偏移 =  变量在被感染对象中的位置。 

  是不是很好理解?

  继续思索: 

  我们如何求病毒被插入感染对象后的起始位置,它是可变的。 
    
  我们来看一下call指令, call指令是将下一句指令的偏移压入堆栈,然后设置eip寄存器指向要跳转的地址。

  看以下代码:  
  00401010 >/$  E8 00000000   ;call  00401015
  00401015  |$  5B            ;pop       ebx
  
    就如这段代码call指令首先将下一句指令的地址00401015h压入堆栈,然后将eip寄存器指向00401015h。


病毒技术中call指令详解:

  我们都知道call 调用一个内存地址的话,编译器编译的是相对于调用地址的偏移(注意:这里不是绝对偏移,相对偏移),求调用地址的公式是调用地址 - (call指令所处偏移 +5) = 相对偏移

  如上面这段代码, 假设我们的代码是call 00401016的话, 那么编译器会将机器码编译为 E8 00000001 。 E8为call对应的机器码。 00000001为偏移差,不懂自己根据上面的公式算算。

  我想大家看到这点应该明白我讲解call 指令的作用了吧。。 因为call是将下句指令偏移压入堆栈,然后设置eip寄存器为调用地址。所以我们只要在调用地址中取得堆栈中4字节数据则为下句指令的偏移。

  这句代码执行的到00401015处通过pop ebx取得堆栈中4字节的数据(这4字节数据则为call 地址所处位置下句指令偏移地址, 也就是pop ebx指令的地址)。通过这个地址我们就可以把它参照(就相当于上面所说的把它相当于病毒的起始地址),这样我们后面任何绝对地址均采用 这个地址 + 绝对地址相对这个地址的偏移 来取得真正的地址。说起来有些绕口,不过的确是这么个意思。初学者可以多读读理解下。

  这里很多不了解基础的人,写代码总是开始E8 00000000  

  其实你可以调用其他的地址,然后在其后写一些垃圾代码防止杀软的查杀。然后只要把下句指令偏移作为参照就行了。  

  看代码。

    szText  db  'Virus Dels Demo', 0
    
   __Entry:
     call  Dels2
    Dels:
    int  3
    int  3
    Dels2:
     pop  ebx
     lea  edx, [ebx + szText - Dels] ; edx = szText
    ret
        

  代码很简单很好理解,通过调用call dels, 然后通过pop ebx获得dels的偏移,然后通过szText - Dels获得szText变量基于Dels的相对偏移,然后在+dels(ebx) = 重定位后的偏移。

  如果您能看到这里,我想您已经是基本理解了。其实就是这么简单,找一个能在运行时计算出来的地址,然后+上相对它的偏移则为重定位后的地址。主要思路就是这样,至于如何发挥就是大家的事情了,您可以发挥你的创造力来变形你的重定位代码,任何技术都是基础。。

  好了今天这篇文章就到这里吧。下篇文章我们再见面。