huolong blog

dll注入与hook

使用dll的方法

  1. 隐式链接(lib+dll+头文件) #pragma comment(lib,“libname.lib”) #include<libname.h> 调用
  2. 只有dll文件(显式链接) LoadLibrary hModule GetProcAddress funcName FreeLibrary 或在.h文件中: extern “C” funcName()

在动态链接库项目被编译后,会生成lib文件和dll文件 .lib文件: 存储了导出函数的名称和位置 .dll文件: 包含实际的函数代码和数据

dll劫持

原理:程序调用loadlibrary载入库时,如果使用了相对路径,可能会加载同名其他恶意dll dll加载目录搜索顺序:

  1. 程序所在目录
  2. 加载dll时所在的当前目录(比如在桌面打开图片,桌面就是当前目录)
  3. 系统目录system32
  4. Windows目录
  5. 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注入的几种方法:

  1. CreateRemoteThread() 最常用的注入方法,缺点是对于session 0的服务无能为力,无法注入
  2. 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这一个,表示创建线程后是否挂起
  3. QueueUserAPC()
  4. SetWindowsHookEx()
  5. 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 );
  6. SetThreadContext()
  7. 反射式dll注入