您的位置:首页 > 其它

Dll注入技术之远程线程注入

2016-03-22 11:38 351 查看
[align=center]DLL注入技术之远线程注入[/align]

    DLL注入技术指的是将一个DLL文件强行加载到EXE文件中,并成为EXE文件中的一部分,这样做的目的在于方便我们通过这个DLL读写EXE文件内存数据,(例如 HOOK EXE文件中的API),或以被注入EXE的身份去执行一些操作等等。
    远线程注入原理是利用Windows 系统中CreateRemoteThread()这个API,其中第4个参数是准备运行的线程,我们可以将LoadLibrary()填入其中,这样就可以执行远程进程中的LoadLibrary()函数,进而将我们自己准备的DLL加载到远程进程空间中执行。
    当然除了CreateRemoteThread()和LoadLibrary()这个两个主要的API还是远远不够的,我们还需要以下表格所示的API:
OpenProcess打开远程进程
VirtualAllocEx在远程进程中申请空间
WriteProcessMemory在远程进程中写入数据
WaitForSingleObject等待信号量
VirtualFreeEx释放远程进程中申请空间
CloseHandle关闭句柄
    主要代码如下:

int CRemoteThreadInjectDLL::InjectDll(DWORD dwProcessId, PTCHAR szDllName)
{
if (szDllName[0] == NULL)
return -1;
//提高权限相关操作
EnablePrivilege(TRUE);
//1. 打开进程
HANDLE hProcess = ::OpenProcess( PROCESS_ALL_ACCESS, //打开进程权限
FALSE, //是否可继承
dwProcessId); //进程ID

if (hProcess == INVALID_HANDLE_VALUE)
return -1;

//2. 在远程进程中申请空间
LPVOID pszDllName = ::VirtualAllocEx(hProcess, //远程进程句柄
NULL, //建议开始地址
4096, //分配空间大小
MEM_COMMIT, //空间初始化全0
PAGE_EXECUTE_READWRITE); //空间权限

if (NULL == pszDllName)
{
return -1;
}

//3. 向远程进程中写入数据
BOOL bRet = ::WriteProcessMemory( hProcess, pszDllName,
szDllName, MAX_PATH, NULL);

if (NULL == bRet)
{
return -1;
}

//4. 在远程进程中创建远程线程
m_hInjecthread = ::CreateRemoteThread(hProcess, //远程进程句柄
NULL, //安全属性
0, //栈大小
(LPTHREAD_START_ROUTINE)LoadLibrary, //进程处理函数
pszDllName, //传入参数
NULL, //默认创建后的状态
NULL); //线程ID

if (NULL == m_hInjecthread)
{
DWORD dwErr = GetLastError();
return -1;
}

//5. 等待线程结束返回
DWORD dw = WaitForSingleObject(m_hInjecthread, -1);
//6. 获取线程退出码,即LoadLibrary的返回值,即dll的首地址
DWORD dwExitCode;
GetExitCodeThread(m_hInjecthread, &dwExitCode);
m_hMod = (HMODULE)dwExitCode;

//7. 释放空间
BOOL bReturn = VirtualFreeEx(hProcess, pszDllName,
4096, MEM_DECOMMIT);

if (NULL == bReturn)
{
return -1;
}

CloseHandle(hProcess);
hProcess = NULL;
//恢复权限相关操作
EnablePrivilege(FALSE);

return 0;
} 此外,我们还需要提升进程权限以便于提高注入成功率,所需API如下表所示:
OpenProcessToken得到令牌句柄
LookupPrivilegeValue得到权限值
AdjustTokenPrivileges提升令牌句柄权限
int CRemoteThreadInjectDLL::EnablePrivilege(bool isStart)
{
//1. 得到令牌句柄
HANDLE  hToken = NULL;      //令牌句柄
if (!OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_READ,
&hToken))
{
return FALSE;
}

//2. 得到特权值
LUID    luid = {0};         //特权值
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
{
return FALSE;
}
//3. 提升令牌句柄权限
TOKEN_PRIVILEGES tp = {0};  //令牌新权限
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = isStart ? SE_PRIVILEGE_ENABLED : 0;
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL))
{
return FALSE;
}
//4. 关闭令牌句柄
CloseHandle(hToken);
return 0;
}


当要在指定的进程中加载DLL时,我们就需要过滤指定名称的进程,这时遍历进程ID并进行对比,得到所指定的进程,所需API如表所示:
CreateToolhelp32Snapshot  创建进程快照  
Process32First  第一个进程快照
Process32Next  循环下一个进程快照  
DWORD CRemoteThreadInjectDLL::GetProcessId(PTCHAR pszProcessName)
{
HANDLE hProcess = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

if (INVALID_HANDLE_VALUE == hProcess)
{
return 0;
}

DWORD dwProcessId = 0;

PROCESSENTRY32 process32 = {0};
process32.dwSize = sizeof(PROCESSENTRY32);

BOOL bRetProcess = FALSE;
bRetProcess = ::Process32First(hProcess, &process32);

do
{
if (_tcscmp(pszProcessName, process32.szExeFile) == 0)
{
dwProcessId = process32.th32ProcessID;
break;
}

bRetProcess = ::Process32Next(hProcess, &process32);
}while (bRetProcess);
::CloseHandle(hProcess);

return dwProcessId;
}

远线程注入API使用较多,不易实现。但是可以批量注入和卸载,这样对于需要反复调试的注入就非常的方便。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: