重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
DLL劫持利用系统未知DLL的搜索路径方式,使得程序加载当前目录下的系统同名DLL。所以可以告诉系统DLL的位置,改变加载系统DLL的顺序不是当前目录,而是直接到系统目录下查找。
创新互联公司专业提供四川服务器托管服务,为用户提供五星数据中心、电信、双线接入解决方案,用户可自行在线购买四川服务器托管服务,并享受7*24小时金牌售后服务。
这个想法可以通过修改注册表实现。
在注册表键值:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
是调用系统DLL的首要查找目录。例如里面有RE_SZ类型的ntdll=ntdll.dll项,则系统载入ntdll时会直接从系统目录加载。
由此,添加LPK=LPK.DLL即可防止LPK被劫持,同理可以阻止一些其他DLL被劫持,例如USP10。
在Windows NT系统,XP默认只有少数关键DLL在此键值下,Win7下面此键值已经相当齐全,在Win7系统下发生DLL劫持的概率要比XP小很多。
一 回顾DLL挟持的发展
2010年08月24日微软发布安全公告2269637,提到三方软件编程不安全存在一个DLL挟持的缺陷可以导致远程攻击
2010年08月24日流行的漏洞信息共享网站exploit-db马上就爆出多个DLL挟持漏洞涉及的软件有:Wireshark(免费嗅探器),Windows
Live email(邮箱客户端), Microsoft MovieMaker(视频编辑处理),Firefox(网页浏览器),
uTorrent (BT下载工具),PowerPoint 2010(办公软件)等
2010年08月25日-26日漏洞信息共享网站exploit-db继续爆出Winamp,Google
Earth,Photoshop等软件存在DLL挟持漏洞,同时发布这个blog之前笔者的电脑中已经发掘存在的流行软件有,QQ影音,QQ音乐,美图秀秀,ppstream等
二新老DLL挟持的攻击原理分析和防御
1 动态链接库文件通常加载顺序如下
windows xp sp2系统以上会默认开启SafeDllSearchMode,安全dll搜索模式下DLL文件的搜索顺序如下所示
(1)可执行程序加载的目录(可理解为程序安装目录比如
C:\Program Files\uTorrent)(2)系统目录(即 %windir%\system32 )(3)16位系统目录(即
%windir%\system)(4)Windows目录(即 %windir%)(5)运行某文件的所在目录,比如C:\Documents and
Settings\Administrator\Desktop\test)(6)PATH环境变量中列出的目录
2 老DLL挟持触发的原理解析和防御(漏洞触发在DLL搜索流程的第一层,运行程序即加载病毒)
(1)老DLL挟持的特点:
为了增加触发的概率,通常会使用usp1.dll,ws2_32.dll,lpk.dll等应用程序所必须的系统dll文件,然后利用DLL搜索第一顺位是程序安装目录,在程序安装目录释放一个同名DLL文件,抢先加载恶意病毒DLL文件,从而达到破坏的作用。这里可执行程序相当于恶意dll的加载器
(2)老DLL挟持病毒利用回顾重现
2007年罗姆病毒(ws2_32.dll导致很多杀毒软件无法打开),2009年春节猫癣病毒(usp10.dll导致很多用户重装系统都无法解决病毒问题)
通常使用老DLL挟持的病毒木马会枚举电脑里面的所有exe目录,然后将恶意的usp10.dll释放到每个exe所在的目录。当用户执行一个应用程序的时候,将会把恶意的usp10.dll文件优先加载从而感染系统
根据前面介绍的DLL加载顺序,运行程序的时候会优先到程序执行的目录下加载必须文件,下图显示了utorrent.exe在安装目录下的找到了usp10.dll文件并把它加载到内存中。
(3)老DLL挟持的通用免疫方案
可以通过编辑HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs来添加需要面议的DLL文件,比如:新建一个ws2_32 指向ws2_32.dll
3 新DLL挟持触发的原理解析和防御(漏洞触发在DLL搜索流程的第五层,运行图片即加载病毒)
(1)新DLL挟持的特点:
应用程序为了扩展或者兼容等目的需要加载相应的DLL文件,但是因为某些原因导致这个DLL文件默认不存在于当前系统,比如plugin_dll.dll文件默认情况下不存在utorrent的安装目录,dwmapi.dllxp环境下不存在(Vista以上系统存在),ie6环境下没有ieframe.dll(ie7以上版本存在)。正是因为程序需要的DLL文件在DLL搜索顺序的(1)-(4)中都不可能存在,此时就会尝试加载文件所在目录下的恶意dll文件,从而达到破坏的作用。这里运行的文件(比如mp3)相当于触发者,根据文件关联它会启动一个应用程序去播放mp3文件。而因为应用程序存在DLL挟持漏洞(比如QQ影音),此时QQ影音就会因为设计上的不足导致成为恶意DLL的加载器。相当于老DLL挟持,简直达到了运行图片/视频文件就会执行恶意文件的目的,当然前提是大灰客们能猜中你电脑里面的默认查看的软件是否存在DLL挟持漏洞了,目前已经发现的存在DLL挟持缺陷的主要有以下几类
① 特定系统环境下的文件
典型的有dwmapi.dll文件,xp环境下不存在,vista以上版本存在,也就是说需要触发这个漏洞的系统环境只能是XP系统
② 特定软件版本下的文件
典型的有:ieframe.dll,IE6下不 存在,ie7以上版本有,也就是说触发漏洞的电脑IE必须是IE6版本
③ 特定的库文件
典型的有:mfc80chs.dll
④ 程序自己需要的dll文件,可能是为了功能扩展或者兼容
典型的有:plugin_dll.dll
⑤ 其它未知
(2)新DLL挟持利用重现
通常灰客们会先通过DLL挟持挖掘工具寻找存在DLL挟持漏洞的流行应用程序,然后构造相应的文件上传到网络上供用户下载(具体的传播方式请看下一章),如果用户的电脑存在漏洞那么运行相应文件的时候就会执行存在漏洞的程序,从而使得恶意dll被不知不觉加载
根据前面介绍的DLL加载顺序和新DLL挟持的特点,程序在前四个流程都没有找到需要的文件,只能勉为其难的在第五流程-当前文件目录下加载恶意dll文件,下图就显示了uTorrent加载plugin_dll.dll顺序(前四个流程都是
name not found)并且加载当前目录下恶意plugin_dll.dll文件(第五流程显示的是success )的过程
(3)新DLL挟持的免疫
目前微软没有提供有效的免疫方案可以使用,建议升级你常用软件到最新版本.
三 新DLL挟持可能存在的攻击方式
exploit-db公布了存在DLL
Hijacking的大量常用软件,这些软件里面有视频音频播放器,图像设计浏览软件,IM聊天工具,文字处理软件,网页浏览器,下载软件,杀毒软件。根据在下的一点拙见如果病毒作者想要利用这个漏洞来实现广泛传播的话主要有几种方式。
1 BT下载大片传播
挖掘出支持BT下载的流行软件(比如uTorrent
)的DLL
Hijacking漏洞,然后构造一个恶意dll文件(估计会设置隐藏属性,这样你解压以后将不会看到这个文件)和BT种子文件打包成压缩包上传到网上供用户下载,用户一旦下载了这个压缩包双击BT种子文件的时候会调用uTorrent
打开,uTorrent 运行的时候由于设计上的不河蟹根据dll加载的顺序最后会将种子所在目录的恶意dll加载
2 美女图片分享传播
挖掘出流行图片浏览工具(比如美图秀秀)的DLL
Hijacking漏洞,然后构造一个恶意dll文件(估计会设置隐藏属性,这样你解压以后将不会看到这个文件)和图片文件打包成压缩包上传到网上供用户下载,用户一旦下载了这个压缩包,解压浏览美女靓照的时候可能会调用图片浏览工具打开从而触发漏洞加载恶意dll文件
3 软件下载包含的网页文件传播
挖掘出流行网页浏览工具(比如firefox)的DLL
Hijacking漏洞,然后构造一个恶意dll文件(估计会设置隐藏属性,这样你解压以后将不会看到这个文件),应用程序和htm等网页文件打包成软件压缩包并上传到网上供用户下载。用户一旦下载了这个软件压缩包,解压以后运行安装必看.htm之类的网页文件会调用网页浏览工具打开从而触发漏洞加载恶意dll文件
4 热门视频音频文件传播
挖掘出流行视频音频播放工具(比如QQ影音)的DLL
Hijacking漏洞,然后构造一个恶意dll文件(估计会设置隐藏属性,这样你解压以后将不会看到这个文件)和rmvb等视音频文件打包压缩包并上传到网上供用户下载。用户一旦下载了这个压缩包,解压播放相应视频的时候从而触发漏洞加载恶意dll文件
5 目前公布的部分软件列表
Google Earth
Nullsoft Winamp 5.581
Media Player Classic 6.4.9.1
Mozilla Thunderbird
Microsoft Office PowerPoint 2007
Adobe InDesign CS4
Nvidia Driver
Adobe Illustrator CS4
Adobe Premier Pro CS4
Skype = 4.2.0.169
TechSmith Snagit 10
Safari v5.0.1
uTorrent
Microsoft Visio 2003
Adobe Photoshop CS2
avast! = 5.0.594
Adobe Dreamweaver CS5
Opera v10.61
Firefox = 3.6.8
四 DLL安全编程,避免产生DLL挟持问题
(1) 调用LoadLibrary, LoadLibraryEx, CreateProcess的,或者 的ShellExecute 等涉及到模块加载的函数的时候,指定DLL加载的完整路径,貌似应该有API可以获取当前程序运行的目录的
(2)考虑使用 的DLL重定向 或 Manifests文件 ,以确保您的应用程序使用正确的DLL。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
(3)确保DLL安全搜索模式被激活。未使用安全搜索设置的话,第二加载项就是当前目录。
HKLM\System\CurrentControlSet\Control\Session Manager \ SafeDllSearchMode
(4)从搜索列表中取消当前目录,可以通过调用SetDllDirectory 参数设置为一个空字符串
hook是一个英语单词,名词、动词,作名词时意思是“挂钩,吊钩”,作及物动词时意思是“钩住;引上钩”,作不及物动词时意思是“钩住;弯成钩状”。
.hook是Windows中提供的一种用以替换DOS下“中断”的系统机制。
双语例句
1、Hang your coat up on that hook.
把你的上衣挂在那个挂钩上。
2、Hang your coat on the hook.
把你的外套挂在那个钩上。
3、You can tap into key moments in that lifecycle by implementing one or more of the lifecycle hook interfaces.
你可以通过实现一个或多个生命周期钩子接口,切入到生命周期中的关键时间点。
Hook原理
每一个Hook都有一个与之相关联的指针列表,称之为钩子链表,由系统来维护。这个列表的指针指向指定的,应用程序定义的,被Hook子程调用的回调函数,也就是该钩子的各个处理子程序。当与指定的Hook类型关联的消息发生时,系统就把这个消息传递到Hook子程。
一些Hook子程可以只监视消息,或者修改消息,或者停止消息的前进,避免这些消息传递到下一个Hook子程或者目的窗口。最近安装的钩子放在链的开始,而最早安装的钩子放在最后,也就是后加入的先获得控制权。
Windows 并不要求钩子子程的卸载顺序一定得和安装顺序相反。每当有一个钩子被卸载,Windows 便释放其占用的内存,并更新整个Hook链表。如果程序安装了钩子,但是在尚未卸载钩子之前就结束了,那么系统会自动为它做卸载钩子的操作。
钩子子程是一个应用程序定义的回调函数(CALLBACK Function),不能定义成某个类的成员函数,只能定义为普通的C函数。用以监视系统或某一特定类型的事件,这些事件可以是与某一特定线程关联的,也可以是系统中所有线程的事件。
答案
首先函数柯里化因为参数固定,使用vars数组保存每次传进来的参数,然后判断fn的参数个数,如果fn参数个数正好等于vars数组中保存的个数,那么执行fn,否则递归一次,返回curried函数,继续等待输入。这里外层curry 函数只会执行一次便会被剥离,之后add会变成curried的一个引用,同时curried可以闭包引用外层的vars,使得每次传入的参数可以长久保存。
参考上面网上优秀答案的思路,写出这个不定参数处理add函数,...args可以接受不定参数,由于题目二中并没有题目一中 const add = curry((a, b ,c ,d) = a + b + c +d) 函数劫持的过程,所以不能直接返回函数定义,而是要返回一个执行完的函数curried(...args),同时在curried中再返回一个函数定义curried,这样就可以把函数连接起来了。由于参数不定,这里对每次传入的参数都要进行执行处理,执行方法是利用函数的隐式转换,当函数执行结束时会有一个toString的操作,来使函数能参与其他的运算,这里我们将toString从新定义,返回vars中的累加值,从而实现add运算。
哔哩哔哩。API劫持主要是利用动态链接技术,通过预先加载SO,隐藏符号,是有由教程视频的,可以前往哔哩哔哩学习。ApiHook又叫做API劫持,也就是如果A程序调用了B.cll里面的C函数,我们可以做到当A调用C函数执行的时候,直接执行我们自己事先准备好的函数,之后我们在执行真正的C,当然我们可以不执行C或者更改C的参数。
HOOK技术是Windows消息处理机制的一个平台,应用程序可以在上面设置子程序以监视指定窗口的某种消息,而且所监视的窗口可以是其他进程所创建的。当消息到达后,在目标窗口处理函数之前处理它。钩子机制允许应用程序截获处理window消息或特定事件。
钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。
扩展资料:
Hook原理
Hook技术无论对安全软件还是恶意软件都是十分关键的一项技术,其本质就是劫持函数调用。但是由于处于Linux用户态,每个进程都有自己独立的进程空间,所以必须先注入到所要Hook的进程空间,修改其内存中的进程代码,替换其过程表的符号地址。在Android中一般是通过ptrace函数附加进程,然后向远程进程注入so库,从而达到监控以及远程进程关键函数挂钩。
Hook技术的难点,并不在于Hook技术,初学者借助于资料“照葫芦画瓢”能够很容易就掌握Hook的基本使用方法。如何找到函数的入口点、替换函数,这就涉及了理解函数的连接与加载机制。
从Android的开发来说,Android系统本身就提供给了我们两种开发模式,基于AndroidSDK的Java语言开发,基于AndroidNDK的NativeC/C++语言开发。所以,我们在讨论Hook的时候就必须在两个层面上来讨论。
对于Native层来说Hook的难点其实是在理解ELF文件与学习ELF文件上,特别是对ELF文件不太了解的读者来说;对于Java层来说,Hook就需要了解虚拟机的特性与Java上反射的使用。
转载:
原始函数是这样的
[cpp] view plain copy
kernel32!CreateProcessInternalW:
00000000`7738e750 4c8bdc mov r11,rsp
00000000`7738e753 53 push rbx
00000000`7738e754 56 push rsi
00000000`7738e755 57 push rdi
00000000`7738e756 4154 push r12
00000000`7738e758 4155 push r13
00000000`7738e75a 4156 push r14
00000000`7738e75c 4157 push r15
00000000`7738e75e 4881ec400b0000 sub rsp,0B40h
00000000`7738e765 488b0564cc0e00 mov rax,qword ptr [kernel32!local_unwind+0x606b1 (00000000`7747b3d0)]
跟32位一样,在函数入口写入跳转指令,跟32不一样的是,不能再用之前的E9 xx xx xx xx这样的指令了,E9不支持64位地址跳转,最大只能支持到32位,
直接用E9大部分情况下会出错.所以我们换一种方法.
[cpp] view plain copy
mov rax,0x1122334455667788
jmp rax
机器码是48 b8 8877665544332211 ffe0总共占了12个字节,不是我们之前用E9跳转的5字节了.
最前面的48叫REX Prefix,大家可以GOOGLE下,4是固定的,8表示使用64位寄存器.
如果没有前面的48就变成了mov eax, 0x1122334455667788了,使用32位寄存器.
我们需要把函数前面12字节改成跳转指令,正好
[cpp] view plain copy
00000000`7738e750 4c8bdc mov r11,rsp
00000000`7738e753 53 push rbx
00000000`7738e754 56 push rsi
00000000`7738e755 57 push rdi
00000000`7738e756 4154 push r12
00000000`7738e758 4155 push r13
00000000`7738e75a 4156 push r14
这12个字节是完整的7条指令,写入12字节指令,不会破坏后面的指令.
写入跳转指令后
[cpp] view plain copy
kernel32!CreateProcessInternalW:
00000000`7738e750 48b8001055fbfe070000 mov rax,offset x64dll!FakeCreateProcessInternal (000007fe`fb551000)
00000000`7738e75a ffe0 jmp rax
00000000`7738e75c 4157 push r15
00000000`7738e75e 4881ec400b0000 sub rsp,0B40h
00000000`7738e765 488b0564cc0e00 mov rax,qword ptr [kernel32!local_unwind+0x606b1 (00000000`7747b3d0)]
00000000`7738e76c 4833c4 xor rax,rsp
00000000`7738e76f 48898424300b0000 mov qword ptr [rsp+0B30h],rax
00000000`7738e777 4889a42438050000 mov qword ptr [rsp+538h],rsp
完整代码如下.
少NTDLL.h的朋友可以去搜索下载,也可以把RtlAdjustPrivilege替换成AdjustTokenPrivileges,效果样的,只是代码多几行而已.
声明:本人很菜,水平有限,汇编功底也是相当的水,如发现有误人子弟之处,敬请指正.若您有更好的方法也请多多指教.
[cpp] view plain copy
#include stdio.h
#include tchar.h
#include windows.h
#include shlwapi.h
#include ntdll.h
#pragma comment(lib, "shlwapi.lib")
#define CODE_LEN 12
TCHAR ModuleFile[MAX_PATH];
DWORD dwOldProtect;
BYTE OldCode[CODE_LEN] = {0x90};
typedef HANDLE (WINAPI *__CreateProcessInternal)(HANDLE hToken,LPCTSTR lpApplicationName,LPTSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCTSTR lpCurrentDirectory,LPSTARTUPINFOA lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation,PHANDLE hNewToken);
__CreateProcessInternal pfnCreateProcess = 0;
HANDLE WINAPI FakeCreateProcessInternal(HANDLE hToken,LPCTSTR lpApplicationName,LPTSTR lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL bInheritHandles,DWORD dwCreationFlags,LPVOID lpEnvironment,LPCTSTR lpCurrentDirectory,LPSTARTUPINFOA lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation,PHANDLE hNewToken)
{
MessageBox(NULL, lpCommandLine, lpApplicationName, MB_ICONASTERISK);
return pfnCreateProcess(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken);
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
::DisableThreadLibraryCalls(hinstDLL);
GetModuleFileName(NULL, ModuleFile, _countof(ModuleFile));
if (StrRStrI(ModuleFile, 0, TEXT("explorer.exe")))
{
pfnCreateProcess = (__CreateProcessInternal)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "CreateProcessInternalW");
::VirtualProtect(pfnCreateProcess, CODE_LEN, PAGE_EXECUTE_READWRITE, dwOldProtect);
memcpy(OldCode, pfnCreateProcess, CODE_LEN);
memset(pfnCreateProcess, 0x90, CODE_LEN);
/*
mov rax, FakeCreateProcessInternal
jmp rax
*/
*(LPWORD)pfnCreateProcess = 0xb848;
*(INT64*)((INT64)pfnCreateProcess+2) = (INT64)FakeCreateProcessInternal;
*(LPWORD)((INT64)pfnCreateProcess+10) = 0xe0ff;
::VirtualProtect(pfnCreateProcess, CODE_LEN, dwOldProtect, NULL);
pfnCreateProcess = (__CreateProcessInternal)VirtualAlloc(NULL, CODE_LEN+12, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(pfnCreateProcess, OldCode, CODE_LEN);
/*
mov rax, CreateProcessInternalW + CODE_LEN
jmp rax
*/
*(LPWORD)((INT64)pfnCreateProcess+CODE_LEN) = 0xb848;
*(INT64*)((INT64)pfnCreateProcess+CODE_LEN+2) = (INT64)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "CreateProcessInternalW")+CODE_LEN;
*(LPWORD)((INT64)pfnCreateProcess+CODE_LEN+10) = 0xe0ff;
}
else if (StrRStrI(ModuleFile, 0, TEXT("Rundll32.exe")))
{
DWORD dwProcessId = 0;
HANDLE hProcess = 0;
HWND hwndDeskTop;
hwndDeskTop = FindWindow(TEXT("ProgMan"), NULL);
GetModuleFileName(hinstDLL, ModuleFile, _countof(ModuleFile));
GetWindowThreadProcessId(hwndDeskTop, dwProcessId);
BOOLEAN bEnable;
::RtlAdjustPrivilege(0x13, 1, 0, bEnable);
if (dwProcessId)
{
hProcess = OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION, NULL, dwProcessId);
}
LPVOID Param = VirtualAllocEx(hProcess, NULL, 256, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(hProcess, Param, (LPVOID)ModuleFile, 256, NULL);
HANDLE hThread = CreateRemoteThread(hProcess,
NULL,
NULL,
(LPTHREAD_START_ROUTINE)LoadLibraryW,
Param,
NULL,
NULL);
if (hThread)
{
WaitForSingleObject(hThread, INFINITE);
}
VirtualFreeEx(hProcess, Param , 0, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
}
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
int _stdcall Setup(void)
{
return 1;
}
编译成DLL后,在运行里执行rundll32.exe X64Dll.dll,Setup,DLL会自动注入到explorer.exe进程.
完全工程及编译好的文件点击打开链接
顺便说下,CreateRemoteThread在WIN7下是可以用的,问题不在CreateRemoteThread,而是在OpenProcess打开进程的权限
权限设为
[cpp] view plain copy
PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_WRITE|PROCESS_QUERY_INFORMATION
就可以了,WIN7( 32/64)测试都没问题