全站搜索

揭开病毒的奥秘 DLL的远程注入技术详解

2005-11-09   作者:依桑编辑   阅读量:

模拟的病毒体DLL.dll

  这是一个简单的Win32 DLL程序,它仅由一个入口函数DllMain组成:

BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
{
 switch ( fdwReason )
 {
  case DLL_PROCESS_ATTACH:
  {
   MessageBox( NULL, _T("DLL已进入目标进程。"), _T("信息"), MB_ICONINFORMATION );
  }
  break;
  case DLL_PROCESS_DETACH:
  {
   MessageBox( NULL, _T("DLL已从目标进程卸载。"), _T("信息"), MB_ICONINFORMATION );
  }
  break;
 }
 return TRUE;
}

  如你所见,这里我在DLL被加载和卸载的时候调用了MessageBox,这是用来显示我的远程注入/卸载工作是否成功完成。而对于一个真正的病毒体来说,它往往就是处理DLL_PROCESS_ATTACH事件,在其中加入了启动病毒代码的部分:

case DLL_PROCESS_ATTACH:
{
 StartVirus();
}
break;
注入!

  现在要开始我们的注入工作了。首先,我们需要找到目标进程:

DWORD FindTarget( LPCTSTR lpszProcess )
{
 DWORD dwRet = 0;
 HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
 PROCESSENTRY32 pe32;
 pe32.dwSize = sizeof( PROCESSENTRY32 );
 Process32First( hSnapshot, &pe32 );
 do
 {
  if ( lstrcmpi( pe32.szExeFile, lpszProcess ) == 0 )
  {
   dwRet = pe32.th32ProcessID;
   break;
  }
 } while ( Process32Next( hSnapshot, &pe32 ) );
 CloseHandle( hSnapshot );
 return dwRet;
}

  这里我使用了Tool Help函数库,当然如果你是NT系统的话,也可以选择PSAPI函数库。

  这段代码的目的就是通过给定的进程名称来在当前系统中查找相应的进程,并返回该进程的ID。得到进程ID后,就可以调用OpenProcess来打开目标进程了:

// 打开目标进程
HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION |
 PROCESS_VM_WRITE, FALSE, dwProcessID );

  现在有必要说一下OpenProcess第一个参数所指定的三种权限。在Win32系统下,每个进程都拥有自己的4G虚拟地址空间,各个进程之间都相互独立。如果一个进程需要完成跨进程的工作的话,那么它必须拥有目标进程的相应操作权限。在这里,PROCESS_CREATE_THREAD表示我可以通过返回的进程句柄在该进程中创建新的线程,也就是调用CreateRemoteThread的权限;同理,PROCESS_VM_OPERATION则表示在该进程中分配/释放内存的权限,也就是调用VirtualAllocEx/VirtualFreeEx的权限;PROCESS_VM_WRITE表示可以向该进程的地址空间写入数据,也就是调用WriteProcessMemory的权限。

  至此目标进程已经打开,那么我们该如何来将DLL注入其中呢?在这之前,我请你看一行代码,是如何在本进程内显式加载DLL的:

HMODULE hDll = LoadLibrary( "DLL.dll" );

  那么,如果能控制目标进程调用LoadLibrary,不就可以完成DLL的远程注入了么?的确是这样,我们可以通过CreateRemoteThread将LoadLibrary作为目标进程的一个线程来启动,这样就可以完成“控制目标进程调用LoadLibrary”的工作了。到这里,也许你会想当然地写下类似这样的代码:

DWORD dwID;
LPVOID pFunc = LoadLibraryA;
HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0,
 (LPTHREAD_START_ROUTINE)pFunc,
(LPVOID)"DLL.dll", 0, &dwID );

  不过结果肯定会让你大失所望——注入DLL失败!

  那么现在让我们来分析一下失败的原因吧。我是前说过,在Win32系统下,每个进程都拥有自己的4G虚拟地址空间,各个进程之间都是相互独立的。在这里,我们当作参数传入的字符串"DLL.dll"其实是一个数值,它表示这个字符串位于Virus.exe地址空间之中的地址,而这个地址在传给Target.exe之后,它指向的东西就失去了有效性。举个例子来说,譬如A、B两栋大楼,我住在A楼的401;那么B楼的401住的是谁我当然不能确定——也就是401这个门牌号在B楼失去了有效性,而且如果我想要入住B楼的话,我就必须请B楼的楼长为我在B楼中安排新的住处(当然这个新的住处是否401也就不一定了)。

责任编辑:依桑
文章来源:PCICP   2005-11-09

请发表评论或留言

用户名: 匿名发表

:硬件::软件: