Exploiting Windows Device Drivers
By Piotr Bania <bania.piotr@gmail>
pb.specialised.info
翻译:ayarei <xuewufh@Gmail>
hi.baidu/ayarei
"By the pricking of my thumbs, something wicked this way comes . . ."
- "Macbeth", William Shakespeare.
免责声明
作者对提供的信息或者代码的用途不负有任何责任。作者保留文章著作权。任何公众范围的代码或者文字的电子复制或打印需经过作者同意。
介绍
设备驱动漏洞现在正在增长成为Windows和其他操作系统安全的主要威胁。这是一个相关的新领域,但是很少有公开的技术文档讲述这个方面。据我所知,第一个windows设备驱动攻击是有SEC-LABS小组在Win32 Device Drivers Communication Vulnerabilities白皮书中提到的。这个文章公开了一些有用的驱动溢出技术,并且描绘了未来研究的蓝图。第二个值得一读的文章是Barnaby Jack的文章,叫做“Remote Windows Kernel Exploitation Step into the Ring 0”。由于这方面技术文档的缺乏,我决定共享我自己的研究成果。在这个文章中,我将会介绍我的设备驱动攻击技术,提供一些详细的可用技术的细节,包括完整的攻击代码和用于测试的样例驱动的代码。
读者需要拥有IA-32汇编阅读能力和软件漏洞攻击经验。另外,强烈建议你要去阅读之前提过的两篇白皮书。
实验环境的组建
过程中我使用了我的小型“实验室”:
-一台1G内存的电脑;
-虚拟机软件,比如Vmware;
-windbg或者softice。我在VMware中使用第二种,但是它并不怎么稳定;
-IDA 反汇编器;
-一些软件我会在后面提到。
我在虚拟机和主机之间使用pipe进行远程调试,但是通常其他方式更好一点。如果你想进一步研究驱动的话,这个环境的组建是非常重要的。
特权级和用户态
操作系统可以工作在不同的特权级别中,我们叫做Ring。最特权模式是Ring0,我们叫做内核模式。简单点说就是,如果你有了ring0权限,你就变成了系统中的上帝。内核模式的内存地址从0x80000000到0xFFFFFFFF。
用户态代码(软件)在Ring3模式下运行(它没有访问Ring0模式的权限),并且他不能直接访问操作系统的函数,如果想使用这些函数只能通过call请求他们。这个叫做函数封装。用户模式内存地址是由0x00000000到0x7FFFFFFF。
Windows系统使用了两种权限模式(ring0和ring3)。
Driver loader
在我发布那个简单驱动之前,我们先来简单看下如何加载它。这是实现这个功能的代码:/* wdl.c */
#define UNICODE
#include <stdio.h>
#include <conio.h>
#include <windows.h>
void install_driver(SC_HANDLE sc, wchar_t *name)
{
SC_HANDLE service;
wchar_t path[512];
wchar_t *fp;
if (GetFullPathName(name, 512, path, &fp) == 0)
{
printf("[-] Error: GetFullPathName() failed, error = %d\n",GetLastError());
return;
}
service = CreateService(sc, name, name, SERVICE_ALL_ACCESS, \
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START, \
SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, \
NULL, NULL);
if (service == NULL)
{
printf("[-] Error: CreateService() failed, error %d\n",GetLastError());
return;
}
printf("[+] Creating service - success.\n");
if (StartService(service, 1, (const unsigned short**)&name) == 0)
{
printf("[-] Error: StartService() failed, error %d\n", GetLastError());
if (DeleteService(service) == 0)
printf("[-] Error: DeleteService() failed, error = %d\n", GetLastError());
return;
}
printf("[*] Staring service - success.\n");
CloseServiceHandle(service);
}
void delete_driver(SC_HANDLE sc, wchar_t *name)
{
SC_HANDLE service;
SERVICE_STATUS status;
service = OpenService(sc, name, SERVICE_ALL_ACCESS);
if (service == NULL)
{
printf("[-] Error: OpenService() failed, error = %d\n", GetLastError());
return;
}
printf("[+] Opening service - success.\n");
if (ControlService(service, SERVICE_CONTROL_STOP, &status) == 0)
{
printf("[-] Error: ControlService() failed, error = %d\n",GetLastError());
return;
}
printf("[+] Stopping service - success.\n");
if (DeleteService(service) == 0) {
printf("[-] Error: DeleteService() failed, error = %d\n", GetLastError());
return;
}
printf("[+] Deleting service - success\n");
}
int main(int argc, char *argv[])
{
int m, b;
SC_HANDLE sc;
wchar_t name[MAX_PATH];
createprocessaprintf("[+] Windows driver loader by Piotr Bania\n\n");
if (argc != 3)
{
printf("[!] Usage: (/l | /u) driver.sys\n");
printf("[!] /l - load the driver\n");
printf("[!] /u - unload the driver\n");
getch();
return 0;
}
if (strcmp(argv[1], "/l") == 0)
m = 0;
else
m = 1; // default uninstall mode
sc = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE,
SC_MANAGER_ALL_ACCESS);
if (sc == NULL)
{
printf("[-] Error: OpenSCManager() failed\n");
return 0;
}
b = MultiByteToWideChar(CP_ACP, 0, argv[2], -1, name, MAX_PATH);
if (m == 0)
{
printf("[+] Trying to load: %s\n",argv[2]);
install_driver(sc, name);
}
if (m != 0)
{
printf("[+] Trying to unload: %s\n",argv[2]);
delete_driver(sc, name);
}
getch();
}
/* wdl.c ends */
含漏洞的驱动样本
这是含漏洞驱动的样例代码,我们将会在文章接下来尝试攻击它。这个驱动的基于Iczelion的框架模型。
; buggy.asm start
.386
.MODEL FLAT, STDCALL
OPTION CASEMAP:NONE
INCLUDE D:\masm32\include\windows.inc
INCLUDE inc\string.INC
INCLUDE inc\ntstruc.INC
INCLUDE inc\ntddk.INC
INCLUDE inc\ntoskrnl.INC
INCLUDE inc\NtDll.INC
INCLUDELIB D:\masm32\lib\wdm.lib
INCLUDELIB D:\masm32\lib\ntoskrnl.lib
INCLUDELIB D:\masm32\lib\ntdll.lib
.CONST
pDevObj PDEVICE_OBJECT 0
TEXTW szDevPath, <\Device\BUGGY/0>
TEXTW szSymPath, <\DosDevices\BUGGY/0>
.CODE
assume fs : NOTHING
DriverDispatch proc uses esi edi ebx, pDriverObject, pIrp
mov edi, pIrp
assume edi : PTR _IRP
sub eax, eax
mov [edi].IoStatus.Information, eax
mov [edi].IoStatus.Status, eax
assume edi : NOTHING
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论