dll注入与hook
使用dll的方法
- 隐式链接(lib+dll+头文件) #pragma comment(lib,“libname.lib”) #include<libname.h> 调用
- 只有dll文件(显式链接) LoadLibrary hModule GetProcAddress funcName FreeLibrary 或在.h文件中: extern “C” funcName()
在动态链接库项目被编译后,会生成lib文件和dll文件 .lib文件: 存储了导出函数的名称和位置 .dll文件: 包含实际的函数代码和数据
dll劫持
原理:程序调用loadlibrary载入库时,如果使用了相对路径,可能会加载同名其他恶意dll dll加载目录搜索顺序:
- 程序所在目录
- 加载dll时所在的当前目录(比如在桌面打开图片,桌面就是当前目录)
- 系统目录system32
- Windows目录
- Path环境变量下的目录
微软的应对措施:
- 开启safedllsearchmode,改变加载顺序,即将上表中的第二加载改为倒数第二加载
- 注册表中knowndlls项规定了某些特殊的dll,这些dll必须在system32目录中寻找并加载
- 微软还提供了一个ExcludeFromKnownDlls项,重启生效
防御:
- 使用绝对路径
- 白名单,签名机制
- SetDllDirectory把当前目录一项去掉
全局钩子
HHOOK WINAPI SetWindowsHookEx( int idhook;\钩子类型 HOOKPROC lpfn;\回调函数地址 HINSTANCE hMod;\包含lpfn的实例句柄 DWORD dwThreadid;\线程ID,如果是零,则监控所有线程的全局钩子 ) 钩子类型:
值 | 含义 |
---|---|
WH_CALLWNDPROC | 安装钩子程序,在系统将消息发送到目标窗口过程之前监视消息。 |
WH_CALLWNDPROCRET | 安装钩子程序,在目标窗口过程处理消息后监视消息。 |
WH_CBT | 安装接收对CBT应用程序有用的通知的挂钩程序。 |
WH_DEBUG | 安装可用于调试其他挂钩程序的挂钩程序。 |
WH_FOREGROUNDIDLE | 安装将在应用程序的前台线程即将变为空闲时调用的钩子过程。该挂钩对于在空闲时执行低优先级任务很有用。 |
WH_GETMESSAGE | 安装一个监视发送到消息队列的消息的挂钩过程。 |
WH_JOURNALPLAYBACK | 安装一个挂钩过程,用于发布先前由WH_JOURNALRECORD挂钩过程记录的消息。 |
WH_JOURNALRECORD | 安装一个挂钩过程,记录发布到系统消息队列的输入消息。这个钩子对于录制宏很有用。 |
WH_KEYBOARD | 安装监视按键消息的挂钩过程。 |
WH_KEYBOARD_LL | 安装监视低级别键盘输入事件的挂钩过程。 |
WH_MOUSE | 安装监视鼠标消息的挂钩过程。 |
WH_MOUSE_LL | 安装监视低级别鼠标输入事件的挂钩过程。 |
WH_MSGFILTER | 安装钩子程序,用于监视在对话框,消息框,菜单或滚动条中由于输入事件而生成的消息。 |
WH_SHELL | 安装接收对shell应用程序有用的通知的挂钩程序。 |
WH_SYSMSGFILTER | 安装钩子程序,用于监视在对话框,消息框,菜单或滚动条中由于输入事件而生成的消息。钩子程序监视与调用线程相同的桌面中的所有应用程序的这些消息。 |
普通的钩子需要写在dll程序中才能执行,但是低级键盘钩子可以在无dll的情况下运行,比如低级键盘钩子和低级鼠标钩子,判断钩子的优先级遵循一个原则,后下的钩子先执行,WH_DEBUG>WH_KEYBOARD_LL>WH_KEYBOARD,即调试钩子>低级钩子>普通钩子
早期QQ的防止记录措施,登录前每秒hook和unhook钩子,保证自己的钩子最后下,最先拿到数据,防止其他钩子获取到正确密码
PE共享节及dll注入
#pragma data_seg(".shared") ULONG g_ulNum #pragma data_seg() #pragma comment(linker,"/SECTION:.shared,RWS") RWS即为写/读/共享 共享段内的数据可供多个进程访问,普通的全局变量只能一个进程内部访问,共享段可用于多个进程间通信 dll注入的几种方法:
- CreateRemoteThread() 最常用的注入方法,缺点是对于session 0的服务无能为力,无法注入
- NtCreateThreadEx() 该函数是ntdll.dll中的未文档化的函数,能够突破session 0的限制
函数原型为: DWORD WINAPI ZwCreateThreadEx(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended, SIZE_T ZeroBits, SIZE_T StackSize, SIZE_T MaximumStackSize, LPVOID pUnkown ) 其中比较重要的参数是CreateSuspended这一个,表示创建线程后是否挂起 - QueueUserAPC()
- SetWindowsHookEx()
- RtlCreateUserThread() 该函数也是未导出函数,同样也可以突破session 0的限制,函数原型:
DWORD WINAPI RtlCreateUserThread(
HANDLE Process, //句柄 PSECURITY_DESCRIPTOR ThreadSecurityDescriptor, //线程安全描述符
BOOLEAN CreateSuspended, //创建挂起标志 ULONG ZeroBits, SIZE_T MaximumStackSize, SIZE_T CommittedStackSize, PUSER_THREAD_START_ROUTINE StartAddress, //远程线程函数 PVOID Parameter OPTIONAL, //参数 PHANDLE Thread OPTIONAL, PCLIENT_ID ClientId OPTIONAL ); - SetThreadContext()
- 反射式dll注入