经过两天的折腾,终于模拟成功了。在此感谢坛友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,不知道我有没有拼错。。
- 标 题:脱离deviceiocontrol进行ring3 ring0之间的数据交互
- 作 者:wuaiwu
- 时 间:2011-09-18 10:17:34
- 链 接:http://bbs.pediy.com/showthread.php?t=140260