DLL的远程注入技术是目前Win32病毒广泛使用的一种技术。使用这种技术的病毒体通常位于一个DLL中,
在系统启动的时候,一个EXE程序会将这个DLL加载至某些系统进程(如Explorer.exe)中运行。这样一来,普通的进程管理器就很难发现这种病毒了,而且即使发现了也很难清除, 因为只要病毒寄生的进程不终止运行,那么这个DLL就不会在内存中卸载, 用户也就无法在资源管理器中删除这个DLL文件,真可谓一箭双雕哉。记得2003年QQ尾巴病毒肆虐的时候,就已经有些尾巴病毒的变种在使用这种技术了。 到了2004年初,我曾经尝试着仿真了一个QQ尾巴病毒,但独是跳过了DLL的远程加载技术。 直到最近在学校论坛上看到了几位朋友在探讨这一技术,便忍不住将这一尘封已久的技术从我的记忆中拣了出来,以满足广大的技术爱好者们。
必备知识
在阅读本文之前,你需要了解以下几个API函数: ·OpenProcess - 用于打开要寄生的目标进程。 ·VirtualAllocEx/VirtualFreeEx - 用于在目标进程中分配/释放内存空间。 ·WriteProcessMemory - 用于在目标进程中写入要加载的DLL名称。 ·CreateRemoteThread - 远程加载DLL的核心内容,用于控制目标进程调用API函数。 ·LoadLibrary - 目标进程通过调用此函数来加载病毒DLL。 在此我只给出了简要的函数说明,关于函数的详细功能和介绍请参阅MSDN。 示例程序 我将在以下的篇幅中用一个简单的示例Virus.exe来实现这一技术。这个示例的界面如下图: 首先运行Target.exe,这个文件是一个用Win32 Application向导生成的“Hello, World”程序,用来作为寄生的目标进程。 然后在界面的编辑控件中输入进程的名称“Target.exe”,单击“注入DLL”按钮,这时候Virus.exe就会将当前目录下的DLL.dll注入至Target.exe进程中。 在注入DLL.dll之后,你也可以单击“卸载DLL”来将已经注入的DLL卸载。 模拟的病毒体DLL.dll 这是一个简单的Win32 DLL程序,它仅由一个入口函数DllMain组成:
如你所见,这里我在DLL被加载和卸载的时候调用了MessageBox,这是用来显示我的远程注入/ 卸载工作是否成功完成。而对于一个真正的病毒体来说, 它往往就是处理DLL_PROCESS_ATTACH事件,在其中加入了启动病毒代码的部分:
}
break;
注入! 现在要开始我们的注入工作了。首先,我们需要找到目标进程:
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的:
在系统启动的时候,一个EXE程序会将这个DLL加载至某些系统进程(如Explorer.exe)中运行。这样一来,普通的进程管理器就很难发现这种病毒了,而且即使发现了也很难清除, 因为只要病毒寄生的进程不终止运行,那么这个DLL就不会在内存中卸载, 用户也就无法在资源管理器中删除这个DLL文件,真可谓一箭双雕哉。记得2003年QQ尾巴病毒肆虐的时候,就已经有些尾巴病毒的变种在使用这种技术了。 到了2004年初,我曾经尝试着仿真了一个QQ尾巴病毒,但独是跳过了DLL的远程加载技术。 直到最近在学校论坛上看到了几位朋友在探讨这一技术,便忍不住将这一尘封已久的技术从我的记忆中拣了出来,以满足广大的技术爱好者们。
必备知识
在阅读本文之前,你需要了解以下几个API函数: ·OpenProcess - 用于打开要寄生的目标进程。 ·VirtualAllocEx/VirtualFreeEx - 用于在目标进程中分配/释放内存空间。 ·WriteProcessMemory - 用于在目标进程中写入要加载的DLL名称。 ·CreateRemoteThread - 远程加载DLL的核心内容,用于控制目标进程调用API函数。 ·LoadLibrary - 目标进程通过调用此函数来加载病毒DLL。 在此我只给出了简要的函数说明,关于函数的详细功能和介绍请参阅MSDN。 示例程序 我将在以下的篇幅中用一个简单的示例Virus.exe来实现这一技术。这个示例的界面如下图: 首先运行Target.exe,这个文件是一个用Win32 Application向导生成的“Hello, World”程序,用来作为寄生的目标进程。 然后在界面的编辑控件中输入进程的名称“Target.exe”,单击“注入DLL”按钮,这时候Virus.exe就会将当前目录下的DLL.dll注入至Target.exe进程中。 在注入DLL.dll之后,你也可以单击“卸载DLL”来将已经注入的DLL卸载。 模拟的病毒体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;
}
...{
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;
}
case DLL_PROCESS_ATTACH:
{
}
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;
}
...{
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系统下,每个进程都拥有自己的
HMODULE hDll = LoadLibrary( "DLL.dll" );
那么,如果能控制目标进程调用LoadLibrary,不就可以完成