关于本站
管理团队
  
胡杨林-吉林IT·互动主题区  [登录] [注册] [发表新文章]  

作者: wanglihui 收藏:1 回复:1 点击:4922 发表时间: 2003.06.29 03:17:46

藏该文章 返回《程序、脚本(普通用户论坛)》 快速返回 [转载]


   收
  核心成员
  
  积分:3359
  贴数:2093
  经验:1
   日期:2003-6-25 20:11:51
  --------------------------------------------------------------------------------
  
  任意用户模式下执行 ring 0 代码
  
  Author : sinister
  Email : sinister@whitecell.org
  HomePage: http://www.whitecell.org
  
  
   众所周知在非 Admin 用户模式下,是不允许加载驱动执行 RING 0 代码的。
  本文提供了一种方法,通过修改系统 GDT,IDT 来添加自己的 CALLGATE 和
  INTGATE 这样便在系统中设置了一个后门。我们就可以利用这个后门
  在任意用户模式下执行 ring 0 代码了。为了保证我们添加的 CALLGATE 和 INT
  GATE 永久性。可以在第一次安装时利用 SERVICE API 或 INF 文件设置成随
  系统启动。不过此方法也有个缺陷,就是在第一次安装 CALLGATE 或 INTGATE
  时仍然需要 ADMIN 权限。下面分别给出了添加 CALLGATE 与 INTGATE 的具体
  代码。
  
  
   一、通过添加调用门实现
  
   为了可以让任意用户来调用我们的 CALLGATE 需要解决一个小问题。因为
  需要知道 CALLGATE 的 SELECTOR 后才可以调用。而在 RING 3 下除了能
  得到 GDT 的 BASE ADDRESS 和 LIMIT 外是无法访问 GDT 内容的。我本想
  在 RING 0 把 SELECTOR 保存到文件里。在 RING 3 下读取出来再调用。
  后经过跟 wowocock 探讨。他提出的思路是在 RING 0 下通过
  ZwQuerySystemInformation 得到 NTDLL.DLL 的 MODULE BASE 然后根据
  PE HEADER 中的空闲处存放 SELECTOR。这样在 RING 3 的任意用户模式下
  就很容易得到了。在这里要特别感谢 wowocock。下面的代码为了演示
  方便,用了在我机器上 GDT 中第一个空闲描述符的 SELECTOR 。
  
  
  驱动程序:
  
  /*****************************************************************
  文件名 : WssAddCallGate.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 LOWORD(l) ((unsigned short)(unsigned int)(l))
  #define HIWORD(l) ((unsigned short)((((unsigned int)(l)) >> 16) & 0xFFFF))
  
  
  typedef unsigned long ULONG;
  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 tagGDT_DESCRIPTOR{
   unsigned limit : 16;
   unsigned baselo : 16;
   unsigned basemid : 8;
   unsigned type : 4;
   unsigned system : 1;
   unsigned dpl : 2;
   unsigned present : 1;
   unsigned limithi : 4;
   unsigned available : 1;
   unsigned zero : 1;
   unsigned size : 1;
   unsigned granularity : 1;
   unsigned basehi : 8;
  }GDT_DESCRIPTOR, *PGDT_DESCRIPTOR;
  
  typedef struct tagCALLGATE_DESCRIPTOR{
   unsigned short offset_0_15;
   unsigned short selector;
   unsigned char param_count : 4;
   unsigned char some_bits : 4;
   unsigned char type : 4;
   unsigned char app_system : 1;
   unsigned char dpl : 2;
   unsigned char present : 1;
   unsigned short offset_16_31;
  } CALLGATE_DESCRIPTOR, *PCALLGATE_DESCRIPTOR;
  
  #pragma pack(pop)
  
  void __declspec(naked) Ring0Call()
  {
   PHYSICAL_ADDRESS PhyAdd;
  
   __asm {
   pushad
   pushfd
   cli
   }
  
   DbgPrint("WSS - My CallGate n");
  
   //
   // 这里可以添加你想要执行的 ring 0 代码。
   //
  
   __asm {
   popfd
   popad
   retf
   }
  }
  
  VOID AddCallGate( ULONG FuncAddr )
  {
   GDTR gdtr;
   PGDT_DESCRIPTOR gdt;
   PCALLGATE_DESCRIPTOR callgate;
   WORD wGDTIndex = 1;
  
  
   __asm {
   sgdt gdtr // 得到 GDT 基地址与界限
   }
  
   gdt = (PGDT_DESCRIPTOR) ( gdtr.dwBase + 8 ); // 跳过空选择子
  
   while ( wGDTIndex present == 0 ) //从 GDT 中找到空描述符
   {
   callgate = (PCALLGATE_DESCRIPTOR)gdt;
  
   callgate->offset_0_15 = LOWORD(FuncAddr);
   callgate->selector = 8; // 内核段选择子
   callgate->param_count = 0; // 参数复制数量
   callgate->some_bits = 0;
   callgate->type = 0xC; // 386调用门
   callgate->app_system = 0; // 系统描述符
   callgate->dpl = 3; // RING 3 可调用
   callgate->present = 1; // 设置存在位
   callgate->offset_16_31 = HIWORD(FuncAddr);
   DbgPrint("Add CallGaten");
  
   return;
   }
  
   gdt ++;
   wGDTIndex ++;
   }
  
  }
  
  
  // 驱动入口
  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\WssAddCallGate" );
  
   status = IoCreateDevice( DriverObject,
   0,
   &nameString,
   FILE_DEVICE_UNKNOWN,
   0,
   TRUE,
   &deviceObject
   );
  
  
   if (!NT_SUCCESS( status ))
   return status;
  
  
   RtlInitUnicodeString( &linkString, L"\DosDevices\WssAddCallGate" );
  
   status = IoCreateSymbolicLink (&linkString, &nameString);
  
   if (!NT_SUCCESS( status ))
   {
   IoDeleteDevice (DriverObject->DeviceObject);
   return status;
   }
  
   AddCallGate((ULONG)Ring0Call);
  
   for ( i = 0; i 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;
  
   RtlInitUnicodeString( &nameString, L"\DosDevices\WssAddCallGate" );
   IoDeleteSymbolicLink(&nameString);
   IoDeleteDevice(pDriverObject->DeviceObject);
  
   return;
  }
  
  
  应用程序:
  
  #include
  #include
  
  void main()
  {
   WORD farcall[3];
  
   farcall[0] = 0x0;
   farcall[1] = 0x0;
   farcall[2] = 0x4b; //在我机器上,添加 CALLGATE 的选择子为 4BH
  
   _asm call fword ptr [farcall]
  
  
  }
  
  
   二、通过添加中断门实现
  
   添加中断门没有什么需要解决的问题。直接在 RING 3 利用 int x
  即可切换。想想系统调用 INT 2E 就很容易理解了。
  
  
  /*****************************************************************
  文件名 : WssMyInt.c
  描述 : 添加中断门
  作者 : sinister
  最后修改日期 : 2002-11-02
  *****************************************************************/
  
  #include "ntddk.h"
  
  #pragma pack(1)
  
  
  typedef struct tagIDTR {
   short Limit;
   unsigned int Base;
  }IDTR, *PIDTR;
  
  
  typedef struct tagIDTENTRY {
   unsigned short OffsetLow;
   unsigned short Selector;
   unsigned char Reserved;
   unsigned char Type:4;
   unsigned char Always0:1;
   unsigned char Dpl:2;
   unsigned char Present:1;
   unsigned short OffsetHigh;
  } IDTENTRY, *PIDTENTRY;
  
  #pragma pack()
  
  #define MYINT 0x76
  
  extern VOID _cdecl MyIntFunc();
  CHAR IDTBuffer[6];
  
  IDTENTRY OldIdt;
  PIDTR idtr = (PIDTR)IDTBuffer;
  
  
  static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
  VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject);
  
  // 我们得中断处理函数
  
  VOID _cdecl MyIntFunc()
  {
   PHYSICAL_ADDRESS PhyAdd;
   unsigned int dwCallNum;
   unsigned int dwVAddr;
  
   _asm mov dwCallNum,eax
  
   //
   // 这里可以添加你想要执行的 ring 0 代码
   //
  
   switch ( dwCallNum )
   {
   case 0x01:
   DbgPrint("MyIntGate eax = 0x01n");
   break;
  
   case 0x02:
   DbgPrint("MyIntGate eax = 0x02n");
   break;
  
   default:break;
  
   }
  
  
   _asm iretd; //中断返回
  }
  
  NTSTATUS AddMyInt()
  {
   PIDTENTRY Idt;
  
   //得到 IDTR 中得段界限与基地址
   _asm sidt IDTBuffer
  
   Idt = (PIDTENTRY)idtr->Base; //得到IDT表基地址
  
   //保存原有得 IDT
   RtlCopyMemory(&OldIdt, &Idt[MYINT], sizeof(OldIdt));
  
  
   //禁止中断
   _asm cli
  
   //设置 IDT 表各项添加我们得中断
  
   Idt[MYINT].OffsetLow = (unsigned short)MyIntFunc; //取中断处理函数低16位
   Idt[MYINT].Selector = 8; //设置内核段选择子
   Idt[MYINT].Reserved = 0; //系统保留
   Idt[MYINT].Type = 0xE; //设置0xE表示是中断门
   Idt[MYINT].Always0 = 0; //系统保留必须为0
   Idt[MYINT].Dpl = 3; //描述符权限,设置为允许 RING 3 进程调用
   Idt[MYINT].Present = 1; //存在位设置为1表示有效
   Idt[MYINT].OffsetHigh = (unsigned short)((unsigned int)MyIntFunc>>16); //取中断处理函数高16位
  
   //开中断
   _asm sti
  
   return STATUS_SUCCESS;
  }
  
  
  //删除中断
  
  void RemoveMyInt()
  {
   PIDTENTRY Idt;
   Idt = (PIDTENTRY)idtr->Base;
  
   _asm cli
   //恢复 IDT
   RtlCopyMemory(&Idt[MYINT], &OldIdt, sizeof(OldIdt));
   _asm sti
  }
  
  
  
  // 驱动入口
  NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath )
  {
  
   UNICODE_STRING nameString, linkString;
   //UNICODE_STRING deviceString;
   PDEVICE_OBJECT deviceObject;
   NTSTATUS status;
   WCHAR wBuffer[200];
  
   nameString.Buffer = wBuffer;
   nameString.MaximumLength = 200;
  
  
   //卸载驱动
   DriverObject->DriverUnload = DriverUnload;
  
   //建立设备
   RtlInitUnicodeString( &nameString, L"\Device\WSSINT" );
  
   status = IoCreateDevice( DriverObject,
   0,
   &nameString,
   FILE_DEVICE_UNKNOWN,
   0,
   TRUE,
   &deviceObject
   );
  
  
   if (!NT_SUCCESS( status ))
   return status;
  
   RtlInitUnicodeString( &linkString, L"\??\WSSINT" );
  
   //使WIN32应用程序可见
   status = IoCreateSymbolicLink (&linkString, &nameString);
  
   if (!NT_SUCCESS( status ))
   {
   IoDeleteDevice (DriverObject->DeviceObject);
   return status;
   }
  
   AddMyInt();
  
   DriverObject->MajorFunction[IRP_MJ_CREATE] = MydrvDispatch;
   DriverObject->MajorFunction[IRP_MJ_CLOSE] = MydrvDispatch;
  
   return STATUS_SUCCESS;
  }
  
  
  static NTSTATUS MydrvDispatch (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  {
   NTSTATUS status;
  
   UNREFERENCED_PARAMETER( DeviceObject );
  
   Irp->IoStatus.Status = STATUS_SUCCESS;
   Irp->IoStatus.Information = 0L;
   status = STATUS_SUCCESS;
  
   IoCompleteRequest( Irp, 0 );
   return status;
  
  }
  
  
  
  VOID DriverUnload (IN PDRIVER_OBJECT pDriverObject)
  {
   UNICODE_STRING nameString;
   UNICODE_STRING deviceString,driveString;
   NTSTATUS ntStatus;
  
   RemoveMyInt();
  
   //删除WIN32可见
   IoDeleteSymbolicLink(&nameString);
   //删除设备
   IoDeleteDevice(pDriverObject->DeviceObject);
  
   return;
  }
  
  
  关于我们:
  
  WSS(Whitecell Security Systems),一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传统的hacker精神,追求技术的精纯。
  WSS 主页:http://www.whitecell.org/
  
  返回《程序、脚本(普通用户论坛)》 快速返回
  
  
  
  我 火云邪神 也来说一说!
  
  表情
  
  
  
  
  文章内容
  普通方式
  图形方式
  
  
  
  

------------------------
让我成为你的好友

转载    收   藏  

回帖


回复人: 狼儿 Re:藏该文章 回复时间: 2003.06.29 10:40

    好东西,我收了。
  回去好好读读。
  :)

回    复    

回复人: 飞天宝宝 Re:藏该文章 回复时间: 2003.06.30 14:58

    写的好~~~~~~~~:)

------------------------
鱼说,你看不到我眼中的泪,因为我在水中。
水说,我却能感觉到你的泪,因为你在我心。

本人留言簿:http://www.ihua.net/guestbook/index.asp?user=ftbaobao

回    复    

回复人: 飞天宝宝 Re:藏该文章 回复时间: 2003.06.30 14:58

    写的好~~~~~~~~:)

------------------------
鱼说,你看不到我眼中的泪,因为我在水中。
水说,我却能感觉到你的泪,因为你在我心。

本人留言簿:http://www.ihua.net/guestbook/index.asp?user=ftbaobao

回    复    

回复


回复主题: 回复在论坛 回复到信箱
回复内容:
附加签名:
上传贴图:
图片要求:长宽建议不超过:650×650。大小:300K 以内,文件后缀名必须为:.gif 或.jpg 或.png
      
版主推荐:
编辑推荐:
作者其它文章:

Copyright 2002-2008 版权所有
胡杨林© All rights reserved.
服务支持拓商网