在另一个进程中注入代码的方式20171013

在另一个进程中注入代码,可以实现程序员自己编写的功能,这为很多程序员提供了方便,同时也给恶意的黑客(当然黑客范畴很广,并不是一个贬义词,也有好的黑客)提供了可乘之机,不管怎样,注入代码很管用,能做到将代码注入到一个进程,却不被杀毒软件查杀到才最牛。

要想另外一个进程能执行我们写入的代码,就是让另一进程执行我们写入的一个或多个函数功能,最简单的方法就是将函数代码写在dll中,然后通过远程线程注入该dll,其次的方法就是通过远程线程直接将我们写入的函数作为线程回调函数,再其次就是在函数代码写入所要注入的进程中,后通过移动EIP让进程执行我们写的代码,执行完后再移回来。所以注入代码的方式是有很多的,列举如下:1)远程注入dll,2)注入dll到另一进程,然后dll中hook那个所注入的进程,3)直接通过汇编或C语言在另一进程中写代码,当做远程线程函数的回调函数,4)通过移动EIP来执行我们的函数代码。后两种方式需要地址重定位,因此比较复杂。</span>

方法一:远程注入dll
第一步:利用API函数 FindWindow 对要注入代码的进程主窗口名或者类名查找到窗口句柄,然后通过API函数GetWindowThreadProcessId 获得进程的ID和线程的ID,然后通过进程ID打开进程句柄。代码如下:

HWND hWnd = FindWindow(NULL, “计算器”);
DWORD dwPid = 0;
DWORD dwTid = GetWindowThreadProcessId(hWnd, &dwPid);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);

第二步:通过进程句柄利用API函数 VirtualAllocEx 在另一进程中申请一段内存,一般一个分页就够了,属性为可读可写可执行,然后通过API函数WriteProcessMemory 将 *.dll 的地址写入到申请的内存分页的首地址。代码如下:
LPVOID pAddr = VirtualAllocEx(hProcess, NULL, 0x1000, MEM_COMMIT,PAGE_EXECUTE_READWRITE);
DWORD dwNumberOfBytesWritten = 0;
BOOL bRet = WriteProcessMemory(hProcess, (TCHAR*)pAddr, DLLPATH, sizeof(DLLPATH) + 1,&dwNumberOfBytesWritten); 


第三步:创建远程线程CreateRemoteThread,这是注入代码成功的关键,因为线程回调函数有一个参数,而LoadLibrary函数正好也只有一个参数,所以取巧将LoadLibrary作为远程回调函数的回调函数,就可以加载一个 *.dll 到另一进程中。代码如下:
HANDLE hThreadLoad = CreateRemoteThread(hProcess,
NULL, 
0, 
(LPTHREAD_START_ROUTINE)LoadLibrary,
(LPVOID)pAddr,
0,
NULL);
DWORD dwRet = WaitForSingleObject(hThreadLoad, INFINITE);


第四步:释放*.dll , *.dll注入到进程后不会随着远程线程的退出而被释放,同样这里释放*.dll用到 FreeLibrary 函数,再创建一个远程线程,以 FreeLibrary  作为回调函数,然后就可以释放*.dll,不过得以*.dll 的模块地址做为参数,上一个远程线程的返回码即为*.dll的模块首地址,通过GetExitCodeThread 获取即可,代码如下:
DWORD dwExitCode = 0;
bRet = GetExitCodeThread(hThreadLoad, &dwExitCode);
DWORD dwTId = 0;
HANDLE hThreadFree = CreateRemoteThread(hProcess,
NULL, 
0, 
(LPTHREAD_START_ROUTINE)FreeLibrary,
(LPVOID)dwExitCode,
0,
&dwTId);
CloseHandle(hProcess);


方法二:hook某一进程
hook的中文意思是钩子的意思,它的作用是监视程序的运行,在程序运行到某个操作时,将原来代码勾过来检测或者执行我们
自己的代码,然后再还回原来的进程。hook 的类型很多,由设置hook的API函数 SetWindowsHookEx 的第一个参数决定hook的类型,
常见的有WH_CALLWNDPROC、WH_KEYBOARD、WH_MOUSE等,线程发消息即调用SendMessage函数,键盘消息WM_KEYUP
 和 WM_KEYDOWN 和鼠标消息来的时候就能被勾住,即进入到hook的程序中,这是在hook函数的回调函数中,写入我们自己的代码
即可实现一些自己的功能,不过hook的范围比较广,针对性没那么强。
实现步骤:
第一步:创建一个*.dll,在其中设置hook,如下:
g_hHook = SetWindowsHookEx(WH_KEYBOARD,( HOOKPROC)KeyboardProc, (HINSTANCE)m_hCurModule, 0);


返回值为hook程序的句柄,用全局变量保存,是因为后面还需将其解除掉hook,用UnhookWindowsHookEx(g_hHook)。m_hCurModule
为当前dll在进程中的模块地所有址,最后参数为0,说明hook同时运行的所有线程。KeyboardProc为回调函数,只要hook成功了,就会
进入该函数中。
第二步:通过方法一将创建的*.dll文件导入到要注入的线程,即可以hook进程,执行代码,但这样什么窗口都会被hook到,有些是不
需要的,这是可以增加条件来实现过滤,或者因为是注入到某一进程,就是为了监控那一进程的运行,因此可以在回调函数中用
SetWindowLong将回调函数转换一下,退出时转换回来。如:
LRESULT CALLBACK MyWindowProc(
     HWND hwnd,      // handle to window
     UINT uMsg,      // message identifier
     WPARAM wParam,  // first message parameter
     LPARAM lParam   // second message parameter
    )
{
if (uMsg == WM_KEYDOWN)
{
AfxMessageBox(TEXT("uMsg == WM_KEYDOWN"));
}
else if (uMsg == WM_KEYUP)
{
AfxMessageBox(TEXT("uMsg == WM_KEYUP"));
}
else if (uMsg == WM_MOUSEMOVE)
{
AfxMessageBox(TEXT("uMsg == WM_MOUSEMOVE"));
}
return CallWindowProc((pFnWindowProc)theApp.m_pfnWindowProc, hwnd, uMsg, wParam, lParam);
}


LRESULT CALLBACK KeyboardProc(int code,       // hook code
                              WPARAM wParam,  // virtual-key code
                              LPARAM lParam   // keystroke-message information
                              )
{
if (code < 0)
{
CallNextHookEx(g_hHook, code, wParam, lParam);
}

g_pfnWindowProc = (pFnWindowProc)SetWindowLong(g_hMainWnd, GWL_WNDPROC, (LONG)MyWindowProc);


return CallNextHookEx(g_hHook, code, wParam, lParam);
}



猜你喜欢

转载自blog.csdn.net/Denny_Chen_/article/details/78231180
今日推荐