home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 13
/
mediashare_13.zip
/
mediashare_13
/
ZIPPED
/
PROGRAM
/
DDJ9403A.ZIP
/
UC394.ASC
< prev
next >
Wrap
Text File
|
1994-01-30
|
11KB
|
312 lines
_UNDOCUMENTED CORNER COLUMN_
edited by Andrew Schulman
"RINGO: VXDS ON THE FLY"
by Alex Shmidt
Listing 1
/* CALLGATE.H */
typedef DWORD (FAR PASCAL *GATEPROC)(WORD svc, WORD cnt, DWORD extra);
/* SeeYouAtRing0 services */
#define Get386_Svc 0 //get system info
#define PhysToLin_Svc Get386_Svc + 1 //map phys to linear
#define Register_Hwnd_Svc PhysToLin_Svc + 1 //register HWND
#define Unregister_Hwnd_Svc Register_Hwnd_Svc + 1 //unregister HWND
#define StopVM_Svc Unregister_Hwnd_Svc + 1 //toggle DOS box exec
#define RemapGate_Svc StopVM_Svc + 1 //remap call gate
typedef struct { /* call gate procedure parameters */
DWORD G_Dword; // Dword parameter
WORD G_Word; // Word parameter
WORD G_Svc; // service number
}GPARAM;
/* RingoInit functions */
#define EXITRINGO 0xFFFF
#define INITRINGO 0
Listing 2
/* RINGO.C -- excerpts */
//#define CALLGATE_386 //define CALLGATE_386 to get gates from CALLGATE.386
#include <windows.h>
#include "386.h"
#include "callgate.h"
#ifdef CALLGATE_386
GATEPROC GetFirstCallGateVxD (FARPROC entrypoint,BYTE paramcount);
void DestroyInitGateVxD (WORD callgateselector);
#endif
VOID WINAPI RingoInit(void);
VOID WINAPI SeeYouAtRing0(void);
VOID WINAPI MakeSureOurSegIsInMemory(void);
GATEPROC GetLdtRing0CallGate (FARPROC entrypoint,
BYTE paramcount,WORD callgate);
GATEPROC GDT_Gate,LDT_Gate;
int FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSeg,
WORD cbHeapSize, LPSTR lpszCmdLine )
{
FARPROC ri = (FARPROC) RingoInit;
if (!(GetWinFlags () & WF_ENHANCED)) /*VxDs exist in enhanced mode only*/
return 0;
#ifdef CALLGATE_386 // get the GDT call gate from CALLGATE.386
if (!(LDT_Gate = GetFirstCallGateVxD (ri, sizeof(GPARAM)/4)))
#else // get the LDT call gate with INT 2F, AX=168A
if (!(LDT_Gate = GetLdtRing0CallGate (ri, sizeof(GPARAM)/4, 0)))
#endif
return 0;
/*** get the main call gate in GDT ***/
GDT_Gate = (GATEPROC)LDT_Gate (INITRINGO, sizeof(GPARAM)/4,
(DWORD)SeeYouAtRing0);
if (cbHeapSize)
UnlockData (0);
return (1);
}
char vendor[] = "MS-DOS"; // Microsoft's signature
GATEPROC GetLdtRing0CallGate (FARPROC gproc, BYTE params,WORD gatesel)
{
#define VENDOR_SPECIFIC_API 0x168a
WORD ldt_map; // LDT selector, which maps LDT itself
WORD (far * entryp)(void); // entry point to get the above
LPCALLGATEDESCRPT CGateDescriptor; // build call gate descriptor with this
WORD RW_ldt_map; /* ldt map selector fixes segment read-only problem */
WORD CGateSelector; // to be a call gate selector
DWORD initgate_flat; // callgate procedure's linear address
_asm {
mov si, offset vendor
mov ax, VENDOR_SPECIFIC_API
int 2fh
or al, al
jnz no_vendor
mov word ptr [entryp], di /* private entry point */
mov word ptr [entryp+2], es
mov ax, 100h /* magic number */
}
ldt_map = entryp(); /* returns LDT map selector */
_asm jnc vendor_ok
no_vendor:
return 0;
vendor_ok:
// When run under SoftICE/W LDT alias returns read_only, give us a good one
if (!(RW_ldt_map = AllocSelector(SELECTOROF((void FAR *)&GDT_Gate))))
return 0;
SetSelectorBase(RW_ldt_map, GetSelectorBase(ldt_map));
SetSelectorLimit(RW_ldt_map, GetSelectorLimit(ldt_map));
if ((CGateSelector = gatesel) == 0) // we might already have one
if (!(CGateSelector = AllocSelector(0))) // Get a selector for the gate
{
FreeSelector (RW_ldt_map);
return 0;
}
// create a pointer to write into the LDT
CGateDescriptor = MAKELP(RW_ldt_map,CGateSelector & SELECTOR_MASK);
// build 32-bit ring 3-to-0 call gate
#define MK_LIN(x) (GetSelectorBase(SELECTOROF(x)) + (DWORD)OFFSETOF(x))
initgate_flat = MK_LIN(gproc);
CGateDescriptor->Offset_O_15 = LOWORD (initgate_flat);
CGateDescriptor->Offset_16_31 = HIWORD (initgate_flat);
CGateDescriptor->Selector = 0x28; // ring0 flat code seg
CGateDescriptor->DWord_Count = params & CALLGATE_DDCOUNT_MASK;
CGateDescriptor->Access_Rights = GATE32_RING3; //pres,sys,dpl3,32CallGate
FreeSelector (RW_ldt_map); // don't need you any more
return ((GATEPROC)MAKELP(CGateSelector,0));
}
DWORD WINAPI _export MapPhysToLinear (DWORD physaddr, WORD mapsize)
{
return (GDT_Gate)(PhysToLin_Svc,mapsize,physaddr); /* DPMI alternative */
}
Listing 3
;;; RINGO.INC -- excerpts
GPARAM struc ; parameters
G_Dword dd ?
G_Word dw ?
G_Svc dw ?
GPARAM ends
CALLGATE_FRAME struc ; stack frame at the time of ring transition
CG_pushbp dd ?
CG_Old_EIP dd ? ; this is where we came from
CG_Old_CS dd ? ; and will get back
CG_Params db (type GPARAM) dup (?) ; call gate parameters
CG_Old_ESP dd ? ; caller's
CG_Old_SS dd ? ; stack
CALLGATE_FRAME ends
BuildGateStackFrame macro dataseg
push ebp
mov ebp,esp
push gs
push ds
push es
push fs
push esi
push edi
ifidni <dataseg>,<_DATA>
mov ax,ds
mov gs,ax ; we'll access our data seg via gs
endif
mov ax,ss
mov ds,ax ; ring 0 flat data delector
mov es,ax
mov fs,ax
ifdifi <dataseg>,<_DATA>
call GetRingoGdtDataSel
endif
endm
ClearGateStackFrame macro cleanup
pop edi
pop esi
pop fs
pop es
pop ds
pop gs
pop ebp
ret cleanup
endm
movoffs macro reg,off32 ; run-time fixup
mov reg, offset &off32
add reg,gs:[ringo_flat]
endm
Listing Four
;;; CALLGATE.ASM -- excerpts
.386p
include vmm.inc
include ringo.inc
include 386.inc
public RingoInit,SeeYouAtRing0,MakeSureOurSegIsInMemory
_GATESEG segment dword use32 public 'CODE'
assume cs:_GATESEG,gs:_DATA
RingoInit proc far
BuildGateStackFrame _DATA
cmp [ebp].CG_Params.G_Svc,EXITRINGOCALL
jnz short @f
call RingoExit ; deallocate everything we've got
jmp short retini
@@: call RelocateRingo ; run-time relocation and fixups
jc short init_ret
call DynalinkTrick ; get the VxD chain root
call InsertRingoDDB ; welcome to the VxD club
call CreateRingoGDTGate ; GDT call gate to SeeYouAtRing0
retini: mov edx, eax ; prepare return values for the ring 3
shr edx, 16
ClearGateStackFrame <size CG_Params> ; clear both ring stack frames
RingoInit endp
SeeYouAtRing0 proc far ; The callgate service proc
BuildGateStackFrame
VMMCall Get_Cur_VM_Handle ; always helpful
movzx eax, [ebp].CG_Params.G_Svc ; service dispatcher
cmp eax,LASTSVC
ja @f
call gs:Gate_Service_Table[eax*4]
@@: mov edx, eax
shr edx, 16
ClearGateStackFrame <size CG_Params>
SeeYouAtRing0 endp
CreateRingoGDTGate proc
movzx edx, word ptr [ebp].CG_Params.G_Dword ; offset16
add edx,gs:[ringo_flat] ; fixup
mov ax, cs ; VMM code selector
mov cx, [ebp].CG_Params.G_Word ; parameter count
and cx, CALLGATE_DDCOUNT_MASK ; make sure it's a reasonable number
or cx, GATE32_RING3 ; call gate type
call BuildCallGateDWords
VMMCall _Allocate_GDT_Selector,<edx,eax,20000000h> ; undocumented flag
ror eax,16
ret
CreateRingoGDTGate endp
BeginProc DestroyGDTCallGate,public
movzx eax,[ebp].CG_Params.G_Word
VMMCall _Free_GDT_Selector,<eax,0>
ret
EndProc DestroyGDTCallGate
BuildCallGateDWords proc
movzx eax, ax
shl eax, 16 ; selector
mov ax, dx ; offset 0-15
mov dx, cx ; offset 16-31 + type + count
ret
BuildCallGateDWords endp
;****************************************************************************
; To get the VxD Base (VMM DDB ptr) we're using the undocumented fact that
; VMM's dynalink handler (considered a 'fault' 20h in DDK spec parlance)
; returns it in ecx. The idea is to hook VMM fault 20h, call any VMM service
; to get our fault handler receive control, call VMM's dynalink directly,
; store ecx in a static variable, and hook fault 20h again, this time
; with fault handlers reversed.
;****************************************************************************
BeginProc DynalinkTrick
mov esi, gs:[OurDynalinkHandler]
twice: mov eax, 20h
VMMCall Hook_VMM_Fault ; install our handler
mov gs:[OLD_DYNALINK_HANDLER], esi
VMMCall Get_VMM_Version ; need one call get it executed
cmp esi, gs:[OurDynalinkHandler]
jnz twice
mov eax, gs:[VXD_FIRST]
ret
EndProc DynalinkTrick
Ringo_Dynalink_Handler proc
call gs:[OLD_DYNALINK_HANDLER]
mov gs:[VXD_FIRST], ecx ; DDB pointer
ret
Ringo_Dynalink_Handler endp
PhysToLin proc ; physical to linear address mapping
movzx ecx, [ebp].CG_Params.G_Word
VMMcall _MapPhysToLinear,<[ebp].CG_Params.G_Dword,ecx,0>
ret
PhysToLin endp
ringo_flat dd 0 ; run-time space base
OLD_DYNALINK_HANDLER dd 0
VXD_FIRST dd 0 ; VxD chain root
OurDynalinkHandler dd offset Ringo_Dynalink_Handler
Ringo_DDB VxD_Desc_Block <,,,1,0,,'Ringo ',,offset RingoControlProc,,,,,,,>
Gate_Service_Table label dword
dd offset Get386
dd offset PhysToLin
dd offset RegisterHWND
dd offset UnregisterHWND
dd offset StopVM
dd offset RemapCallGate
_GATESEG ends
end