现在的位置: 首页 > 综合 > 正文

获取全局描述符表GDT的内容

2018年02月08日 ⁄ 综合 ⁄ 共 6412字 ⁄ 字号 评论关闭
/stdfx.h文件

//Ring0环的程序

//测试环境VS2005

#ifndef _WIN32_WINNT		// Allow use of features specific to Windows XP or later.                   
#define _WIN32_WINNT 0x0501	// Change this to the appropriate value to target other versions of Windows.
#endif						

#ifdef __cplusplus
extern "C" 
{

#endif

#include <ntddk.h>
#include <ntddstor.h>
#include <mountdev.h>
#include <ntddvol.h>


#ifdef __cplusplus
}
#endif
</pre><pre name="code" class="cpp"><pre name="code" class="cpp">//stdfx.cpp文件

//This file is used to build a precompiled header
#include "stdafx.h"

//GetGDT.cpp文件


#include "stdafx.h"


//SGDT返回的数据格式 
#pragma pack(1)
typedef struct
{
USHORT GDTLimit;     //GDT表的字节大小
ULONG GDTAddress;    //GDT表的基址
}GDTINFO, *PGDTINFO;
#pragma pack()


//驱动的控制码
#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)
#define  MY_BASE 0x800
#define  MY_CTL_CODE(i)    CTL_CODE(FILE_DEVICE_UNKNOWN, MY_BASE + i, METHOD_BUFFERED, FILE_ANY_ACCESS)


//设置控制码IOCTL_GET_GDT
#define  IOCTL_GET_GDT  MY_CTL_CODE(1)


//卸载例程
void GetGDTUnload(IN PDRIVER_OBJECT DriverObject);
//创建关闭例程
NTSTATUS GetGDTCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
//默认处理例程
NTSTATUS GetGDTDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
//驱动控制例程函数的声明
NTSTATUS DispathControlDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);


#ifdef __cplusplus
//驱动入口函数
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath);
#endif




//入口函数
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath)
{
UNICODE_STRING DeviceName,Win32Device;
PDEVICE_OBJECT DeviceObject = NULL;
NTSTATUS status;
ULONG i;


//设置断点
KdBreakPoint();


//设置设备名称
RtlInitUnicodeString(&DeviceName, L"\\Device\\GetGDT0");
//设置设备连接符
RtlInitUnicodeString(&Win32Device, L"\\DosDevices\\GetGDT0");


//填充默认的派遣函数
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
{
DriverObject->MajorFunction[i] = GetGDTDefaultHandler;
}


//设置创建函数
DriverObject->MajorFunction[IRP_MJ_CREATE] = GetGDTCreateClose;
//设置关闭函数
DriverObject->MajorFunction[IRP_MJ_CLOSE] = GetGDTCreateClose;


//设置驱动控制函数
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispathControlDriver;

//设置卸载函数
DriverObject->DriverUnload = GetGDTUnload;
//创建设备对象
status = IoCreateDevice(DriverObject,
0,
&DeviceName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&DeviceObject);
if (!NT_SUCCESS(status))
return status;
if (!DeviceObject)
return STATUS_UNEXPECTED_IO_ERROR;


//直接方式I/O
DeviceObject->Flags |= DO_DIRECT_IO;
//设置文件字对齐
DeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;


//创建符号连接
status = IoCreateSymbolicLink(&Win32Device, &DeviceName);
if (!NT_SUCCESS(status))
return status;


//设备初始化完毕可以工作了
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;


return STATUS_SUCCESS;
}




//卸载例程
void GetGDTUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING Win32Device;
RtlInitUnicodeString(&Win32Device, L"\\DosDevices\\GetGDT0");
//删除连接符
IoDeleteSymbolicLink(&Win32Device);
//删除设备
IoDeleteDevice(DriverObject->DeviceObject);
}


//创建关闭例程
NTSTATUS GetGDTCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}


//默认处理例程
NTSTATUS GetGDTDefaultHandler(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Irp->IoStatus.Status;
}


//驱动的控制例程函数
NTSTATUS DispathControlDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS status               = STATUS_INVALID_DEVICE_REQUEST; 
PIO_STACK_LOCATION pIrpStack  = NULL;
ULONG uIoControlCode          = 0;
PVOID pIoBuffer = NULL;
ULONG uInSize                 = 0;
ULONG uOutSize                = 0;


//设置断点
KdBreakPoint();

//获取当前IRP的堆栈
pIrpStack  = IoGetCurrentIrpStackLocation(Irp);
//获取设备控制例程的控制代码
uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;


//获取IRP的缓冲区
pIoBuffer = Irp->AssociatedIrp.SystemBuffer;
//获取缓冲区的输出长度
uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;


switch(uIoControlCode)
{
//获取GDT表
case IOCTL_GET_GDT:
{
//设置断点
KdBreakPoint();


INT i = 0;
ULONG uLeng = 0;
GDTINFO gdtEntry;
ULONG gdtAddr = 0;


//获取GDTR寄存器的值
__asm sgdt gdtEntry;


//GDTR寄存器值的头两个字节表示的是GDT表的长度,后4个字节表示的是GDT表的地址


//获取GDT表的界限
uLeng = gdtEntry.GDTLimit;
//获取GDT表的基址
gdtAddr = gdtEntry.GDTAddress;

//拷贝GDT表值到输出缓冲区
RtlCopyMemory((CHAR*)pIoBuffer, (CHAR*)gdtAddr, uLeng);


uOutSize = uLeng;


status = STATUS_SUCCESS;
}
break;


}


//设置成功操作的字节数
if(status == STATUS_SUCCESS)
{
Irp->IoStatus.Information = uOutSize;
}
else
{
Irp->IoStatus.Information = 0;
}


//设置I/O状态
Irp->IoStatus.Status = status;
//完成请求
IoCompleteRequest(Irp, IO_NO_INCREMENT);


return status;
}


</pre><pre name="code" class="cpp"><pre name="code" class="cpp">//Ring3环程序的测试环境为VC6.0
//推荐在F5调试环境下测试

//注:在GDT表的解析时,好像出了错?

#include <stdlib.h>
#include <Windows.h>
#include <winioctl.h>

//段的定义-64位
#pragma pack(1)
typedef struct
{
	unsigned int m_Limit1:16;        //段界限低16位
	unsigned int m_BaseAddr1:24;     //段基地址低24位
	unsigned int m_Attributes:12;    //段属性12位
	unsigned int m_Limit2:4;         //段界限高4位
	unsigned int m_BaseAddr2:8;      //段基地址高8位
}SEGMENT, *PSEGMENT;
//段基址32位
//段界限20位
#pragma pack()

//获取段基址
#define MAKESEGADDR(BaseAddr1, BaseAddr2)\
((unsigned long) (((unsigned short) (BaseAddr1)) | ((unsigned long) ((unsigned short) (BaseAddr2))) << 24))
//获取段界限
#define MAKESEGLIMIT(Limit1, Limit2)\
((unsigned long) (((unsigned short) (Limit1)) | ((unsigned long) ((unsigned short) (Limit2))) << 16))

//直接使用<winioctl.h>头文件不使用宏
//驱动控制所需要的宏
//#define METHOD_BUFFERED                 0
//#define FILE_ANY_ACCESS                 0
//#define FILE_DEVICE_UNKNOWN             0x00000022

//驱动的控制码
#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
	((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
)

//0x800之前的数值系统保留
#define  MY_BASE 0x800
#define  MY_CTL_CODE(i)    CTL_CODE(FILE_DEVICE_UNKNOWN, MY_BASE + i, METHOD_BUFFERED, FILE_ANY_ACCESS)

//设置控制码IOCTL_GET_GDT
#define  IOCTL_GET_GDT  MY_CTL_CODE(1)

//连接符
#define WIN32_LINK_NAME      "\\\\.\\GetGDT0" 
  

int main(int argc, char* argv[])
{
	DWORD dwRead = 0;
	BYTE szBuffer[0x1000];
	//清零
	RtlZeroMemory(szBuffer, 0, sizeof(szBuffer));
	
	//打开文件句柄
	HANDLE hFile = CreateFile(WIN32_LINK_NAME, 
		GENERIC_READ | GENERIC_WRITE,
		0, 
		NULL, 
		OPEN_EXISTING, 
		FILE_ATTRIBUTE_NORMAL, 
		NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		printf("CreateFile False!\r\n");
		return 0;
	}
	
	//发送获取GDT表值的请求
	BOOL blRet = DeviceIoControl(hFile, IOCTL_GET_GDT, 
								0, NULL, 
								szBuffer, sizeof(szBuffer), 
								&dwRead, 
								NULL);
	if (blRet == FALSE)
	{
		printf("DeviceIoControl False!\r\n");
		return 0;
	}
	
	DWORD dwSegBaseAddr = 0;
	DWORD dwSegLimit    = 0;
	DWORD dwSegAttribt  = 0;
	PSEGMENT pSegmentEntry = NULL;
	
	for (DWORD i = 0; i < dwRead; i += 8)
	{
		//GDT表的一项
		pSegmentEntry = (PSEGMENT)(szBuffer+i);
		
		//获取段基址-32位
		dwSegBaseAddr = MAKESEGADDR(pSegmentEntry->m_BaseAddr1, pSegmentEntry->m_BaseAddr2);
		//获取段界限-20位
		dwSegLimit    = MAKESEGLIMIT(pSegmentEntry->m_Limit1, pSegmentEntry->m_Limit2);
		//获取段属性-12位
		dwSegAttribt  = pSegmentEntry->m_Attributes;
		
		//显示GDT表项的值
		printf("SegmentBase:%08X, SegmentLimit:%06X, SegmentAtrribute:%04X\r\n", dwSegBaseAddr, dwSegLimit, dwSegAttribt);
		
	}
	
	//暂停
	system("pause");
	
	return 0;
}

抱歉!评论已关闭.