欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

脱离deviceiocontrol进行ring3 ring0之间的数据交互

脱离deviceiocontrol进行ring3 ring0之间的数据交互

经过两天的折腾,终于模拟成功了。在此感谢坛友cvcvxk, 在我提出问题的时候给与我的回答和帮助,嘿嘿。。还有就是偶是小菜,可能你知道这种方法,切莫拍砖。。
  最近玩一个梦幻诛仙的游戏,有幸的google了下它的驱动保护。。网上有人发帖说它利用 int 0x21和int 0x22进行数据交互。。看后很心动,想模拟一下。。于是,操刀实验。。
  思路是:1,利用寄存器在ring3和ring0传递大量数据。想法可行,可操作太难,我想到的是难点是同步问题。中断进入内核貌似只会将错误码,eflags,cs,eip压栈,其他的很多寄存器,我们都可以使用,最起码的8个基本寄存器。用户层可以把它们pushad压栈,在中断结束操作完中断返回的数据再popad。
  思路2:利用共享物理内存和寄存器传递数据。这种方法我测试成功了,嘿嘿。在这种方法中,寄存器只是负责传递少量数据,在这我传递的是物理内存在用户空间的映射基址。
   首先,添加中断。。我添加的是0x24号中断
     IDTINFO m_idt = {0};   //IDTINFO是定义的一个保存中断寄存器的结构体
  __asm sidt m_idt;
  ULONG ulBase = m_idt.LowIDTbase;
  ulBase += (ULONG)(m_idt.HiIDTbase<<16);
  KdPrint(("idt的基地址x%x\n",ulBase));
    InterruptGate_t *idtentry = (InterruptGate_t *)ulBase; //InterruptGate_t保存的是中断项指针
     
__asm
  {
    cli
      push eax
      mov eax,cr0
      and eax,not 0x10000
      mov cr0,eax
      pop eax
  }
    idtentry[0x24].Dpl = 3;
    idtentry[0x24].OffsetHigh = (USHORT)((ULONG)bingle>>16);
    idtentry[0x24].OffsetLow = (USHORT)bingle;
    idtentry[0x24].Present = 1;
    idtentry[0x24].Reserved = 0;
    idtentry[0x24].SegmentType = 0xe;
         idtentry[0x24].Selector = 0x8;
         idtentry[0x24].SystemSegmentFlag = 0;
    __asm
    {
       push eax
         mov eax,cr0
         or eax,0x10000
         mov cr0,eax
         pop eax
         sti
    }  
      然后,中断历程函数比较纠结,我还没有摸透它为什么调用kdprint的时候有时会出错(ring3不能正常收数据)。可能还有很多限制,有研究过的可以告诉我。呵呵。。下边是Cvcvxk的框架,我只是修改了一个寄存器eax。这里有我纠结的问题,本来8个普通寄存器使用应该没问题的。可是有时候会出错。我没法摸透为什么。。
      ULONG ulBuf ;  //缓存的一个堆栈空间,没有初始化为0是因为在裸函数中
   __asm
   {
        pushad
      pushfd
      push ds
      push es
      push fs
      push eax
      mov eax, 0x23
      mov ds, ax
      mov es, ax
      mov eax, 0x30
      mov fs, ax
      pop eax
      
         call MapUserSpace  //MapUserSpace是用来映射的函数。。
      mov ulBuf,eax
      pop fs
      pop es
      pop ds
      popfd
      popad
      mov eax,ulBuf
      Iretd  //貌似中断返回就是iretd 不是sysexit呀  呵呵
   }
 接下来就是想法作映射了。我在ring0空间开辟了一页大小的空间。利用它来缓存交互的数据。
#pragma code_seg("PAGE")
__declspec(naked) VOID MapUserSpace()
{
  PVOID pBuf;
  pBuf = ExAllocatePool(NonPagedPool,0x1000);
  PMDL pMdl;
  pMdl = IoAllocateMdl(pBuf,0x1000,FALSE,FALSE,NULL);
  memset(pBuf,0xAA,100); //我把分配的空间数据初始化为0xAA,为了完成测试,ring3下可读出
  if(!pMdl) ExFreePool(pBuf);
  MmBuildMdlForNonPagedPool(pMdl);
  ULONG ulUserBase;
  ulUserBase =    (ULONG)MmMapLockedPagesSpecifyCache(pMdl,UserMode,MmCached,NULL,FALSE,NormalPagePriority);
  
  //KdPrint(("用户空间的基地址:x%x\n",ulUserBase));
    有这个打印函数会出错,不知道为什么。非得把这个打印函数单独放在一个自定义函数中调用,然后才ok。。。至此还是困惑
  __asm mov eax,ulUserBase
   __asm ret 
 }
接下来就是收尾工作,清理ExallocatePool分配的空间。。
在我测试中,ring3只负责接受映射后的基地址,然后从基地址读取数据。。
     LoadLibrary("user32.dll");//控制台程序
  DWORD dwBingle = 0;
  __asm int 0x24;
  
  __asm mov dwBingle,eax
  printf("Ox%x",dwBingle);
  printf("0x%x\n",*(BYTE *)dwBingle);//把0xaa读取出来了。
欠缺:我还没有进行ring3写入,ring0读取的测试。还没有搞明白为什么使用了打印函数会出错的问题。还没有透彻的理解假如直接在中断历程中使用8个寄存器会不会出错的问题。。。。。晚上回来继续研究,女友等我一块看书呢,嘿嘿!

最后再次感谢Cvcvxk,不知道我有没有拼错。。

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功