char buffer[6];
/* Pointer to structure to identify the limit and base of IDTR*/
PIdtr_t Idtr=(PIdtr_t)buffer;
IdtEntry OldEntry;
PIdtEntry pIdtEntry;
ULONG count;
PVOID NewHandler,TMP;
DWORD cur,tss_ring0esp;
WORD tr;
void __declspec(naked) callback(PVOID addr,PVOID stack)
{//stack是Ring3的stack,这个玩意map一下就可以搞到手了
//addr是ring3code的开始地址
//注意这个代码不是很稳定...不过可以自己构造ring3的stack和ring3code(就是找个r3的空间插进去不是么~)
_asm enter 256,0
_asm pushfd
_asm pushad
_asm sidt buffer
pIdtEntry = (PIdtEntry)Idtr->Base;
OldEntry = pIdtEntry[HOOKINT]; //#define HOOKINT 0xF0
_asm lea eax,interrupt
_asm mov NewHandler,eax
/*接管中断0xF0,目的是让应用程序能通过使用int 0f0h
指令返回到核心态。
int 0f0h起的作用正是等同于ret
F0陷阱的处理函数恢复内核栈等至“调用”前的状态*/
_asm cli
pIdtEntry[HOOKINT].Dpl = 3;
pIdtEntry[HOOKINT].Type = 0xF;
pIdtEntry[HOOKINT].Present = 1;
pIdtEntry[HOOKINT].OffsetLow = (unsigned short)NewHandler;
pIdtEntry[HOOKINT].OffsetHigh = /
(unsigned short)((unsigned int)NewHandler>>16);
_asm sti
_asm {
str word ptr[tr]
push eax
sgdt [esp-2]
pop eax
movzx ebx,word ptr[tr]
and ebx,0fffffff8h
add eax,ebx
mov ebx,[eax]
and ebx,0ffff0000h
shr ebx,16
mov ecx,[eax+4]
and ecx,0ffh
shl ecx,16
or ebx,ecx
mov ecx,[eax+4]
and ecx,0ff000000h
or ebx,ecx //tss base
mov ebx,[ebx+4]
mov tss_ring0esp,ebx
mov cur,esp
}
count=tss_ring0esp-cur;
TMP=(PVOID)ExAllocatePool( NonPagedPool,count);
if(!TMP) goto exit;
/*上面代码获取当前内核栈的地址与需保存大小
下面代码保存栈内容*/
_asm{
mov ecx,count
mov edi,TMP
mov esi,cur
cld
rep movsb
}
/*模拟返回环境,不用多解释了
iretd我们把它类比于call*/
_asm{
mov eax,3bh
mov fs,ax
mov eax,23h
push eax
mov eax,stack
push eax
pushfd
mov eax,1bh
push eax
mov eax,addr
push eax
iretd
}
/*int 0f0h后返回这里开始执行*/
interrupt:
_asm{
mov eax,30h
mov fs,ax
mov ecx,count
mov esi,TMP
mov edi,cur
cld
rep movsb
mov esp,cur
}
_asm cli
pIdtEntry[HOOKINT] = OldEntry;
_asm sti
exit:
_asm popad
_asm popfd
_asm leave
_asm ret 8
}