1. 通过GetModuleHandle定位LoadLiabrary在Kernel32.dll中的虚拟地址!!(根据jerry 牛人的说法,就是kernel32.dll在任何进程中加载的位置都是一样的)
2. 提升当前进程的权限,使其权限提升为debug的权限,这样才能在目标进程中分配虚拟空间和读写虚拟空间操作。
3. 在目标进程中分配存放LoadLibrary的参数的内存。因为必须将参数写到目标进程中,才能让创建的线程访问,要不然,就会发生进程访问数据冲突,(不能垮进程访问地址),通过函数VirtualAllocEx.
4. 在分配的地址空间中写入参数值,通过WriteProcessMemery.
5. 调用CreateRemoteThread创建远程线程!
6. 补充说明一下:提升权限用到的函数:
1)通过OpenProcess一查询权限打开自己的进程.
2)通过OpenProcessToken打开访问令牌。
3)通过LookupPrivilegeValue查询debug权限的值
4)通过AdjustPrivilegeValue来调整进程权限
7. 在写的过程中遇到了很多麻烦,其中一个问题就是,当我代码没有问题的时候,发现老师只能注入自己的线程,其他的都注入不进去,后来啄么了很久,才防线是依赖库的问题,没有吧依赖库放到一起,再者,需要注意的是,当远程线程在目标进程中运行的时候,如果你传的路径不是绝对路径,那么也会出问题,因为他要从目标进程的目录中搜索,搜索不到,在从环境变量中列出的路径搜索,所以,路径得必须谨慎。其次,是你的函数和传入的路径字符串要是同一字符集。要不让也会出问题!
8. 如果想要卸载注入的DLL,也很简单,通过注入FreeLiabray线程就OK了!!!方法同上!
代码:
BOOL CMoveCursorDlg::AdjustProcessPrivilege(DWORD dwProcessId)
{
HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,dwProcessId); //以查询方式打开进程
if(hProcess == NULL)
return FALSE;
HANDLE hToken = NULL;
BOOL bRet = FALSE;
DWORD dwErr = 0;
bRet = ::OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY ,&hToken);
dwErr = ::GetLastError();
if(!bRet)
return FALSE;
LUID luid;
if(::LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid) == 0)//查询权限值(设置权限值)
return FALSE;
TOKEN_PRIVILEGES tkp;
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
bRet = ::AdjustTokenPrivileges(hToken,FALSE,&tkp,0,NULL,NULL); //调整权限
if(!bRet)
return FALSE;
::CloseHandle(hToken);
::CloseHandle(hProcess);
return TRUE;
9. }
// //注入目标进程
BOOL CMoveCursorDlg::InjectDesProcess(DWORD dwProcessId)
{
BOOL bRet = FALSE;
DWORD dwCurrProcessId = ::GetCurrentProcessId();
bRet = AdjustProcessPrivilege(dwCurrProcessId); //手动提升当前进程权限
//打开目标进程句柄
m_hDesProcess = ::OpenProcess(PROCESS_ALL_ACCESS,
FALSE , dwProcessId);
if(m_hDesProcess != NULL && bRet)
{
//定位LoadLibraryA在kernel32.dll中的位置
HMODULE hModule = ::GetModuleHandle(_T("Kernel32"));
if(hModule == NULL)
return FALSE;
PTHREAD_START_ROUTINE pfnLoadLibraryW = (PTHREAD_START_ROUTINE)::GetProcAddress(hModule,LPCSTR("LoadLibraryW"));
if(pfnLoadLibraryW == NULL)
return FALSE;
//在远程线程中分配地址空间来存放LoadLibraryA的参数
TCHAR szDllPath[MAX_PATH] ={0};
_tcscpy_s(szDllPath,MAX_PATH, _T("INJDLL.dll")); //DLL路径
DWORD dwSize = lstrlen(szDllPath) * sizeof(TCHAR) + 1;
PCWSTR* lpAddr = (PCWSTR*)::VirtualAllocEx(m_hDesProcess , NULL, dwSize, MEM_COMMIT | MEM_RESERVE , PAGE_EXECUTE_READWRITE);
if(lpAddr == NULL)
return FALSE;
//将数据写入到目标进程地址空间中去
DWORD dwNumBytesOfWritten = 0;
bRet = ::WriteProcessMemory(m_hDesProcess, lpAddr, (LPVOID)szDllPath ,dwSize, &dwNumBytesOfWritten);
if(dwSize != dwNumBytesOfWritten)
{
::VirtualFreeEx(m_hDesProcess,lpAddr,sizeof(szDllPath), MEM_RELEASE); //释放地址空间
return FALSE;
}
if(!bRet)
return FALSE;
//将指定DLL注入目标进程
DWORD dwThreadId = 0;
HANDLE hRemoteThread = ::CreateRemoteThread(m_hDesProcess, NULL, 0, (PTHREAD_START_ROUTINE)pfnLoadLibraryW, lpAddr, 0, &dwThreadId);
if(hRemoteThread == NULL)
return FALSE;
::WaitForSingleObject(hRemoteThread,INFINITE);
::VirtualFreeEx(m_hDesProcess,lpAddr,sizeof(szDllPath), MEM_RELEASE); //释放地址空间
::CloseHandle(hRemoteThread);
return TRUE;
}
else
{
return FALSE;
}
}
10.