我是靠谱客的博主 认真黑夜,最近开发中收集的这篇文章主要介绍VC++远程注入动态库的实现(6-4),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

相关视频教程下载链接:http://pan.baidu.com/s/1eR6xKiQ 密码:alrl

(3)分配内存地址空间

要将指定的动态库路径写入到进程的地址空间中,需要为该动态库路径分配地址空间。要分配地址空间,就需要知道要分配地址空间的大小。假设动态库文件与注入程序文件在同一文件夹下,即如果注入文件的绝对路径为C:12inject.exe”,则动态库的绝对路径为“C:12myDll.dll”。分配地址空间的大小即为动态库绝对路径的长度,首先获取注入文件的绝对路径,之后将绝对路径中的“inject.exe”换成“myDll.dll”即可。

TCHAR szLibFile[MAX_PATH] = { 0 };

GetModuleFileName(NULL, szLibFile, _countof(szLibFile));

PTSTR pFileName = _tcsrchr(szLibFile, _T('\')) + 1;

_tcscpy_s(pFileName, _countof(szLibFile) - (pFileName - szLibFile), inject_dll_name);

int cch = lstrlen(szLibFile) + 1;

SIZE_T cb = cch*sizeof(TCHAR);

其中,GetModuleFileName()函数的作用是获取注入程序的绝对路径,并将其保存在szLibFile中;之后通过_tcsrchr()函数获取szLibFile中最后一个“\”的位置;接下来通过_tcscpy_s()函数将szLibFile中注入程序的名称换成动态库的名称inject_dll_name;最后得到动态库的绝对路径的长度cb

在获取了要分配内存地址空间的长度之后,通过VirtualAllocEx()函数在远程进程的内存空间中进行分配。该函数的格式为

LPVOID WINAPI VirtualAllocEx(

  _In_     HANDLE hProcess,

  _In_opt_ LPVOID lpAddress,

  _In_     SIZE_T dwSize,

  _In_     DWORD  flAllocationType,

  _In_     DWORD  flProtect

);

其中,参数hProcess表示进程的句柄;lpAddress指定了分配的内存地址空间的起始地址,如果该参数为NULL,则表示由函数本身来决定分配空间的起始地址;dwSize表示分配的内存地址空间的大小;flAllocationType表示分配内存的类型;flProtect表示对分配的内存地址空间的权限。该函数的返回值即为分配的内存地址空间的起始地址。

LPVOID dll_name_address = VirtualAllocEx(hProcess, NULL, cb, MEM_COMMIT, PAGE_READWRITE);

if (NULL == dll_name_address)

{

MessageBox(_T("分配内存失败!"));

return;

}

VirtualAllocEx()函数的参数中,hProcess是在“(2)获取远程进程句柄”中获取到的远程进程的句柄;第二个参数NULL表示由函数指定内存空间的起始地址;cb是动态库文件绝对路径的大小;MEM_COMMIT表示内存的类型是“提交”;PAGE_READWRITE表示对分配的内存地址空间有读写权限。返回值dll_name_address是分配的内存地址空间的起始地址。

(4)写入动态库的绝对路径

在内存中分配了地址空间之后,接下来通过WriteProcessMemory()函数将动态库的绝对路径写入到内存空间中。该函数的格式为

BOOL WINAPI WriteProcessMemory(

  _In_  HANDLE  hProcess,

  _In_  LPVOID  lpBaseAddress,

  _In_  LPCVOID lpBuffer,

  _In_  SIZE_T  nSize,

  _Out_ SIZE_T  *lpNumberOfBytesWritten

);

其中,参数hProcess是进程的句柄;lpBaseAddress表示写入内存的起始地址;lpBuffer表示写入内存地址的内容;nSize表示写入内存地址内容的大小;lpNumberOfBytesWritten表示写入到内存地址内容的实际大小。如果将指定内容成功写入到内存地址中,则返回值是TRUE,否则为FALSE

SIZE_T number_bytes_written = 0;

if (!WriteProcessMemory(hProcess, dll_name_address, (LPCVOID)szLibFile, cb, &number_bytes_written))

{

MessageBox(_T("写入内存失败"));

return;

}

其中,SIZE_T类型在basetsd.h中定义为

typedef ULONG_PTR SIZE_T, *PSIZE_T;

可将该类型看作是一个64位无符号的long类型。WriteProcessMemory()函数的参数hProcess是在“获取远程进程句柄”中获取到的指定的远程线程的句柄;dll_name_address是在“(3)分配内存地址空间”中分配的内存地址空间的起始地址;szLibFile是在“(3)分配内存地址空间”中得到的动态库文件的绝对路径;cb是动态库文件的绝对路径的大小。

3.3.3 创建远程线程注入动态库

在将动态库文件的绝对路径写入到远程进程的地址空间之后,接下来在远程进程中创建远程线程。该线程的函数为LoadLibrary(),线程函数的参数即为在“3.3.2 写入动态库名称”中写入的动态库绝对路径。

(1)获取LoadLibrary()函数的地址

LoadLibrary()函数在Windows系统的动态库文件Kernel32.dll中定义。对于在Windows系统中运行的程序,在运行时都会导入该动态库文件。对于导入程序和要注入的远程程序,在运行时都会导入Kernel32.dll文件。也就是说,LoadLibrary()函数在导入程序中的地址与远程程序中的地址是相同的。因此,在导入程序中获取的LoadLibrary()函数地址即为其在要注入的远程程序中的地址。

LPVOID remote_thread_pointer = LoadLibraryW;

其中,remote_thread_pointer即为LoadLibrary()函数在远程进程中的地址。

(2)创建LoadLibrary()函数的进程

通过CreateRemoteThread()函数创建远程线程。该函数的格式为

HANDLE WINAPI CreateRemoteThread(

  _In_  HANDLE                 hProcess,

  _In_  LPSECURITY_ATTRIBUTES  lpThreadAttributes,

  _In_  SIZE_T                 dwStackSize,

  _In_  LPTHREAD_START_ROUTINE lpStartAddress,

  _In_  LPVOID                 lpParameter,

  _In_  DWORD                  dwCreationFlags,

  _Out_ LPDWORD                lpThreadId

);

其中,参数hProcess表示远程进程句柄;lpThreadAttributes表示创建的线程的安全描述符(security descriptor),该参数是NULL表示线程使用默认的安全描述符;dwStackSize表示新创建的线程堆的初始大小,该参数是0表示新线程使用默认的堆大小;lpStartAddress表示线程对应的函数的地址;lpParameter表示线程函数的参数;dwCreateFlags表示创建线程时的标志;lpThreadId表示创建线程的ID。该函数的返回值为新创建线程的句柄。

DWORD remote_thread_id = 0;

HANDLE remote_thread_handle = CreateRemoteThread(

hProcess

, NULL

, 0

, (LPTHREAD_START_ROUTINE)remote_thread_pointer

, dll_name_address

, 0

, &remote_thread_id);

if (NULL == remote_thread_handle)

{

MessageBox(_T("创建线程失败"));

return;

}

对于CreateRemoteThread()函数的参数,hProcess是“获取远程进程句柄”中获取到的指定的远程线程的句柄;remote_thread_pointer“(1)获取LoadLibrary()函数的地址”中LoadLibrary()函数的地址;dll_name_address是动态库的绝对路径。

(3)等待新创建的线程结束

在创建了新线程之后,需要等待其结束再进行后续释放资源的处理。否则,会导致导入动态库失败。可通过WaitForSingleObject()函数等待线程结束,该函数的格式为

DWORD WINAPI WaitForSingleObject(

  _In_ HANDLE hHandle,

  _In_ DWORD  dwMilliseconds

);

其中,参数hHandle表示要等待的线程句柄;dwMilliseconds表示要等待的时间。该函数的返回值表示函数返回的原因。

WaitForSingleObject(remote_thread_handle, INFINITE);

其中,remote_thread_handle是在“(2)创建LoadLibrary()函数的进程”中新创建线程的句柄,INFINITE表示无限等待下去,直到指定的线程结束。

最后

以上就是认真黑夜为你收集整理的VC++远程注入动态库的实现(6-4)的全部内容,希望文章能够帮你解决VC++远程注入动态库的实现(6-4)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(30)

评论列表共有 0 条评论

立即
投稿
返回
顶部