IT技术博客大学习 共学习 共进步

深入解析DLL劫持漏洞

程序人生 2016-03-07 23:34:07 浏览 3,804 次

0×00. 导读

DLL劫持是一种古老的技术了,本文是《CVE-2016-0041 Windows 10 PhoneInfo.dll Hijacking Vulnerability》的延伸,介绍了DLL劫持的漏洞原理、漏洞挖掘方法、漏洞利用场景等,同时引入了HaifeiLi关于Chrome/Edge自动下载漏洞的介绍,以及最新版本Edge对DLL注入的缓解措施。本文已在外部发表于乌云知识库,特别感谢tombkeeper在行文思路上的建议。

0×01. DLL劫持漏洞介绍

1.1 漏洞简介

如果在进程尝试加载一个DLL时没有指定DLL的绝对路径,那么Windows会尝试去指定的目录下查找这个DLL;如果攻击者能够控制其中的某一个目录,并且放一个恶意的DLL文件到这个目录下,这个恶意的DLL便会被进程所加载,从而造成代码执行。这就是所谓的DLL劫持。

在Windows XP SP2之前,Windows查找DLL的目录以及对应的顺序如下:
1. 进程对应的应用程序所在目录;
2. 当前目录(Current Directory);
3. 系统目录(通过 GetSystemDirectory 获取);
4. 16位系统目录;
5. Windows目录(通过 GetWindowsDirectory 获取);
6. PATH环境变量中的各个目录;

在Windows下,几乎每一种文件类型都会关联一个对应的处理程序,当我们在资源管理器中打开某种特定类型的文件时,与之相关联的处理程序便会被执行,也就是会新建一个进程,进程默认的 Current Directory (当前目录)就是被打开文件所在的目录。在Windows搜索DLL的这些目录中,攻击者最容易控制的当然是 Current Directory。攻击者可以把恶意的DLL文件和目标文件(如WORD文档)打包在一起,如果受害者进行解压操作,恶意DLL和目标文件就会位于同一个目录,攻击者可以十分方便的实施DLL劫持。

由于早期Windows查找DLL文件的顺序并不合理,可以想象DLL劫持漏洞伴随着Windows存在了相当长的时间。然而,在相当长的一段时间里DLL劫持漏洞并没有受到大家的关注,直到2010年8月,微软发布安全通报2269637,同时网上公布了大量受影响软件的名字,DLL劫持漏洞才开始进入大家的视野。

1.2 漏洞归类

DLL劫持漏洞翻译成英文叫做 DLL Hijacking Vulnerability,CWE将其归类为 Untrusted Search Path Vulnerability。如果想要去CVE数据库中搜索DLL劫持漏洞案例,搜索这两个关键词即可。

1.3 缓解措施

从Windows XP SP2开始,SafeDllSearchMode 默认会被开启。SafeDllSearchMode的开启与否主要影响 Current Directory(当前目录) 在搜索顺序中的位置。开启SafeDllSearchMode后的DLL搜索顺序如下:
1. 进程对应的应用程序所在目录;
2. 系统目录(通过 GetSystemDirectory 获取);
3. 16位系统目录;
4. Windows目录(通过 GetWindowsDirectory 获取);
5. 当前目录
6. PATH环境变量中的各个目录;

启用SafeDllSearchMode之后可以防范大部分DLL劫持,如系统DLL劫持。不过,如果进程尝试加载的DLL并不存在,那么进程仍然会尝试去当前目录加载这个DLL,这是SafeDllSearchMode所无法防范的。不过微软引入了 SetDllDirectory 这个API,给这个API传递一个空字符串就可以将当前目录从DLL搜索顺序中排除掉。

BOOL WINAPI SetDllDirectory(
  _In_opt_ LPCTSTR lpPathName
);
If the lpPathName parameter is an empty string (""), 
the call removes the current directory from the default DLL search order.

1.4 漏洞检查

使用Sysinternals工具包中的 Process Monitor(ProcMon)可以十分方便的检测DLL劫持漏洞,只需要设置几个过滤参数即可。
1. ProcessName 目标进程的名字;
2. Path 文件路径,可以设置为 begins with 当前目录所在路径;
3. Result 结果,设置为 NAME NOT FOUND

0×02. DLL劫持漏洞利用场景

2.1 针对应用程序安装目录的DLL劫持

不管SafeDllSearchMode是否开启,在查找DLL时应用程序本身所在的目录都是最先被搜索的。因此如果能够放一个恶意的DLL文件到程序的安装目录,就可以利用DLL劫持漏洞来执行代码。

这种利用场景的要求相对较高,因为大部分程序默认安装到 %ProgramFiles% 或者是 %ProgramFiles(x86)%。这两个目录都需要管理员权限才可以进行写入操作,也就是说在进行DLL劫持之前,要求已经具有代码执行权限。基于这一原因,软件厂商一般不予处理此类问题。

这种场景多被一些恶意代码所使用,对常用软件进行DLL劫持可以在一定程度替代自启动功能,同时,利用 白加黑 方式还能逃避安全软件的检测。此外,一些外挂或者破解程序也会采用这种方式进行DLL劫持,例如QQ的一些显IP插件就是通过劫持 msimg32.dll 来实现功能的。

2.2 针对文件关联的DLL劫持

在Windows下,我们平时使用的各种文件(如MP3音乐、DOC文档、PDF文档、MKV视频等)都有一个与之关联的默认处理软件。当在资源管理器中打开某种特定类型的文件时,操作系统会自动创建一个进程来处理这个文件,进程对应的程序就是该文件类型关联的默认处理程序,进程的 当前目录 就是被打开文件所在的目录。

例如,如果Adobe Acrobat DC关联了.PDF文件类型,那么打开PDF文件时就会自动创建一个Acrobat.exe进程,进程的当前目录(Current Directory)就是PDF文件所在的目录。如果进程尝试加载一个不存在的DLL,根据默认的DLL搜索顺序,进程最终会搜索到PDF文件所在目录(即当前目录),如果该目录下恰好就存在有一个同名的DLL,那么这个DLL就会被进程所加载。这就是所谓的 文件关联型DLL劫持

相对于 针对应用程序安装目录的DLL劫持针对文件关联的DLL劫持 的利用条件十分简单,只要放一个恶意的DLL就行了。由于实施这种DLL劫持不需要其他先决条件,许多厂商关注并承认该利用场景下的DLL劫持漏洞

许多流行软件可能仍然存在有这种DLL劫持漏洞:笔者在2015年给12月给Adobe报告了Adobe Acrobat DC 15.009.20077中存在的一个DLL劫持漏洞(CVE-2016-0947),该漏洞由Acrobat.exe进程加载不存在的updaternotifications.dll所引起。此外,去CVE漏洞库搜索 DLL Hijacking 或者 Untrusted Search Path 也能找到很多案例。

2.3 针对安装程序的DLL劫持

许多应用程序的安装包程序也存在有DLL劫持漏洞,这种场景与 针对应用程序安装目录的DLL劫持 比较类似,本来也没有什么特殊之处,不过结合后文提到的浏览器自动下载漏洞,其利用条件又变得相对简单了。

这里以Notepad++最新的安装包npp.6.9.Installer.exe为例来进行讲解。启动 ProcMon 并设置好过滤器,可以看到npp.6.9.Installer.exe运行后尝试加载了许多DLL,这些都是第一次加载时没有加载成功的。
Notepad++安装包npp.6.9.Installer.exe尝试加载但未成功加载的DLL列表

仔细观察进程尝试加载这些DLL时产生的调用栈,会发现有的调用栈中存在有 LoadLibrary(Ex),而有的调用栈中却没有。这里选取 Version.dll 和 SHFOLDER.dll 来进行对比说明。

  • npp.6.9.Installer.exe在尝试加载 Version.dll 时产生的调用栈中并没有 LoadLibrary(Ex),这是因为DLL并不是被进程动态加载的,而是因为应用程序的导入表直接或者间接导入了这个DLL。在这种利用场景下,伪造DLL的导出表最好与被伪造DLL的导出表完全一致,否则DLL可能无法被进程成功加载(会弹出错误提示消息框)。有一个叫做 AheadLib 的工具可以十分方便的生成此类DLL的源文件。

    0   fltmgr.sys      FltAcquirePushLockShared +0x9071   fltmgr.sys      FltIsCallbackDataDirty +0x1f3d2   fltmgr.sys      FltDeletePushLock +0x64f3   ntoskrnl.exe    MmCreateSection +0x25b14   ntoskrnl.exe    SeQueryInformationToken +0xe3e5   ntoskrnl.exe    ObOpenObjectByName +0x3066   ntoskrnl.exe    NtOpenProcessTokenEx +0x3267   ntoskrnl.exe    KeSynchronizeExecution +0x3a238   ntdll.dll       ZwQueryAttributesFile +0xa9   wow64.dll       Wow64EmulateAtlThunk +0xd2b110   wow64.dll       Wow64SystemServiceEx +0xd711   wow64cpu.dll    TurboDispatchJumpAddressEnd +0x2d12   wow64.dll       Wow64SystemServiceEx +0x1ce13   wow64.dll       Wow64LdrpInitialize +0x42a14   ntdll.dll       RtlUniform +0x6e615   ntdll.dll       EtwEventSetInformation +0x186f816   ntdll.dll       LdrInitializeThunk +0xe17   ntdll.dll       ZwQueryAttributesFile +0x1218   ntdll.dll       aullrem +0x1f119   ntdll.dll       aullrem +0x6cb20   ntdll.dll       aullrem +0x56521   ntdll.dll       RtlEncodeSystemPointer +0x40422   ntdll.dll       RtlSetBits +0xf023   ntdll.dll       RtlSetBits +0x16b24   ntdll.dll       RtlSetBits +0x6025   ntdll.dll       RtlSetThreadPoolStartFunc +0x3a126   ntdll.dll       RtlSetUnhandledExceptionFilter +0x5027   ntdll.dll       LdrInitializeThunk +0x10
  • npp.6.9.Installer.exe在尝试加载 SHFOLDER.dll 时产生的调用栈中存在有 LoadLibrary(Ex),说明这个DLL是被进程所动态加载的。在这种利用场景下,伪造的DLL文件不需要存在任何导出函数即可被成功加载,即使加载后进程内部出错,也是在DLL被成功加载之后的事情。

    0   fltmgr.sys         FltAcquirePushLockShared +0x9071   fltmgr.sys         FltIsCallbackDataDirty +0x1f3d2   fltmgr.sys         FltDeletePushLock +0x64f3   ntoskrnl.exe       MmCreateSection +0x25b14   ntoskrnl.exe       SeQueryInformationToken +0xe3e5   ntoskrnl.exe       ObOpenObjectByName +0x3066   ntoskrnl.exe       NtOpenProcessTokenEx +0x3267   ntoskrnl.exe       KeSynchronizeExecution +0x3a238   ntdll.dll          ZwQueryAttributesFile +0xa9   wow64.dll          Wow64EmulateAtlThunk +0xd2b110   wow64.dll          Wow64SystemServiceEx +0xd711   wow64cpu.dll       TurboDispatchJumpAddressEnd +0x2d12   wow64.dll          Wow64SystemServiceEx +0x1ce13   wow64.dll          Wow64LdrpInitialize +0x42a14   ntdll.dll          RtlUniform +0x6e615   ntdll.dll          EtwEventSetInformation +0x186f816   ntdll.dll          LdrInitializeThunk +0xe17   ntdll.dll          ZwQueryAttributesFile +0x1218   ntdll.dll          aullrem +0x1f119   ntdll.dll          aullrem +0x6cb20   ntdll.dll          aullrem +0x56521   ntdll.dll          RtlLookupAtomInAtomTable +0x35a22   ntdll.dll          RtlUlonglongByteSwap +0x67123   KernelBase.dll     LoadLibraryExW +0x24324   KernelBase.dll     LoadLibraryExA +0x2625   kernel32.dll       LoadLibraryA +0x31

2.4 Microsoft Edge与Google Chrome的自动下载漏洞

通过 iframe 可以触发 Microsoft Edge 和 Google Chrome 的自动下载功能,这一特性被 @HaifeiLi 认为是一个安全漏洞,其在Twitter上发表了很多关于该漏洞的推文,甚至抱怨Chrome和Edge团队忽视这个漏洞的存在。在HaifefiLi的长期呼吁下,Chrome最终在48.0.2564.82版本中修复了这个漏洞,而截至笔者撰文时Edge似乎仍然没有修复该漏洞。

Edge浏览器的默认下载目录为 C:\Users\Username\Downloads,通过Edge下载的文件默认都会保存在这个目录下。可以利用Edge的自动下载漏洞下载一个恶意的DLL文件(如Version.dll)到这个目录下,然后利用页面超时自动跳转功能让Edge跳转到正常页面来诱导用户下载一个正常的安装文件,当用户运行安装程序时恶意的DLL文件便会被进程加载。

测试浏览器自动下载漏洞的HTML测试代码如下所示:

<html>
    <head>
        <title>Windows Update</title>
    </head>
    <body>
        <iframe src="evil.dll"></iframe>
        <script>
            setTimeout( function () {
                            window.location = "https://get.adobe.com/reader"
                        }, 5000);
        </script>
    </body>
</html>

在Windows 10下使用Edge打开这个HTML页面,可以看到DLL文件被自动下载到了本地的下载目录中。不过由于DLL没有有效的数字签名,所以Edge会提示这个文件可能存在风险。
Windows Edge浏览器自动下载漏洞

如果DLL文件具有有效的数字签名,那么Edge就不会这样提示了。在最新版本的Google Chrome(48.0.2564.116 m)上测试发现,不管DLL是否具有有效的数字签名,DLL文件下载之后都需要用户手工确认才会保存,否则会被删除。Chrome和Edge的测试结果汇总如下:
Chrome和Edge自动下载测试结果汇总

浏览器的自动下载漏洞还是十分危险的,攻击者甚至只需要诱导用户下载一个恶意的DLL,以后用户在下载目录中执行各种程序时都有可能加载这个DLL。此外,安装程序一般都会请求管理员权限,对于恶意的DLL来说管理员权限似乎是与生俱来的。

0×03. 非典型漏洞CVE-2016-0041分析

微软安全公告MS16-014中的描述表明其修复了一个CVE-ID为CVE-2016-0041的DLL劫持漏洞。漏洞详情为:Windows 10下的 URLMON.dll 文件存在加载 phoneinfo.dll 的代码,而Windows 10本身并不携带这个 phoneinfo.dll 文件,并且在查找DLL时使用的是标准的目录搜索顺序,所以这里会导致DLL劫持漏洞。这个漏洞的独特之处在于其存在于操作系统本身,所以在Windows 10下,只要是调用了 URLMON.dll 中能够触发漏洞代码的API的软件都会受到这个漏洞的影响。笔者在2015年底也发现了也发现了这个漏洞,同时确认Foxit Reader 7.2.8.1124受到该漏洞的影响,并将其报告给了Foxit Software。

3.1 漏洞分析

在发现这个漏洞时,笔者发现网上很少有关于 phoneinfo.dll 文件的介绍,只有 @tombkeeperSexrets of LoadLibrary 中提到了这个文件。TK指出 IE11 running on Windows 10 TP 9926 会尝试加载 phoneinfo.dll,而IE的当前目录就是桌面,所以如果放一个 phoneinfo.dll 到桌面上的话,在启动IE时这个DLL便会被加载。

Greg Linares 在 SRT-VR-24DEC2015 中指出 Windows10 的 URLMON.dll 中存在两处加载 phoneinfo.dll 的地方,可能是DLL文件的版本不一样,笔者找到的代码与之存在一些细微差异。笔者在分析 11.0.10240.16384 版本的 URLMON.dll 时找到的反汇编代码如下所示:

  • 下面的代码位于 BuildUserAgentStringMobileHelper 中:


    .text:1A4636A1 loc_1A4636A1:.text:1A4636A1                 moveax, pfnQueryPhoneInformation
    .text:1A4636A6                 mov[ebp+pszValue],0.text:1A4636AD                 mov[ebp+szSrc],eax.text:1A4636B3                 testeax,eax; 判断eax寄存器的值是否为0.text:1A4636B5                 jnz     loc_1A48FC97     ; 如果不为0则跳转.text:1A4636BB                 pusheax; dwFlags = 0.text:1A4636BC                 pusheax; hFile   = 0.text:1A4636BD                 push    offset aPhoneinfo_dll ; "phoneinfo.dll".text:1A4636C2                 callds:__imp__LoadLibraryExW@12; LoadLibraryExW(x,x,x).text:1A4636C8                 testeax,eax.text:1A4636CA                 jnz     loc_1A48FC78
  • 下面的代码位于 _QueryPhoneInformationA 中:


    .text:1A461B93                 movedi, pfnQueryPhoneInformation
    .text:1A461B99                 movbyte ptr [ebx],0.text:1A461B9C                 testedi,edi.text:1A461B9E                 jnz     loc_1A48EE56
    .text:1A461BA4                 pushedi; dwFlags.text:1A461BA5                 pushedi; hFile.text:1A461BA6                 push    offset aPhoneinfo_dll ; "phoneinfo.dll".text:1A461BAB                 callds:__imp__LoadLibraryExW@12; LoadLibraryExW(x,x,x).text:1A461BB1                 testeax,eax.text:1A461BB3                 jnz     loc_1A48EE34

这里加载 phoneinfo.dll 的代码为 LoadLibraryExW(“phoneinfo.dll”, NULL, 0)。因为这里 dwFlags 的值为0,所以使用标准的DLL搜索顺序;由于Windows 10上并不存在 phoneinfo.dll 这个文件,所以进程最终会尝试加载当前目录下的DLL。

这里简单分析一下受该漏洞影响的Foxit Reader。当在Windows 10下打开一个PDF文件时,进程 FoxitReader.exe 会加载当前目录下的 phoneinfo.dll 文件,对应的调用栈如下所示:

......
16   KernelBase.dll     LoadLibraryExW +0x12417   urlmon.dll         Ordinal523 +0x6f118   urlmon.dll         Ordinal492 +0x94119   urlmon.dll         Ordinal492 +0x16520   urlmon.dll         Ordinal445 +0x2e021   urlmon.dll         RegisterFormatEnumerator +0xe222   urlmon.dll         UrlMkGetSessionOption +0xcf23   FoxitReader.exe    CertFreeCertificateChainEngine +0x72fbef24   FoxitReader.exe    CertFreeCertificateChainEngine +0x70bbc225   FoxitReader.exe    CertFreeCertificateChainEngine +0x70f61e26   FoxitReader.exe    CertFreeCertificateChainEngine +0x6f9f9c27   user32.dll         Ordinal2535 +0x8328   user32.dll         GetScrollInfo +0x1e829   user32.dll         DispatchMessageW +0x28d30   user32.dll         DispatchMessageW +0x1031   FoxitReader.exe    FoxitReader.exe+0x2d1f1b32   FoxitReader.exe    FoxitReader.exe+0x2da62d33   FoxitReader.exe    FoxitReader.exe+0x882a3634   FoxitReader.exe    FoxitReader.exe+0x1866d135   FoxitReader.exe    FoxitReader.exe+0x17328636   FoxitReader.exe    FoxitReader.exe+0x17356337   FoxitReader.exe    FoxitReader.exe+0x21483f38   FoxitReader.exe    FoxitReader.exe+0x21772639   FoxitReader.exe    FoxitReader.exe+0x1e492240   FoxitReader.exe    FoxitReader.exe+0x1f4aba41   FoxitReader.exe    FoxitReader.exe+0x1e8d6a42   FoxitReader.exe    FoxitReader.exe+0x1eb56243   FoxitReader.exe    CertFreeCertificateChainEngine +0x91e56c44   FoxitReader.exe    FoxitReader.exe+0x46cd8e45   kernel32.dll       BaseThreadInitThunk +0x2446   ntdll.dll          RtlInitializeCriticalSectionAndSpinCount +0x29e47   ntdll.dll          RtlInitializeCriticalSectionAndSpinCount +0x26d

结合IDA或者Windbg进行分析,可以知道这里的调用路径为:

UrlMkGetSessionOption
└--> GetUserAgentString
     └--> GetUserAgentStringForMode
          └--> InitUserAgentGlobals
               └--> BuildUserAgentStringMobileHelper
                    └-->LoadLibraryExW

即Foxit Reader因为调用了URLMON.dll中的UrlMkGetSessionOption函数,导致其受到DLL劫持漏洞的影响。在IDA中使用交叉引用功能进行回溯,可以找到其他能够触发该漏洞的路径,Greg Linares 给出了另外两个路径:

  • 路径1


    ┌-----------------------------------------------------┐
    │        CINetHttpEdge::SetOptionUserAgent            │
    │          CINetHttp::SetOptionUserAgent              │
    │ CIEBrowserModeFilter::collectCacheEntryInfoCallback │
    └-----------------------------------------------------┘
    └--> MapBrowserEmulationStateToUserAgent (Ordinal 445)
         └--> InitUserAgentGlobals (Ordinal 492)
              └--> BuildUserAgentStringMobileHelper
  • 路径2


    ┌-------------------------------------┐
    │ ObtainUserAgentString (Ordinal 211) │
    │         GetUserAgentString          │
    └-------------------------------------┘
    └--> InitUserAgentGlobals (Ordinal 492)
         └--> BuildUserAgentStringMobileHelper

Greg Linares 同时也指出了他们发现的其他受该漏洞影响的软件:
1. Internet Explorer 没有命令行参数的情况下(例如双击并打开IE);
2. Skype 启动的时候;
3. OneDrive 同步以及更新的时候(无需用户交互);
4. Visual Studio 2015 微软账户更新或者同步的时候;

3.2 补丁分析

更新后的URLMON.dll文件在调用 LoadLibraryEx 加载 phoneinfo.dll 时将 dwFlags 参数值指定为 0×800,即 LOAD_LIBRARY_SEARCH_SYSTEM32,表示只搜索 System32 目录。对应的代码为LoadLibraryExW(L”phoneinfo.dll”, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32),反汇编代码如下:

.text:1A46386B                 push800h; dwFlags.text:1A463870                 pusheax; hFile.text:1A463871                 push    offset aPhoneinfo_dll ; "phoneinfo.dll".text:1A463876                 callds:__imp__LoadLibraryExW@12; LoadLibraryExW(x,x,x)

0×04. DLL劫持漏洞缓解措施

DLL劫持漏洞在未来可能仍然会影响着许多软件或者操作系统组件,亦或是与其他漏洞相结合以衍生出新的攻击方法。尽管目前没有一个完美的方法(No Silver Bullet)可以防止软件受到DLL劫持漏洞的影响,但是开发人员仍然可以采取各种措施来缓解DLL劫持漏洞带来的影响。

4.1 基本缓解措施

1. 在加载DLL时尽量使用DLL的绝对路径;
2. 调用SetDllDirectory(L””)当前目录 从DLL搜索目录中排除;
3. 使用 LoadLibraryEx 加载DLL时,指定 LOAD_LIBRARY_SEARCH_ 系列标志;

此外,进程也可以尝试去验证DLL的合法性,例如是否具有自家的合法数字签名、是否是合法的系统DLL文件等。

4.2 Windows Edge缓解措施

最新版本的Edge提供了一种对抗DLL劫持(注入)的缓解措施:只有拥有微软签名以及WHQL(Windows Hardware Quality Lab)签名的DLL模块才会被Edge加载,而且这套机制是在操作系统内核中实现的。

关于这一缓解措施的细节分析,可以阅读 Paul Rascagneres 的文章 MICROSOFT EDGE BINARY INJECTION MITIGATION OVERVIEW

0×05. Acknowledges

感谢 TK 在行文思路上的建议;同时,在本文的写作过程中参考了以下资料,在此亦表示感谢。

  1. MSDN,Dynamic-Link Library Security

  2. MSDN,Dynamic-Link Library Search Order

  3. Microsoft,安全通报 (2269637)

  4. CWE,CWE-426: Untrusted Search Path

  5. CWE,CWE-427: Uncontrolled Search Path Element

  6. Yonsm,AheadLib 2.2.150 - 自动生成一个特洛伊 DLL 分析代码的工具

  7. HaifeiLi,Watch your Downloads: the risk of the “auto-download” feature on Microsoft Edge and Google Chrome

  8. Microsoft,<a href="" target="_blank" 微软安全公告 MS16-014

  9. tombkeeper,Sexrets of LoadLibrary

  10. Greg Linares,SRT-VR-24DEC2015

  11. Wins0n,CVE-2016-0041 Windows 10 PhoneInfo.dll Hijacking Vulnerability

  12. Microsoft Edge Dev Blog,Protecting Microsoft Edge against binary injection

  13. Paul Rascagneres,MICROSOFT EDGE BINARY INJECTION MITIGATION OVERVIEW

建议继续学习

  1. 什么是DNS劫持和DNS污染? (阅读 6,104)
  2. 你所不知道的 HSTS (阅读 3,164)
  3. 流量劫持 —— 浮层登录框的隐患 (阅读 2,845)
  4. 从dll导出lib (阅读 2,203)
  5. 说说下载劫持那些事儿 (阅读 1,786)