这是个很古老的DLL注入技术,采用的是创建远程线程的方式。将LdadLibraryA的函数地址当做线程的回调地址,线程参数采用待注入DLL的绝对路径值。这个参数我们得采用VirtualAllocEx和WriteProcessMemory的方式在目标进程进行内存空间的申请和写入。废话不多说,贴上自己写的代码:
DLL注入函数:
bool Dll_Inject(DWORD& v_dwProcessId, const char* v_szDLLPath)
{
bool bRet = false;
HANDLE hProcess = NULL;
PVOID pRemoteThread = NULL;
HANDLE hRemoteThread = NULL;
__try
{
//!<获取进程句柄
printf("GetProcessHandle Start.\n");
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | // Required by Alpha
PROCESS_CREATE_THREAD | // For CreateRemoteThread
PROCESS_VM_OPERATION | // For VirtualAllocEx/VirtualFreeEx
PROCESS_VM_WRITE,
FALSE,
v_dwProcessId); // For WriteProcessMemory, FALSE, v_dwProcessId);
if (hProcess == NULL)
{
printf("GetProcessHandle Failed.<%d>\n", GetLastError());
__leave;
}
printf("GetProcessHandle Success.\n");
//!<在宿主进程中申请内存空间1024字节
printf("VirtualAllocEx Start.\n");
pRemoteThread = VirtualAllocEx(hProcess, NULL, THREAD_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if(pRemoteThread == NULL)
{
printf("VirtualAllocEx Failed.<%d>\n", GetLastError());
__leave;
}
printf("VirtualAllocEx Success.\n");
//!<将待加载的dll路径写入申请的内存空间
printf("WriteProcessMemory Start.\n");
DWORD dwWrite;
if(WriteProcessMemory(hProcess, pRemoteThread, v_szDLLPath, THREAD_SIZE, &dwWrite))
{
if (dwWrite != THREAD_SIZE)
{
printf("WriteProcessMemory Failed.<%d>\n", GetLastError());
VirtualFreeEx(hProcess, pRemoteThread, THREAD_SIZE, MEM_RELEASE);
CloseHandle(hProcess);
__leave;
}
}
else
{
//VirtualFreeEx(hTaskMgr, pRemoteThread, THREAD_SIZE, MEM_RELEASE);
printf("WriteProcessMemory Failed.<%d>\n", GetLastError());
__leave;
}
printf("WriteProcessMemory Success.\n");
//!<获取LoadLibraryA函数地址
printf("CreateRemoteThread Start.\n");
g_RemoteParam.dwLoadLibraryAddr = (DWORD)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA");
DWORD dwThreadId;
hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)g_RemoteParam.dwLoadLibraryAddr, pRemoteThread, 0, &dwThreadId);
if (hRemoteThread == NULL)
{
printf("CreateRemoteThread Failed.<%d>\n", GetLastError());
__leave;
}
printf("CreateRemoteThread Success. Inject Success!\n");
//!<等待线程退出
WaitForSingleObject(hRemoteThread, INFINITE);
bRet = true;
}
__finally
{
//!<释放资源
if (pRemoteThread != NULL)
{
VirtualFreeEx(hProcess, pRemoteThread, THREAD_SIZE, MEM_RELEASE);
}
if (hRemoteThread != NULL)
{
CloseHandle(hRemoteThread);
}
if (hProcess != NULL)
{
CloseHandle(hProcess);
}
}
return bRet;
}
DLL卸载函数:
bool Dll_Enject(DWORD& v_dwProcessId, const char* v_szDLLPath)
{
BOOL bOk = FALSE;
HANDLE hthSnapshot = NULL;
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
__try
{
//!<查找出注入的dll模块的基地址
hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, v_dwProcessId);
if (hthSnapshot == INVALID_HANDLE_VALUE)
__leave;
MODULEENTRY32 me = { sizeof(me) };
BOOL bFound = FALSE;
BOOL bMoreMods = Module32First(hthSnapshot, &me);
for (; bMoreMods; bMoreMods = Module32Next(hthSnapshot, &me))
{
bFound = (stricmp(me.szModule, v_szDLLPath) == 0) || (stricmp(me.szExePath, v_szDLLPath) == 0);
if (bFound)
break;
}
if (!bFound)
__leave;
//!<获取进程句柄
hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION |
PROCESS_CREATE_THREAD |
PROCESS_VM_OPERATION, // For CreateRemoteThread
FALSE, v_dwProcessId);
if (hProcess == NULL)
__leave;
//!<获取卸载dll函数地址
PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");
if (pfnThreadRtn == NULL)
__leave;
//!<直接创建远程进程,这里线程参数不需要再进行内存申请,是因为dll已经注入到目标进程当中,查找出来的dll基地址就是在目标进程当中
hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, me.modBaseAddr, 0, NULL);
if (hThread == NULL)
__leave;
//!<等待线程退出
WaitForSingleObject(hThread, INFINITE);
bOk = TRUE;
}
__finally
{
//!<释放资源
if (hthSnapshot != NULL)
CloseHandle(hthSnapshot);
if (hThread != NULL)
CloseHandle(hThread);
if (hProcess != NULL)
CloseHandle(hProcess);
}
return(bOk);
}
调用例子:
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwTaskMgr;
printf("Input The Process ID:");
scanf("%d", &dwTaskMgr);
std::string szDLLPath = GetCurExePath() + "InjectDll.dll";
//!<先进行提权操作
printf("AdjustTokenPrivileges Start.\n");
if (!EnableDebugPrivilege(TRUE))
{
printf("AdjustTokenPrivileges Failed.<%d>\n", GetLastError());
}
printf("AdjustTokenPrivileges Success.\n");
if (Dll_Inject(dwTaskMgr, szDLLPath.c_str()))
{
Dll_Enject(dwTaskMgr, szDLLPath.c_str());
printf("DLL Injection/Ejection successful.\n");
}
else
{
printf("DLL Injection/Ejection failed.\n");
}
system("pause");
return 0;
}
还有一些工具函数的定义:
#define THREAD_SIZE 1024
typedef struct _REMOTE_PARAMETER
{
DWORD dwLoadLibraryAddr;
}REMOTE_PARAM, *PREMOTE_PARAM;
REMOTE_PARAM g_RemoteParam;
//!<提权操作
BOOL EnableDebugPrivilege( BOOL fEnable )
{
// Enabling the debug privilege allows the application to see
// information about service applications
BOOL fOk = FALSE; // Assume function fails
HANDLE hToken;
// Try to open this process's access token
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
// Attempt to modify the "Debug" privilege
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
//TRACE("AdjustTokenPrivileges:%d\n", GetLastError());
fOk = (GetLastError() == ERROR_SUCCESS);
CloseHandle(hToken);
}
return(fOk);
}
DWORD GetProcessIdByName(const char* v_szName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnapshot)
{
return NULL;
}
PROCESSENTRY32 pe = { sizeof(pe) };
BOOL fOk;
for (fOk = Process32First(hSnapshot, &pe); fOk; fOk = Process32Next(hSnapshot, &pe))
{
if (!stricmp(pe.szExeFile, v_szName))
{
CloseHandle(hSnapshot);
return pe.th32ProcessID;
}
}
return NULL;
}
std::string GetCurExePath()
{
char szExePath[MAX_PATH] = {0};
if (GetModuleFileNameA(NULL, szExePath, MAX_PATH) > 0)
{
LPSTR pos = strrchr(szExePath, '\\');
if (pos)
{
*++pos = 0;
return szExePath;
}
}
else
{
printf("Get Exe Path Failed.");
}
}