阅读:3030回复:5
看wowocock的技术文章
总结进入RING0的方法
by wowocock1/CVC.GB 关于进入RING0层的方法,大家一定听说过不少,我在复习保护模式编程中将一些进RING0 的方法;总结了一下,包括调用门,任务门,中断门,陷阱门等,这些方法都是直接利用 IA32的方法,所以和操作系统应该没有多大关系,当然由于NT内核对GDT,IDT,的保护所 以我们不能用这些方法,不过如果一旦突破了NT的保护,那么所有的方法就都可以使用了, 其他的还有SEH等方法,我在前面的文章中也有介绍。 -----------------Code--- ;======================================== ; WOWOCOCK 编写 ; ;======================================== .586p .model flat, stdcall option casemap :none ; case sensitive include \\masm32\\include\\windows.inc include \\masm32\\include\\kernel32.inc include \\masm32\\include\\user32.inc includelib \\masm32\\lib\\kernel32.lib includelib \\masm32\\lib\\user32.lib ;;-------------- TSS STRUC TRLink dw 0 ;链接字段 dw 0 ;不使用,置为0 TRESP0 dd 0 ;0级堆栈指针 TRSS0 dw 0 ;0级堆栈段寄存器 dw 0 ;不使用,置为0 TRESP1 dd 0 ;1级堆栈指针 TRSS1 dw 0 ;1级堆栈段寄存器 dw 0 ;不使用,置为0 TRESP2 dd 0 ;2级堆栈指针 TRSS2 dw 0 ;2级堆栈段寄存器 dw 0 ;不使用,置为0 TRCR3 dd 0 ;CR3 TREIP dd 0 ;EIP TREFlag dd 0 ;EFLAGS TREAX dd 0 ;eax TRECX dd 0 ;ecx TREDX dd 0 ;edx TREBX dd 0 ;ebx TRESP dd 0 ;esp TREBP dd 0 ;ebp TRESI dd 0 ;esi TREDI dd 0 ;edi TRES dw 0 ;ES dw 0 ;不使用,置为0 TRCS dw 0 ;CS dw 0 ;不使用,置为0 TRSS dw 0 ;ss dw 0 ;不使用,置为0 TRDS dw 0 ;DS dw 0 ;不使用,置为0 TRFS dw 0 ;FS dw 0 ;不使用,置为0 TRGS dw 0 ;GS dw 0 ;不使用,置为0 TRLDTR dw 0 ;LDTR dw 0 ;不使用,置为0 TRTrip dw 0 ;调试陷阱标志(只用位0) TRIOMap dw $+2 ;指向I/O许可位图区的段内偏移 TSS ENDS .data sztit db \"Gate Test\",0 CTEXTCall db \"call gate to Ring0!继续?\",0 CTEXTInt db \"int gate to Ring0 By int 5 !继续?\",0 CTEXTIntx db \"int gate to Ring0 By int X !继续?\",0 CTEXTTrap db \"Trap gate to Ring0 By int 1!继续?\",0 CTEXTFault db \"Fault gate to Ring0!继续?\",0 CTEXTTask db \"Task gate to Ring0!继续?\",0 temp1 db \"Cr3的内容是:%8X\",0 temp2 db 100 dup(?) Freq db 08h ;发声频率 gdtR df 0 idtR df 0 ldtR dw 0 trR dw 0 ;the contents of GDTR,IDTR,LDTR,TR ldtDes dw 0 dw 0 ;LDT Limit dd 0 ;LDT Base Callgt dq 0 ;call gate\'s sel:off TrDes dw 0 dw 0 ;TR Limit dd 0 ;TR Base Tss1Sel dw ? ;TSS Call32 dd 0 Tss1Gate dw ? ;任务门 TSS1 TSS <> Tss1Limit equ $-TSS1 TSS2 TSS <> TestCR3 dd 4 MyCall MACRO Selector,Offsetv db 09ah dd Offsetv dw Selector ENDM ;;----------------------------------------- .code __Start: sgdt fword ptr gdtR sidt fword ptr idtR sldt word ptr ldtR str word ptr trR ;save them for later use ;----------------------- ; get the ldt mes ;----------------------- movzx esi,ldtR add esi,dword ptr [gdtR+2] ;esi->ldt descriptor mov ax,word ptr [esi] mov word ptr [ldtDes],ax mov ax,word ptr [esi+6] and ax,0fh mov word ptr [ldtDes+2],ax ;get ldt Limit mov eax,[esi+2] and eax,0ffffffh mov ebx,[esi+4] and ebx,0ff000000h or eax,ebx mov dword ptr [ldtDes+4],eax ;get ldt Base ;----------------------- ; get the tr mes ;----------------------- movzx esi,trR add esi,dword ptr [gdtR+2] mov ax,word ptr [esi] mov word ptr [TrDes],ax mov ax,word ptr [esi+6] and ax,0fh mov word ptr [TrDes+2],ax ;get tr Limit mov eax,[esi+2] and eax,0ffffffh mov ebx,[esi+4] and ebx,0ff000000h or eax,ebx mov dword ptr [TrDes+4],eax;get tr Base ;------------------------------------- ; 这里演示在GDT中寻找空白表项来制造调用门 ;------------------------------------- mov esi,dword ptr [gdtR+2] ;esi->gdt base movzx eax,word ptr [gdtR] ;eax=gdt limit call Search_XDT ;esi==gdt Base mov esi,dword ptr [gdtR+2] push offset myring0_prc_callgt ;set callgate in gdt pop word ptr [esi+eax+0] pop word ptr [esi+eax+6] ;offset mov word ptr [esi+eax+2],28h mov word ptr [esi+eax+4],0EC00h ;sel=28h,dpl=3,and attribute ->386 call gate! and dword ptr Callgt,0 or al,3h mov word ptr [Callgt+4],ax call fword ptr [Callgt] ;use callgate to Ring0! ;-------------------------------------------- ; 这里演示在Ldt中制造调用门 ;-------------------------------------------- invoke MessageBoxA,0, addr CTEXTCall,addr sztit,MB_YESNO cmp eax,IDNO jz @xit000 ;继续演示? mov esi,dword ptr [ldtDes+4] ;esi->ldt base mov eax,dword ptr [ldtDes] ;eax=ldt limit call Search_XDT ;eax返回找到的空白选择子 mov esi,dword ptr [ldtDes+4] push offset myring0_prc_callgt ;set callgate in ldt pop word ptr [esi+eax+0] pop word ptr [esi+eax+6] ;offset mov word ptr [esi+eax+2],28h mov word ptr [esi+eax+4],0EC00h ;sel=28h,dpl=3,and attribute ->386 call gate! and dword ptr Callgt,0 or al,7h ;所以选择子一定要指向LDT mov word ptr [Callgt+4],ax call fword ptr [Callgt] ;use callgate to Ring0! ; *通过中断门进入ring0,像在Dos下一样,我们只要替换中断向量表的地址以指向我们 ; *自己的程序就可以了,不过在win下中断向量表变为IDT(中断描述符表),其第0~1保存 ; *中断处理程序偏移的低16位,6~7字节保存偏移的高16位,我们必须使用描述符具有DPL=3 ; *的中断门以便在ring3下转入中断程序,而int 03h,04h,05h,10h,13h,30h等本来就是 ; *DPL=3,我们可以方便地利用之,注意中断处理程序返回用iretd ;--------------------------- ; 下面利用int 5进入ring0 ;--------------------------- invoke MessageBoxA,0,addr CTEXTInt,addr sztit,MB_YESNO cmp eax,IDNO jz @xit000 ;继续演示? mov esi,dword ptr [idtR+2] ;esi->idt base push dword ptr [esi+8*5+0] push dword ptr [esi+8*5+4] ;保存INT 5,中断描述符 push offset myring0_prc_Intgt ;替换原来INT5的入口地址 pop word ptr [esi+8*5] pop word ptr [esi+8*5+6] int 5 ;进入ring0! ;int 3 ;//可选择利用int 3 ;db 0CCh ;//则保存和恢复就改为8*3 ;为了增强反跟踪效果 ;当然也可以利用int 1,方法一致不过可能在某些处理器上冲突 pop dword ptr [esi+8*5+4] ;恢复,int 5,中断描述符 pop dword ptr [esi+8*5+0] ; *当然,上面使用的全部是DPL=3的int如1,3,5等,如果我们准备使用任意int 来达到 ; *目的该怎么办?这就需要自己改int descriptor 的属性值,使DPL=3,sel=28h ; *如下面使用int 255 ; *__________________________________________ invoke MessageBoxA,0,addr CTEXTIntx,addr sztit,MB_YESNO cmp eax,IDNO jz @xit000 ;继续演示? movzx ebx,word ptr [idtR] ;ebx=idt limit sub ebx,7 push dword ptr [esi+ebx+0] ; save IDT entry push dword ptr [esi+ebx+4] push offset myring0_prc_Intgt pop word ptr [esi+ebx+0] mov word ptr [esi+ebx+2],28h ;ring0 Sel mov word ptr [esi+ebx+4],0EE00h ;P=1,386中断门,DPL=3 pop word ptr [esi+ebx+6] ;mov eax,ebx ;shl eax,5 ;add eax,90C300CDh ;push eax ;call ss:esp ; 在堆栈中形成指令 int 5Fh ret直接转入执行! int 5fh ;pop eax ; int调用,酷吧! pop dword ptr [esi+ebx+4]; 恢复 pop dword ptr [esi+ebx+0] ; * ; *还有其他的方法进入ring0,如陷阱门,与中断门基本一致,只不过是让硬件自己产生中断 ; *我们则自己置TF=1引发之,注意在中断处理中关闭TF,否则会造成死循环,不断单步,还有故, ; *障门产生故障之后注意cs:eip已经压入堆栈,如果不改指令的话,就得自己修改eip指向安全 ; *地址故障门的好处在于不必自己置sel为28h,也不必担心DPL=0,操作系统为我们准备好了一 ; *切我们只要替换int处理地址就行了,以下是简单例子 ; *__________________________________________ invoke MessageBoxA,0,addr CTEXTTrap,addr sztit,MB_YESNO cmp eax,IDNO jz @xit001 ;继续演示? ;--------------------------------- ; int1 单步陷阱或者int4 除法溢出陷阱 ; 这里演示int 1,int 4类似 ; 这个和上面的有不同吗,有!就是int 1 ; 是由CPU而不是我们显式用int 1指令引发 ;--------------------------------- push dword ptr [esi+(8*1)+0] ; 保存原int 1 push dword ptr [esi+(8*1)+4] push offset myring0_prc_Trapgt pop word ptr [esi+(8*1)+0] pop word ptr [esi+(8*1)+6] pushfd pop eax or ah,1 push eax popfd ; set TF=1 nop ; ring0! pop dword ptr [esi+(8*1)+4]; restore IDT entry pop dword ptr [esi+(8*1)+0] ;-------------------------------------------- ; 这里演示故障门,除法错误 ;-------------------------------------------- @xit001:invoke MessageBoxA,0,addr CTEXTFault,addr sztit,MB_YESNO cmp eax,IDNO jz @xit000 ;继续演示? push dword ptr [esi+(8*0)+0] ; push dword ptr [esi+(8*0)+4] push offset Ring0Code_div pop word ptr [esi+(8*0)+0] pop word ptr [esi+(8*0)+6] xor eax,eax div eax ; 除法错误,进入故障门ring0! ;----------------------------------------- invoke MessageBoxA,0,addr CTEXTTask,addr sztit,MB_YESNO cmp eax,IDNO jz @xit000 ;------------------------------------- ; 这里演示在GDT中寻找空白表项来制造TSS ;------------------------------------- mov esi,dword ptr [gdtR+2] movzx eax,word ptr [gdtR] call Search_XDT and ax,0fff8h mov Tss1Sel,ax ;save Tss1 selector ,esi==gdt Base mov esi,dword ptr [gdtR+2] mov ebx,offset TSS1 mov word ptr [esi+eax+0],Tss1Limit mov dword ptr [esi+eax+2],ebx ;offset mov word ptr [esi+eax+5],89h shr ebx,24 mov byte ptr [esi+eax+7],bl ;set mytss ;-------------------------------------------- ; 这里演示在Ldt中制造任务门 ;-------------------------------------------- mov esi,dword ptr [ldtDes+4] mov eax,dword ptr [ldtDes] call Search_XDT ;eax返回找到的空白选择子 push eax or ax,7h mov Tss1Gate,ax pop eax mov esi,dword ptr [ldtDes+4] mov word ptr [esi+eax+0],0 mov word ptr [esi+eax+6],0 ;offset push word ptr Tss1Sel pop word ptr [esi+eax+2] mov word ptr [esi+eax+4],0E500h ;Tss Gate mov esi,dword ptr [TrDes+4] assume esi:ptr TSS push word ptr ldtR pop word ptr[esi].TRLDTR ;设置LDT SELECTOR(WINDOWS98的TSS中LDT 为0???) lea edi,TSS1 assume edi:ptr TSS push word ptr trR pop word ptr [edi].TRLink ;返回TSS选择子,设置联接字 push dword ptr[esi].TRESP0 ;设置SP0 pop dword ptr[edi].TRESP0 push word ptr[esi].TRSS0 ;设置SS0 pop word ptr[edi].TRSS0 push dword ptr[esi].TRCR3 ;设置CR3寄存器,即设置好转换以后所有的段及页转换相关寄存器 pop dword ptr[edi].TRCR3 push offset Ring0 pop dword ptr[edi].TREIP mov word ptr[edi].TRCS,28h ;CS=28 mov word ptr[edi].TRSS,30h ;ss=30 push word ptr ldtR ;设置LDTR pop word ptr[edi].TRLDTR push ds pop dword ptr[edi].TRDS mov word ptr[edi+54h+2],0 call fword ptr Call32 mov ebx,dword ptr [TestCR3] @xit000: invoke wsprintf,addr temp2,addr temp1,TestCR3 invoke MessageBoxA,0,addr temp2,addr sztit,0 mov eax,dword ptr [ldtDes+4];恢复GDT,LDT中的空选择子。 movzx esi,Tss1Gate and esi,0fffffff8h add eax,esi mov dword ptr [eax],0 mov dword ptr [eax+4],0 mov eax,dword ptr [gdtR+2] movzx esi,Tss1Sel add eax,esi mov dword ptr [eax],0 mov dword ptr [eax+4],0 invoke ExitProcess,0 ;----------------------------------------- Ring0Code_div proc far pushad mov ecx,10 ;EIP ambalance002: ;cs push ecx ;EFLAGS call Beeps pop ecx loop ambalance002 popad add dword ptr [esp],2 ; 修改Eip,略过除错指令(div eax)2个字节长,继续执行 iretd Ring0Code_div endp myring0_prc_Trapgt proc far pushad ;注意压栈结构为 mov ecx,10 ;esp->EIP ambalance002: ; cs push ecx ; EFLAGS call Beeps pop ecx loop ambalance002 popad and byte ptr [esp+9],0FEh ;一定要置TF=0,终止 iretd ;注意iretd,不是iret(w) myring0_prc_Trapgt endp myring0_prc_Intgt proc far pushad mov ecx,10 ambalance001: push ecx call Beeps pop ecx loop ambalance001 popad iretd myring0_prc_Intgt endp myring0_prc_callgt proc far pushad pushfd pop eax or eax,3000h push eax popfd mov ecx,10 ambalance: push ecx call Beeps pop ecx loop ambalance popad retf myring0_prc_callgt endp ;----------------------------------------- Search_XDT proc near ;entry esi==Base of Ldt or GDT ;eax==Limit pushad mov ebx,eax ;ebx=limit mov eax,8 ; skipping null selector @@1: cmp dword ptr [esi+eax+0],0 jnz @@2 cmp dword ptr [esi+eax+4],0 jz @@3 @@2: add eax,8 cmp eax,ebx jb @@1 ;if we haven\'t found any free GDT entry, ;lets use the last two entries mov eax,ebx sub eax,7 @@3: mov [esp+4*7],eax ; return off in eax popad ; eax=free GDT entry selector ret Search_XDT endp ;----------------------------------------- Beeps proc near ;经典的发声子程序,学dos的时候应该 pushad ;没少用吧... mov al,0B6h out 43h,al mov al,Freq ;接口要求,不要多问 out 42h,al out 42h,al xor byte ptr Freq,0Ch ; 换频率 ; 以便下次发出不同的音高 in al,61h or al,3 out 61h,al mov ecx,1000000h ;延时 loop $ and al,0FCh ;关声音 out 61h,al popad ret Beeps endp Ring0: mov ebx,cr3 mov TestCR3,ebx iretd END __Start ;______________________________Over...___________ |
|
最新喜欢:cyliu
|
沙发#
发布于:2005-05-09 12:24
谢谢了
|
|
板凳#
发布于:2005-05-28 22:21
wowocock就是pjf吧?
ustc的大牛啊,他的文章总是需要慢慢读的, 仔细体会,呵呵 |
|
地板#
发布于:2005-05-29 09:31
wowocock就是pjf吧? 非也,但他们是两位大牛,这样不是更好吗? :D |
|
|
地下室#
发布于:2005-05-31 13:55
pjf是谁? :D
|
|
5楼#
发布于:2005-05-31 15:42
是吗,WOWocock是我一个学校的吗,不知道呢,等下问问
|
|
|