常用的注入手段有两种:一种是远程的dll的注入,另一种是远程代码的注入;
远程线程注入——其主要核心在于一个Windows API函数CreateRemoteThread,通过它可以在另外一个进程中注入一个线程并执行。
被注入进程A, 注入 进程B
HMODULE WINAPI LoadLibrary( _In_ LPCTSTR lpFileName); 以它为远程线程的回调;
它的参数是我们B进程的, 但是真正执行的是在A进程,怎么样才能把B进程的字符串地址放到A进程中呢?
if(!EnablePrivilege(GetCurrentProcess()))//提升进程权限
{
return;
}
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,NULL,dwPID);
void *pRemoteAdrr = VirtualAllocEx(hProcess,NULL,strlen(pDllPathBuf)+1,MEM_COMMIT,PAGE_READWRITE);
WriteProcessMemory(hProcess,pRemoteAdrr,pDllPathBuf,strlen(pDllPathBuf)+1,NULL);
注入线程并执行
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 );
最关心的两个参数是lpStartAddress和lpParameter,它们分别代表线程函数的入口和参数,其他参数一般设置为0即可。
DWORD dwTID = 0;
HANDLE hThread = CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibrary("Kernel32.dll"),"LoadLibraryA"),\
pRemoteAdrr,\ //线程参数, 即loadlibraryA的参数
0,&dwTID);
WaitForSingleObject(hThread,INFINITE);
GetExitCodeThread(hThread,(LPDWORD)&g_dwhMod); //线程退出码,即为g_dwhMod,它也是loadlibraryA的返回值, 模块句柄;
//此时我们的dll已经执行在进程A中了
释放掉我们在A进程中申请的内存, 并关闭线程句柄
VirtualFreeEx(hProcess,pRemoteAdrr,strlen(pDllPathBuf)+1,MEM_DECOMMIT);
CloseHandle(hProcess);
/////////////////////////////////////////////////////////////////////////////////////////////以上是线程注入部分(load之后也应有free嘛),卸载部分
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,NULL,dwPID);
DWORD dwTID = 0;
HANDLE hThread = CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibrary("Kernel32.dll"),"FreeLibrary"),\
g_dwhMod,\
0,&dwTID);
WaitForSingleObject(hThread,INFINITE);
CloseHandle(hProcess);
到此完事
附加:
//提升进程权限
BOOL EnablePrivilege(HANDLE hProcess)
{
HANDLE hToken = NULL;
if (!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken))
{
//printf("LINE: %u Error_Code: %u\n", __LINE__,GetLastError());
return FALSE;
}
LUID luid = { 0 };
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid))
{
//printf("LINE: %u Error_Code: %u\n", __LINE__, GetLastError());
return FALSE;
};
TOKEN_PRIVILEGES token_privelege = { 1 };
token_privelege.Privileges[0].Luid = luid;
token_privelege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(hToken, FALSE, &token_privelege, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
{
//printf("AdjustTokenPrivileges LINE: %u Error_Code: %u\n", __LINE__, GetLastError());
return FALSE;
};
CloseHandle(hToken);
return TRUE;
}