xfocus logo xfocus title
首页 焦点原创 安全文摘 安全工具 安全漏洞 焦点项目 焦点论坛 关于我们
添加文章 English Version

NT下所有RING 3进程任意端口I/O


创建时间:2003-03-21
文章属性:原创
文章来源:http://www.whitecell.org
文章提交:sinister (jiasys_at_21cn.com)

NT下所有RING 3进程任意端口I/O

Author  : sinister
Email   : sinister@whitecell.org
HomePage: http://www.whitecell.org  

(首先说明一下,本文所提到的方法并不是我所发明的,我只不过是按照思路实现一下罢了。如果您是 NT KERNEL 的高手,那么还是别看了,免得耽误时间。)

以NT内核为基础的OS出于对安全的考虑,对I/O端口实行了严格限制。即在 RING 3 下所有进程均不许直接进行端口I/O操作。这虽然提高安全性,但也给程序员们带来了不少麻烦。关于 RING 3 下端口I/O 也有过不少讨论。一种方法是利用未公开的内核函数 Ke386SetIoAccessMap,Ke386IoSetAccessProcess,来设置 TSS 中的IOPM。这种方法只能指定某一个 RING 3 进程允许端口I/O。还有就是直接手工设置标志寄存器中的IOPL位与TSS中的IOPM。(INTEL 手册中还提到了如果 CPL = 0的情况下,那么 IOPL 也同样受到影响)。这里介绍了另一种方式,也就是通过直接设置 TSS 的段界限来实现 RING 3 进程任意端口I/O。下面的代码演示了这一过程。错误之处还望各位指正。


/*****************************************************************
文件名        : WssIo.c
描述          : 任意端口读写
作者          : sinister
最后修改日期  : 2002-11-02
*****************************************************************/

#include "ntddk.h"
#include "string.h"

#ifndef DWORD
#define DWORD unsigned int
#endif

#ifndef WORD
#define WORD unsigned short
#endif

#define NOT_BUSY            9
#define DEFAULT_TSS_LIMIT   0x20ab  //缺省的 TSS 段界限
#define NEW_TSS_LIMIT        0x2fab

static NTSTATUS  MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject);

#pragma pack(push,1)


typedef struct tagGDTR{
    WORD    wLimit;
    DWORD   *dwBase;
}GDTR, *PGDTR;

typedef struct tagGDTENTRY{
    DWORD dwLimit : 16;
    DWORD dwBaselo : 16;
    DWORD dwBasemid : 8;
    DWORD dwType : 4;
    DWORD dwSystem : 1;
    DWORD dwDpl : 2;
    DWORD dwPresent : 1;
    DWORD dwLimithi : 4;
    DWORD dwAvailable : 1;
    DWORD dwZero : 1;
    DWORD dwSize : 1;
    DWORD dwGranularity : 1;
    DWORD dwBasehi : 8;
} GDTENTRY, *PGDTENTRY;

#pragma pack(pop)

VOID SetAllPorcIO( int iTrue )
{
    GDTR        gdtr;
    PGDTENTRY    gdt;

    WORD        TSSseg;


    __asm {
        cli                            // 屏蔽中断
        sgdt  gdtr                    // 得到 GDT 基地址与段界限
        str   TSSseg                // 得到 TSS 选择子
        movzx esi,TSSseg            // 扩展到 ESI 中以便计算
        add   esi,gdtr.dwBase       // 得到 TSS 在 GDT 中描述符
        mov   gdt,esi
    }

    if ( iTrue == 1 )
    {
        gdt->dwLimit = NEW_TSS_LIMIT;    // 设置新的 TSS 段界限
    }

    else {
        gdt->dwLimit = DEFAULT_TSS_LIMIT;
    }

    gdt->dwType = NOT_BUSY;            //必须设置为NOTBUSY状态

    __asm {
        ltr TSSseg                // 将设置好的 TSS 重新装入
        sti                        // 开中断
    }


}


// 驱动入口
NTSTATUS  DriverEntry( IN PDRIVER_OBJECT DriverObject,  IN PUNICODE_STRING RegistryPath )
{
    
    UNICODE_STRING  nameString, linkString;
    PDEVICE_OBJECT  deviceObject;
    NTSTATUS        status;
    HANDLE          hHandle;
    int                i;
    

    //卸载驱动
    DriverObject->DriverUnload = DriverUnload;

    //建立设备
    RtlInitUnicodeString( &nameString, L"\\Device\\WssIo" );
    
    status = IoCreateDevice( DriverObject,
                             0,
                             &nameString,
                             FILE_DEVICE_UNKNOWN,
                             0,
                             TRUE,
                             &deviceObject
                           );
                          

    if (!NT_SUCCESS( status ))
        return status;
    

    RtlInitUnicodeString( &linkString, L"\\DosDevices\\WssIo" );

    status = IoCreateSymbolicLink (&linkString, &nameString);

    if (!NT_SUCCESS( status ))
    {
        IoDeleteDevice (DriverObject->DeviceObject);
        return status;
    }    
    
    SetAllPorcIO(1);

    for ( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)    {

          DriverObject->MajorFunction[i] = MydrvDispatch;
    }

      DriverObject->DriverUnload = DriverUnload;
    
  return STATUS_SUCCESS;
}



//处理设备对象操作

static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    Irp->IoStatus.Status = STATUS_SUCCESS;
    Irp->IoStatus.Information = 0L;
    IoCompleteRequest( Irp, 0 );
    return Irp->IoStatus.Status;
    
}



VOID DriverUnload (IN PDRIVER_OBJECT    pDriverObject)
{
    UNICODE_STRING  nameString;

    SetAllPorcIO(0);

    RtlInitUnicodeString( &nameString, L"\\DosDevices\\WssIo" );    
    IoDeleteSymbolicLink(&nameString);
    IoDeleteDevice(pDriverObject->DeviceObject);

    return;
}


应用层测试程序

void main()
{
    int i = 0;
    __asm {
      mov al,0a0h
      mov dx,0388h
      out dx,al
      mov dx,0388h
      in  al,dx
      mov byte ptr i,al
    }

    printf("%d\n",i);
}



关于我们:

WSS(Whitecell Security Systems),一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传统的hacker精神,追求技术的精纯。
WSS 主页:http://www.whitecell.org/