DLL注入相关

来源:互联网 发布:淘宝店铺直播条件 编辑:程序博客网 时间:2024/06/06 01:18

先说说DLL引用的方法:

如果有lib+dll+头文件 

则:建工程的时候选择导出符号

#pragma comment(lib, “libname.lib”)#include “libname.h”func();
只有DLL文件 

LoadLibrary 
GetProcAddress 

因为在C++中有函数重整,(函数名会被自动改变),我们需要在DLL中,在函数前加上

extern "C"
声明是C函数,不要重整函数


SetWindowsHookEx 全局钩子

HHOOK WINAPI SetWindowsHookEx(
__in int idHook, \\钩子类型
__in HOOKPROC lpfn, \\回调函数地址
__in HINSTANCE hMod, \\包含lpfn的实例句柄
__in DWORD dwThreadId); \\线程ID,如果为0,则监控所有线程的全局钩子


WH_CALLWNDPROC and WH_CALLWNDPROCRET
WH_CBT
WH_DEBUG
WH_FOREGROUNDIDLE
WH_GETMESSAGE
WH_JOURNALPLAYBACK
WH_JOURNALRECORD
WH_KEYBOARD_LL
WH_KEYBOARD
WH_MOUSE_LL
WH_MOUSE
WH_MSGFILTER and WH_SYSMSGFILTER
WH_SHELL


得到控制权的钩子函数在完成对消息的处理后,如果想要该消息继续传递,那么它必须调用另外一个SDK中的API函数CallNextHookEx来传递它。钩子函数也可以通过直接返回TRUE来丢弃该消息,并阻止该消息的传递。 


更多钩子https://msdn.microsoft.com/en-us/library/ms644959(VS.85).aspx



全局钩子:

实现文件如下。其中g_hWnd为所有进程共享,并且绕过了系统对可写数据的写时复制机制,维护的是一份拷贝

// Hook.cpp  #include <windows.h>  HHOOK g_hMouse = NULL;  HHOOK g_hKeyboard = NULL;  // 为Hook.DLL创建一个新的节,将全局变量g_hWnd放入其中  #pragma data_seg("MySec")  HWND g_hWnd = NULL;  #pragma data_seg()  // 设置刚创建的节为共享的节  #pragma comment(linker, "/section:MySec,RWS")  // 鼠标钩子过程  LRESULT CALLBACK MouseProc(                             int nCode,      // hook code                             WPARAM wParam,  // message identifier                             LPARAM lParam   // mouse coordinates                             )  {      return 1;   // 屏蔽所有鼠标消息  }  // 键盘钩子过程  LRESULT CALLBACK KeyboardProc(                                int code,       // hook code                                WPARAM wParam,  // virtual-key code                                LPARAM lParam   // keystroke-message information                                )  {      // 后门按键用于结束该进程      if (VK_F2 == wParam)      {          ::SendMessage(g_hWnd, WM_CLOSE, 0, 0);          UnhookWindowsHookEx(g_hKeyboard);          UnhookWindowsHookEx(g_hMouse);      }      else      {          return 1;   // 屏蔽所有键盘消息      }  }  // 安装鼠标钩子过程的函数  void SetHook(HWND hwnd) // 参数是为了让dll获得调用进程的主窗口的句柄  {      g_hWnd = hwnd;      // hook所有进程的鼠标、键盘消息      g_hMouse = SetWindowsHookEx(WH_MOUSE, MouseProc, GetModuleHandle("Hook.dll"), 0);      g_hKeyboard = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle("Hook.dll"), 0);  } 

调用DLL的进程的实现:

/////////////////////////////////////////////////////////////////////////////  // CHookTestDlg message handlers  // 导入函数  __declspec(dllimport) void SetHook(HWND hwnd);  BOOL CHookTestDlg::OnInitDialog()  {      // TODO: Add extra initialization here      // 顶层窗口及最大化窗口的实现      int cxScreen, cyScreen;      cxScreen = GetSystemMetrics(SM_CXSCREEN);      cyScreen = GetSystemMetrics(SM_CYSCREEN);      SetWindowPos(&wndTopMost, 0, 0, cxScreen, cyScreen, SWP_SHOWWINDOW);      // 调用DLL中的函数      SetHook(m_hWnd);      return TRUE;  // return TRUE  unless you set the focus to a control  } 

资料来自:http://blog.csdn.net/xiaobaohe/article/details/6313814

上面是WH_KEYBOARD

下面是使用WH_KEYBOARD_LL 低级键盘钩子 不需要DLL 直接设置即可

// keyboardhook.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include<iostream>#include<windows.h>using namespace std;HHOOK g_Hook;LRESULT CALLBACK LowLevelKeyboardProc(INT nCode, WPARAM wParam, LPARAM lParam){KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *)lParam;BOOL bControlKeyDown = 0;    switch (nCode){case HC_ACTION:{// Check to see if the CTRL key is pressedbControlKeyDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1);//Disable CTRL+ESCif (pkbhs->vkCode == VK_ESCAPE && bControlKeyDown)return 1;if(wParam == WM_KEYUP)printf("%c", pkbhs->vkCode);break;}}return CallNextHookEx(g_Hook, nCode, wParam, lParam); //回调return 1;}int _tmain(int argc, _TCHAR* argv[]){MSG msg;g_Hook=(HHOOK)SetWindowsHookEx(WH_KEYBOARD_LL,(HOOKPROC)LowLevelKeyboardProc, GetModuleHandleW(0),0); while(GetMessageW(&msg,0,0,0))DispatchMessageW(&msg);return 0;}

低级鼠标钩子实例:

// mousehook.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include<iostream>#include<windows.h>using namespace std;/* LPARAM typetypedef struct tagMSLLHOOKSTRUCT {  POINT     pt;  DWORD     mouseData;  DWORD     flags;  DWORD     time;  ULONG_PTR dwExtraInfo;} MSLLHOOKSTRUCT, *PMSLLHOOKSTRUCT, *LPMSLLHOOKSTRUCT;*/LRESULT CALLBACK LowLevelMouseProc(   int nCode,   WPARAM wParam,   LPARAM lParam   ){if(nCode==HC_ACTION){if(wParam==WM_LBUTTONDOWN){return 1;}}return CallNextHookEx(0,nCode,wParam,lParam);}int _tmain(int argc, _TCHAR* argv[]){MSG msg;SetWindowsHookExW(WH_MOUSE_LL,LowLevelMouseProc,GetModuleHandleW(0),0);while(GetMessageW(&msg,0,0,0))DispatchMessageW(&msg);return 0;}

QQ安全密码框的全局钩子

1,WH_DEBUG , WH_KEYBOARD_LL, WH_MOUSE_LL 
2, WH_DEBUG> WH_KEYBOARD_LL> WH_KEYBOARD
3,后加载的先获得消息并执行
4,QQ定时UNHOOK和HOOK上面3个钩子,保证自己最后被安装,自然就是先取得正确的按键信息,然后阻止这个 消息继续传递下来给别人,就算传下去交给别人,也要修改按键信息,传一个错误的下去 


-----------------------------------------------------------------------------------------------------------------------------------------

在下钩子的时候可能我们需要用到通信 可以使用映射,管道,

其实还有一种方便的,就是PE共享节

放到共享节里面的变量时是同实例可以访问的 一般用到多开通信 多开检测,全局dll钩子

#pragma data_seg (".shared")ULONG g_ulNum;#pragma data_seg ()#pragma comment(linker,"/SECTION:.shared,RWS") 
RWS:读/写/共享
共享段里的变量可供进程的多个实例访问
普通的全局变量,只对一个实例有效

也可以实现进程通信


将里面的变量extern 在将所在的头文件引用进来 也可以实现通信

详见

hookSpy InjectEx SetWindowHook
LibSpy CreateRemoteThread LoadLibrary
WinSpy CreateRemoteThread WriteProcessMemory


详见:http://blog.csdn.net/danny_share/article/details/38480141

------------------------------------------------------------------------------------------------------------------------------------------------

DLL注入

分为两种:

1.直接把dll注入目标进程

2.直接把代码注入目标进程

直接注入DLL:
AddDebugPrivilege(void)
OpenProcess()
VirtualAllocEx()
WriteProcessMemory()
CreateRemoteThread()


直接注入代码:
static DWORD WINAPI ThreadFunc (INJDATA *pData)
{
…..
…..
}
AddDebugPrivilege(void)
OpenProcess()
VirtualAllocEx()
WriteProcessMemory()
CreateRemoteThread();


Debug权限与进程打开

BOOL AddDebugPrivilege(void){TOKEN_PRIVILEGES tp;LUID luid;HANDLE hToken;if(!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid)){return FALSE;}tp.PrivilegeCount = 1;tp.Privileges[0].Luid=luid;tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;if(!OpenProcessToken(GetCurrentProcess(),                 TOKEN_ADJUST_PRIVILEGES,&hToken)){return FALSE;}if(!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,(PDWORD)NULL)){return FALSE;}return TRUE;} HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD |                     PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE  |                     PROCESS_VM_READ,FALSE, PID);

其实并不需要这么多函数 但一下函数只能使用在发布版中

typedef long (*RTLADJUSTPRIVILEGE)(ULONG,ULONG,ULONG,PVOID);RTLADJUSTPRIVILEGE RtlAdjustPrivilege;RtlAdjustPrivilege=(RTLADJUSTPRIVILEGE)GetProcAddress(LoadLibraryW(L"ntdll.dll"),"RtlAdjustPrivilege");RtlAdjustPrivilege(20,1,0,&dwRetVal);//debugRtlAdjustPrivilege(19,1,0,&dwRetVal);

这样就可以了

直接注入DLL文件

1。打开目标进程
2。获取待注入的DLL路径,分配一块目标进程内的内存,将路径拷贝到该内存中
3。获取kernel32中的LoadLibraryA地址
4。调用CreateRemoteThread,在目标进程中执行loadlibrary + DLL的动作
5。DLL中的DLLMAIN执行
6。释放分配的目标进程中的内存
7。获取kernel32中的FreeLibrary地址
8。调用CreateRemoteThread,在目标进程中执行FreeLibrary + DLL的动作


int InjectDll( HANDLE hProcess, TCHAR* szLibPath){<span style="white-space:pre"></span>HANDLE hThread;<span style="white-space:pre"></span>void*  pLibRemote = 0;<span style="white-space:pre"></span>DWORD  hLibModule = 0;<span style="white-space:pre"></span>HMODULE hKernel32 = ::GetModuleHandle(_T("Kernel32"));<span style="white-space:pre"></span>LPTHREAD_START_ROUTINE pLoadFunc = NULL;<span style="white-space:pre"></span>pLoadFunc = (LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32,"LoadLibraryW");<span style="white-space:pre"></span>if (szLibPath == NULL ||<span style="white-space:pre"></span>hProcess == NULL ||<span style="white-space:pre"></span>pLoadFunc == NULL)<span style="white-space:pre"></span>{<span style="white-space:pre"></span>return FALSE;<span style="white-space:pre"></span>}<span style="white-space:pre"></span>pLibRemote = ::VirtualAllocEx( hProcess, NULL, (_tcslen(szLibPath) + 1)*sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE );<span style="white-space:pre"></span>if( pLibRemote == NULL )<span style="white-space:pre"></span>return false;<span style="white-space:pre"></span>::WriteProcessMemory(hProcess, pLibRemote, (void*)szLibPath,(_tcslen(szLibPath) + 1)*sizeof(TCHAR),NULL);<span style="white-space:pre"></span>hThread = ::CreateRemoteThread( hProcess, NULL, 0,(LPTHREAD_START_ROUTINE)pLoadFunc, <span style="white-space:pre"></span>pLibRemote, 0, NULL );<span style="white-space:pre"></span>if( hThread == NULL )<span style="white-space:pre"></span>goto JUMP;<span style="white-space:pre"></span>DWORD dwError = GetLastError();<span style="white-space:pre"></span>::WaitForSingleObject( hThread, INFINITE );<span style="white-space:pre"></span>dwError = GetLastError();<span style="white-space:pre"></span>::GetExitCodeThread( hThread, &hLibModule );<span style="white-space:pre"></span>::CloseHandle( hThread );JUMP:<span style="white-space:pre"></span><span style="white-space:pre"></span>::VirtualFreeEx( hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE );<span style="white-space:pre"></span>if( hLibModule == NULL )<span style="white-space:pre"></span>return false;<span style="white-space:pre"></span>return hLibModule;}

我改进了下 直接使用PID ,虽然方便了点,但我自己也不推荐使用

//向目标进程写入DLL名称,和LoadLibraryW / A 然后通过CreateRemoteThread 远程CALL和传参

int InjectDll( DWORD PID, TCHAR* szLibPath){HANDLE hThread;void*  pLibRemote = 0;DWORD  hLibModule = 0;HMODULE hKernel32 = ::GetModuleHandle(_T("Kernel32"));LPTHREAD_START_ROUTINE pLoadFunc = NULL;pLoadFunc = (LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32,"LoadLibraryW");HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD |                     PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE  |                     PROCESS_VM_READ,FALSE, PID);//这个可以拿出去if (szLibPath == NULL ||hProcess == NULL ||pLoadFunc == NULL){return FALSE;}pLibRemote = ::VirtualAllocEx( hProcess, NULL, (_tcslen(szLibPath) + 1)*sizeof(TCHAR), MEM_COMMIT, PAGE_READWRITE );if( pLibRemote == NULL )return false;::WriteProcessMemory(hProcess, pLibRemote, (void*)szLibPath,(_tcslen(szLibPath) + 1)*sizeof(TCHAR),NULL);hThread = ::CreateRemoteThread( hProcess, NULL, 0,(LPTHREAD_START_ROUTINE)pLoadFunc, pLibRemote, 0, NULL );if( hThread == NULL )goto JUMP;DWORD dwError = GetLastError();::WaitForSingleObject( hThread, INFINITE );dwError = GetLastError();::GetExitCodeThread( hThread, &hLibModule );::CloseHandle( hThread );JUMP:::VirtualFreeEx( hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE );if( hLibModule == NULL )return false;return hLibModule;}

//注入程序关键代码UpdateData(TRUE);InjectDll(m_edit,_T("MyDll.dll"));
DLL普通的而已


直接注入代码:

实现线程函数
static DWORD WINAPI ThreadFunc (PVOID *pData)
{

......some code
}
static void AfterThreadFunc (void) 
{
}
打开目标进程(debug权限)
在目标进程内分配pCodeRemote和pDataRemote并将内容拷贝进去//一个是代码 一个是参数
CreateRemoteThread()启动线程执行
从pDataRemote中拿到结果数据
释放pDataRemote和pCodeRemote

声明AfterTheadFunc的原因是获取ThreadFunc函数的长度

代码:向目标写入函数code,和参数

void InjCode (HANDLE hProcess){INJDATA*pDataRemote; DWORD*pCodeRemote; HANDLEhThread = NULL; DWORDdwThreadId = 0;         DWORD           dwNumBytesXferred = 0;pDataRemote = (INJDATA*) VirtualAllocEx( hProcess, 0, sizeof(INJDATA), MEM_COMMIT, PAGE_READWRITE );WriteProcessMemory( hProcess, pDataRemote, &DataLocal, sizeof(INJDATA), &dwNumBytesXferred );const int cbCodeSize = ((LPBYTE) AfterThreadFunc - (LPBYTE) ThreadFunc);pCodeRemote = (PDWORD) VirtualAllocEx( hProcess, 0, cbCodeSize, MEM_COMMIT,PAGE_EXECUTE_READWRITE );WriteProcessMemory( hProcess, pCodeRemote, &ThreadFunc, cbCodeSize, &dwNumBytesXferred );hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) pCodeRemote,pDataRemote, 0 , &dwThreadId);WaitForSingleObject(hThread, INFINITE);ReadProcessMemory( hProcess, pDataRemote, &DataLocal, sizeof(INJDATA), &dwNumBytesXferred);//需要判断pDataRemote,pCodeRemote,hThread的有效性VirtualFreeEx( hProcess, pDataRemote, 0, MEM_RELEASE );VirtualFreeEx( hProcess, pCodeRemote, 0, MEM_RELEASE );CloseHandle(hThread);}

例子:WinSpy

#include <Windows.h>#include "InjCode.h"//---------------------------------------------------------------------// INJDATA// Notice: The data structure being injected.//typedef LRESULT(WINAPI *SENDMESSAGE)(HWND,UINT,WPARAM,LPARAM);typedef struct {HWNDhwnd;SENDMESSAGEfnSendMessage;// pointer to user32!SendMessageBYTEpbText[128 * sizeof(TCHAR)];} INJDATA, *PINJDATA;//---------------------------------------------------------------------// ThreadFunc// Notice: - the code being injected; //   - the remote copy of this function retrieves the password;////Return value: password length//static DWORD WINAPI ThreadFunc (INJDATA *pData){// There must be less than a page-worth of local// variables used in this function.intnXferred = 0;// number of chars retrieved by WM_GETTEXT// Get passwordnXferred = pData->fnSendMessage( pData->hwnd, WM_GETTEXT, sizeof(pData->pbText)/sizeof(TCHAR), (LPARAM)pData->pbText );pData->pbText [127 * sizeof(TCHAR)] = __TEXT('\0');// The thread's exit code is the number // of characters retrieved by WM_GETTEXTreturn nXferred;}// This function marks the memory address after ThreadFunc.// int cbCodeSize = (PBYTE) AfterThreadFunc - (PBYTE) ThreadFunc.static void AfterThreadFunc (void) {}//---------------------------------------------------------------------// GetTextRemote// Notice: - copies ThreadFunc and INJDATA to the remote process;//   - starts the excecution of the remote ThreadFunc;////Return value: password length;//int GetTextRemote (HANDLE hProcess, HWND hWnd, BYTE* pbString, bool fUnicode){HINSTANCEhUser32;INJDATA*pDataRemote;// the address (in the remote process) where INJDATA will be copied to;DWORD*pCodeRemote;// the address (in the remote process) where ThreadFunc will be copied to;HANDLEhThread = NULL; // the handle to the thread executing the remote copy of ThreadFunc;DWORDdwThreadId = 0;int  nCharsXferred = 0; // number of chars retrieved by WM_GETTEXT in the remote thread;DWORD dwNumBytesXferred = 0; // number of bytes written/read to/from the remote process;__try {hUser32 = GetModuleHandle(__TEXT("user32"));if (hUser32 == NULL)__leave;// Initialize INJDATA and then // copy it to the remote processINJDATA DataLocal = {hWnd,(SENDMESSAGE) GetProcAddress(hUser32, fUnicode ? "SendMessageW" : "SendMessageA")};if( DataLocal.fnSendMessage == NULL )__leave;// 1. Allocate memory in the remote process for INJDATA// 2. Write a copy of DataLocal to the allocated memorypDataRemote = (INJDATA*) VirtualAllocEx( hProcess, 0, sizeof(INJDATA), MEM_COMMIT, PAGE_READWRITE );if (pDataRemote == NULL)__leave;WriteProcessMemory( hProcess, pDataRemote, &DataLocal, sizeof(INJDATA), &dwNumBytesXferred );// Calculate the number of bytes that ThreadFunc occupiesconst int cbCodeSize = ((LPBYTE) AfterThreadFunc - (LPBYTE) ThreadFunc);// 1. Allocate memory in the remote process for the injected ThreadFunc// 2. Write a copy of ThreadFunc to the allocated memorypCodeRemote = (PDWORD) VirtualAllocEx( hProcess, 0, cbCodeSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE );if (pCodeRemote == NULL)__leave;WriteProcessMemory( hProcess, pCodeRemote, &ThreadFunc, cbCodeSize, &dwNumBytesXferred );// Start execution of remote ThreadFunchThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) pCodeRemote,pDataRemote, 0 , &dwThreadId);if (hThread == NULL)__leave;WaitForSingleObject(hThread, INFINITE);// Get result (password) backReadProcessMemory( hProcess, pDataRemote, &DataLocal, sizeof(INJDATA), &dwNumBytesXferred);if (fUnicode)  wcscpy((LPWSTR) pbString, (LPCWSTR) DataLocal.pbText);else   strcpy((LPSTR)  pbString, (LPCSTR)  DataLocal.pbText);}__finally {if ( pDataRemote != 0 )VirtualFreeEx( hProcess, pDataRemote, 0, MEM_RELEASE );if ( pCodeRemote != 0 )VirtualFreeEx( hProcess, pCodeRemote, 0, MEM_RELEASE );if ( hThread != NULL ) {GetExitCodeThread(hThread, (PDWORD) &nCharsXferred);CloseHandle(hThread);}}// Return the number of chars retrieved // by WM_GETTEXT in the remote thread.return nCharsXferred;}///////////////////////////////////////////////////////////////////////////int GetWindowTextRemoteA (HANDLE hProcess, HWND hWnd, LPSTR lpString){return GetTextRemote (hProcess, hWnd, (BYTE*)lpString, false);}int GetWindowTextRemoteW (HANDLE hProcess, HWND hWnd, LPWSTR lpString){return GetTextRemote (hProcess, hWnd, (BYTE*)lpString, true);}//////////////////////// End Of File //////////////////////////////////////


获取数据就用ReadProcessMemory



备忘:
hookSpy InjectEx SetWindowHook


LibSpy CreateRemoteThread LoadLibrary


WinSpy CreateRemoteThread WriteProcessMemory


0 0