[x] RingZ3r0  Proudly Presents [x]

InterProcess Communications

A simple method using a VxD

By GEnius

Salve a tutti, come promesso nel mio tut sulla gestione della memoria di win32,
presento ora un'esempio che utilizza le funzioni di basso livello per la manipolazione delle pagine. In questo esempio implementerò un semplice metodo di IPC (InterProcess Communications). Il metodo descritto è molto semplice ed è stato creato solo per scopi didattici, per scambiare i dati tra processi usate le Api messe a disposizione da winzoz che sono molto più avanzate e funzionali!
I sorgenti sono in asm e costituiscono un VXD e due semplici appz che si scambiano una stringa. Il metodo di IPC è il più semplice possibile, e non fà altro che dichiarare un blocco da rendere pubblico. Ripeto non è questo il metodo migliore per rendere un buffer pubblico, ma resta comunque un buon esercizio!!!! Prima di continuare la lettura dell'esempio consiglio a chi non conoscesse bene la gestione della memoria in win9x di leggere il mio precedente tut :D
Ahhhh....dimenticavo i VxD funzano solo in win9x e non in NT.

Prima di continuare a leggere scaricate questo file zip, esso contiene i sorgenti e gli eseguibili. Decompressatelo, e fate partire Server.exe, comparirà una messagebox, NON premete Ok. Eseguite Client.exe, se tutto è andato bene vedrete comparire 2 messagebox con le seguenti stringhe: Messaggio dal Server:, GEnius... funziona!!!! Provate ora ad eseguire cliente senza Server... e provate altre combinazioni :-)
Ora avrete capito come funziona a grandi linee cosa fanno i due programmi. Essi, infatti, tramite l'utilizzo dei servizi messi a dispozione dal VxD "RZvxd.vxd" comunicano tra loro.

Prima di spiegare il VxD parlerò dei servizi messi a disposizione dallo stesso e dei 2 programmi che lo utilizzano.

 Limitazioni dei servizi del vxd:
 - solo un blocco alla volta può essere reso pubblico
 - è possibile rendere pubblici solo blocchi di grandezza
   multipla di 4kb (Se il vostro blocco da rendere è
   di 3kb il servizio funzionerà comunque ma verrà reso pubblico
   anche il kb successivo! Con conseguente possibilità
   da parte degli altri processi di scrivere in quel kb che non li
   dovrebbe riguardare)
 - nessun controllo degli errori!

Ora la descrizione del primo sorgente.

Breve descrizione dei servizi per il server messi a
disposizione da RZvxd.vxd:

 IPC_SHARE_BLOCK
 servizio usato per rendere pubblico un blocco di
 memoria. Parametri:

 InputBuffer deve puntare ad una struttura siffatta:
  DD IndirizzoBuffer - è l'indirizzo del blocco
  DD SizeOfBuffer - è la grandezza del blocco in unità di 4kb
     NB: SizeOfBuffer funziona in unità di 4kb cioè
     SizeOfBuffer=1 significa blocco di 4kb
     Ho scelto di usare 4kb come unità base
     solo per semplificare il codice, visto che
     la grandezza di una pagina è di 4kb!

 OutputBuffer Buffer abastanza grande da ricevere 4 byte
  riceve 1 se il servizio è andato a buon fine
  0 se invece il blocco è già stato definito o c'è stato un errore

 IPC_LEAVE_BLOCK
  servizio usato per non far vedere più il blocco
  agli altri processi. Parametri: Nessuno :)

-----------------------------------------------------------------------
FILE SERVER.ASM
---------------------------------------
.486
locals
jumps

UNICODE = 0
.model flat,STDCALL
 

extrn GetProcAddress  : PROC
extrn   GetCurrentProcess : PROC
extrn   DeviceIoControl  : PROC

include W32.inc
---------------------------------------

solito header di un file assembler :).

---------------------------------------

L                       EQU <LARGE>
IPC_SHARE_BLOCK         EQU 1
IPC_LEAVE_BLOCK         EQU 2
IPC_GET_SHARE_BLOCK     EQU 3
IPC_BLOCK_PRESENT       EQU 4
---------------------------------------
servizi messi a disposizione dal VxD
---------------------------------------
.data
;**************** blocco che verrà reso pubblico *********************
provabuff       dd offset msg1-offset provabuff ;indirizzi relativi
                dd offset msg2-offset provabuff
msg1            db 'Messaggio dal Server:',0
msg2            db 'GEnius... funziona!!!!',0
;*********************************************************************

IndirizzoBuffer dd offset provabuff
SizeOfBuffer    dd 1 ;grandezza del buffer da rendere pubblico in unità di 4kb

Aspetta         db 'Il Blocco è stato reso pubblico!',0
Server          db 'Server: ',0

Inputbuffer     dd  offset IndirizzoBuffer
hInst           dd 0

ControlCode     dd 1 ;usato per chiamare i vari service del VXD
vxdReturn       dd 4 dup(0) ;buffer per ricevere dati dal vxd
Vxd_Handle      dd 0        ;Handle del Vxd
VxDName         db '\\.\RZvxd.vxd',0  ;nome del file vxd
VxDErrorTxT     db 'Cannot load RingZ.vxd :(',0
ErrHeader       db 'Errore',0

---------------------------------------
definizione delle variabili utilizzate dal server.
La definizione più importante è quella relativa al buffer
da rendere pubblico. Esso non è altro che una struttura
formata da 2 DD che puntano a due stringhe. In realtà un
buffer siffatto è stato scelto da me, ma il VxD non implica
una struttura di questo tipo. Ah..dimenticavo gli indirizzi
delle 2 DD sono relativi, cioè nelle due DD c'è solo lo
spiazzamento delle stringhe dall'inizio del buffer.
InputBuffer, VxdReturn sono usati per il dialogo con il
VXD e rappresentano rispettivamente i parametri di Input e
di Output. In effetti come vedrete più tardi
uso sempre queste variabili per scambiari i dati con il VXD.
ControlCode è usato per selezionare un servizio messo a
disposizione dal vxd.
Le altre variabili o sono messaggi o sono autoesplicative :)
---------------------------------------

.code
 

start:

        push    L 0
        call    GetModuleHandle
        mov     [hInst], eax            ; hInstance non mi serve però è un'abitudine!

        call    OpenVxD                 ;Open the Baby!
        cmp     eax,-1
        jne     NoError
        call    VxDError  ;minghia!
        jmp exit

---------------------------------------
Semplicemente apro il Vxd e controllo che non ci siano errori!
---------------------------------------

NoError:
        mov ControlCode, IPC_SHARE_BLOCK
 Call VxDUse ;rendiamo pubblico il blocco
        cmp [vxdReturn],0
        jz exit

        Call MessageBox, 0, offset Aspetta, offset Server,0 ;pausa

        mov ControlCode,IPC_LEAVE_BLOCK
        Call VxDUse  ;basta con i blocchi publlici! il blocco non è + pubblico!

        Call CloseVxD ;Bye Bye Baby;)

exit:
        push    LARGE-1
        call    ExitProcess ; fine del server
---------------------------------------
Qui non faccio altro che chiamare il servizio IPC_SHARE_BLOCK
per rendere pubblico il blocco. Uso ControlCode per selezionare
il servizio, InputBuffer invece contiene il puntatore al buffer
da rendere pubblico ed infine VxdReturn conterrà il risultato
dell'elaborazione (fatta dal vxd!).
Poi chiamo l'api messagebox ed aspetto l'input dell'utente.
Infine chiudo il vxd ed esco dal programma.
ahhh...dimeticavo Vxd_Handle contiene l'handle del vxd è
settata al momento dell'apertura dello stesso.
---------------------------------------
 

;----------------------------------------------------------------------------
; Procedure per la comunicazione con il VXD
; Semplici ed intuitive!
;----------------------------------------------------------------------------

OpenVxD PROC ;Apre il vxd
        push    0
        push    L FILE_FLAG_DELETE_ON_CLOSE
        push    0
        push    0
        push    0
        push    0
        push    offset VxDName
        call    CreateFileA      ;Uaoo un semplice Createfile!!
        mov     Vxd_Handle,eax
        cmp     eax,-1
        je      VxDError
        ret
OpenVxD ENDP
---------------------------------------
apre il vxd. Per farlo bisogna chiamare CreatefileA, il
quale mi restituisce l'handle del vxd aperto.
---------------------------------------

CloseVxD PROC ; Chiude il Vxd....Bye Bye Baby :D
         push    [Vxd_Handle]
         call    CloseHandle
         mov     eax,1
         ret                     ;All Ok!!
CloseVxD ENDP
---------------------------------------
Chiudo il vxd; un semplice CloseHandle
---------------------------------------

VxDError PROC ; Visualizza un dialogbox con il messaggio di errore
         push    L 0
         call    MessageBeep
         push    L MB_ICONEXCLAMATION
         push    offset ErrHeader
         push    offset VxDErrorTxT
         push    0
         call    MessageBoxA
         ret
VxDError ENDP
---------------------------------------
Visualizza un messaggio di errore :)
---------------------------------------

VxDUse  PROC ; Questa è la proc + importante chiama un servizio del vxd
; il servizio attuale da chiamare si trova nella variabile ControlCode
; Inputbuffer è il puntatore ai parametri di input del servizio
; VxdReturn torna il risultato del servizio
 push    L NULL
        push    0                       ;lp to bytes returned
        push    0                       ;size of output buffer
        push    offset vxdReturn        ;lp to output data
        push    0                       ;size of input buffer
        push    offset Inputbuffer      ;lp to input data
        push    [ControlCode]           ;Control code
        push    [Vxd_Handle]
        call    DeviceIoControl
        ret
VxDUse  ENDP
---------------------------------------
Chiama un servizio del Vxd, il servizio è selezionato
tramite la variabile ControlCode, Inputbuffer e vxdReturn
sono i soliti parametri di Input/Output.
Per chiamare un particolare "servizio" di un vxd si può usare
DeviceIoControl. Questo servizio è rappresentato da un
codice di controllo che è un numero intero. Nel nostro caso
IPC_LEAVE_BLOCK è ad esempio il codice di controllo che fà
riferimento al "servizio" leave block del VxD.
---------------------------------------
end start

OK fine primo sorgente. Prima di andare avanti voglio fare un'appunto, in questo tut parlo di servizi del vxd, questi in realtà non sono dei veri service. In effetti per service di un vxd si intende un servizio che può essere chiamato dalle diverse VMM tramite la solita INT 20, quello che qui chiamo servizi non sono altro che uno scambio di codici di controllo da applicazioni a ring 3 e vxd a ring 0. E' bene far chiarezza per non confondere il significato di "service" usato in questo doc da quello più generale usato in letteratura.

Ora il secondo sorgente Client.asm:

Breve descrizione dei servizi per il client messi a
disposizione da RZvxd.vxd:

 IPC_GET_SHARE_BLOCK
  servizio usato per acquisire l'accesso ad un blocco di
  memoria reso pubblico dal server. Parametri:

 OutputBuffer è un buffer 6 byte che riceve la seguente struttura:
  DD IndirizzoBuffer - è l'indirizzo lineare del blocco pubblico
     se è 0 il server non ha ancora reso pubbblico il blocco
  Dw Selector - è un selettore al blocco pubblico
     se è 0 il server non ha ancora reso pubblico il blocco

 IPC_BLOCK_PRESENT
  servizio usato per non far capire se il blocco è ancora presente
  o il Server lo ha rilasciato. Parametri:
   OutputBuffer è un buffer di 4 byte che riceve 1 se il blocco
                è ancora presente 0 se non lo è più
------------------------------------------------------------------------------
FILE SERVER.ASM
---------------------------------------
.486
locals
jumps

UNICODE = 0
.model flat,STDCALL
 

extrn GetProcAddress  : PROC
extrn   GetCurrentProcess : PROC
extrn   DeviceIoControl  : PROC

include W32.inc

L                       EQU <LARGE>
IPC_SHARE_BLOCK         EQU 1
IPC_LEAVE_BLOCK         EQU 2
IPC_GET_SHARE_BLOCK     EQU 3
IPC_BLOCK_PRESENT       EQU 4
---------------------------------------
solito header e definizione dei servizi.
---------------------------------------

.data
prova           db 35 dup (0h) ;ci copio il primo messaggio
hInst           dd 0
client          db 'Client:',0

ControlCode     dd 1
vxdReturn       dd 2 dup(0) ;buffer per ricevere dati dal vxd

IndLinear       dd 0 ;indirizzo lineare del blocco
Selector        dw 0 ; Selettore al blocco

Testo           db 'Non esiste nessun blocco globale al momento',0

Vxd_Handle      dd 0 ;Handle del Vxd
VxDName         db '\\.\RZvxd.vxd',0
VxDErrorTxT     db 'Cannot load RingZ.vxd :(',0
ErrHeader       db 'Errore',0
---------------------------------------
ControlCode è usato per selezionare il servizio.
vxdReturn è un buffer che conterrà l'output
dell'elaborazione del vxd (ehhhh??!!!)
prova è un buffer che verrà spiegato in seguito.
Le altre var sono messaggi o sono autoesplicative :)
---------------------------------------

.code
 

start:

        push    L 0
        call    GetModuleHandle         ; get hmod
        mov     [hInst], eax            ; hInstance is same as HMODULE

        call    OpenVxD                 ;Open the Baby!
        cmp     eax,-1
        jne     NoError
        call    VxDError  ;minghia!
        jmp exit
---------------------------------------
solita storia, carico il vxd e controllo
che non ci siano errori.
---------------------------------------

NoError:
        mov ControlCode, IPC_GET_SHARE_BLOCK
        Call VxDUse ;voglio l'indirizzo del blocco pubblico
        cmp word ptr [vxdReturn],0
        jz mess
---------------------------------------
chiamo il servizio IPC_GET_SHARE_BLOCK. Controllo
che vxdReturn sia 0, in questo caso vuol dire che
non ci sono blocchi pubblici definiti quindi visualizzo il messaggio
di errore.
Se tutto è andato bene, VxdReturn sarà così costituito:
i primi 4 byte costituiscono l'indirizzo lineare del buffer
ed i successivi 2 byte costituiscono il selettore al buffer.
---------------------------------------

        mov ax, word ptr [vxdReturn+4]
        mov [Selector], ax ;Setto la variabile Selector con il selettore al blocco
        mov eax, [vxdReturn]
        mov [IndLinear], eax ;ora memorizzo l'indirizzo lineare del blocco
---------------------------------------
assegno i valori presenti in VxdReturn
in variabili autoesplicative!
---------------------------------------

        push es ;salviamo ES attuale
        mov es, [Selector]
        mov ebx, es:0
        mov ecx, 0ffffh
        mov eax,0
        mov edi,ebx  ;ora edi è l'offset alla prima stringa nel segmento ES
        repnz scasb ;vedo quando è lunga la prima stringa nel blocco
        sub edi,ebx
        mov ecx,edi ;edi contiene la lunghezza della stringa
        mov esi,ebx
        mov edi, offset prova
        push ds
        push es
        pop ds
        pop es
        rep movsb ; copio la prima stringa nel buffer prova
        push es
        pop ds
        pop es
        Call MessageBox, 0, offset prova, offset client,0 ;visualizzo il buffer prova

---------------------------------------
ora copio la prima stringa, che si trova nel blocco pubblico,
nel buffer prova. Per far questo utilizzo il selettore presente
in selector invece dell'indirizzo lineare (presente in IndLinear).
Il selettore punta ad un descrittore che specifica un segmento
che contiene il solo blocco pubblico. Viene usato il selettore
solo per scopi didattici :) infatti è più semplice usare l'indirizzo lineare!
Infine viene visualizzata la prima stringa tramite il buffer prova
---------------------------------------

        mov ControlCode, IPC_BLOCK_PRESENT
        Call VxDUse       ;controllo che il blocco esista ancora!
        cmp word ptr [vxdReturn],0
        jz chiudi
        mov eax, [IndLinear] ;ora usiamo l'indirizzo lineare invece che il selettore!
        add eax, [eax+4]     ;aggiunge l'indirizzo relativo che punta alla 2° stringa
        Call MessageBox, 0, eax, offset client,0 ;visualizzo la seconda stringa
                                                 nel blocco semplicemente usando un
                                                 indirizzo lineare
 
 

---------------------------------------
Chiama il servizio IPC_BLOCK_PRESENT, per controllare
se il blocco è ancora esistente. Se tutto và per il meglio
allora visualizza la seconda stringa tramite l'indirizzo lineare
al buffer pubblico. Da notare il calcolo dell'indirizzo assoluto
della seconda stringa a partire da quello relativo.
---------------------------------------

chiudi:
        Call CloseVxD

exit:
        push    LARGE-1
        call    ExitProcess  ;fine programma!

mess:
        Call MessageBox, 0, offset Testo, offset client,0 ;messaggio: non esiste nessuno blocco
                                                          ;globale definito!
        jmp exit
---------------------------------------
esce dal programma.
---------------------------------------

E' quindi finito anche il secondo programma di esempio. Ora finalmente arriviamo a ciò che veramente ci interessa e cioè il VXD. Nel codice seguente ho appositamente incluso anche alcune sezioni non utilizzate al solo scopo di mostrare la struttura
completa di un VxD.

.386p
 .xlist
 include vmm.inc
 include vwin32.inc
 include shell.inc
.list
 

RINZEName              EQU     <'RINZE VXD      '> ;Must be 16 chars
RINZERev               EQU     00H

RINZE_MAJOR_VERSION    EQU     1
RINZE_MINOR_VERSION    EQU     0

ErrorCode               EQU 0FFFFFFFFh

---------------------------------------
Header del Vxd molto simile a quello di un normale programma
---------------------------------------

;******************************************************************************
;                                D A T A
;******************************************************************************

VXD_LOCKED_DATA_SEG
;       Pagelocked data here - try to keep this to a minimum.
VM_Handle   dd 0
jmptable    dd RetSuccess
            dd IPC_SHARE_BLOCK
            dd IPC_LEAVE_BLOCK
            dd IPC_GET_SHARE_BLOCK
            dd IPC_BLOCK_PRESENT
Selector    dd 0 ;selettore al blocco pubblico; 0 se il blocco non è presente
LinAddress  dd 0 ;linear address al blocco pubblico; 0 se il blocco non è presente
SizeAddress dd 0 ; Size of the block in unità di 4kb
VXD_LOCKED_DATA_ENDS
---------------------------------------
Segmento che contiene le variabili globali del programma.
Esse non saranno mai spostate.
VM_Handle è l'handle del vxd.
jmptable è una jump table ad i vari servizi messi a disposizione
dal vxd.
Le altre variabili sono autoesplicative.
---------------------------------------
 

VxD_CODE_SEG
;******************************************************************************
;
;   VXD_Create_VM
;
;   DESCRIPTION:
;       This is a shell for a routine that is called when a virtual
;       machine is created. A typical VxD might perform some action
;       here to prepare for handling the new VM in the system.
;
;   ENTRY:
;       EBX = VM handle
;
;   EXIT:
;       Carry clear to continue creating VM
;       Carry set to abort the creation of the VM
;
;   USES:
;       flags
;
;==============================================================================

BeginProc VXD_Create_VM

        clc                             ;no error - continue
        ret

EndProc VXD_Create_VM
---------------------------------------
non usato!!!
---------------------------------------

VxD_CODE_ENDS

;******************************************************************************
;              V I R T U A L   D E V I C E   D E C L A R A T I O N
;------------------------------------------------------------------------------
; The VxD declaration statement defines the VxD name, version number,
; control proc entry point, VxD ID, initialization order, and VM API
; entry points. What follows is a minimal VxD declaration, defining
; only the name, version, control proc, and an undefined ID. Depending
; on the requirements of the VxD, the following may be added:
;
; - Defined VxD ID: See VXDID.TXT for more information
; - Init order: If your Vxd MUST load before or after a specific VxD,
;               the init order can be defined. See VMM.INC for the
;               definition of the init order of the standard devices.
; - V86,PM API: You may wish to allow application or library code running
;               in a virtual machine to communicate with your VxD directly.
;               See the chapter entitled "VxD APIs (Call-Ins)" in the
;               Virtual Device Adaptation Guide.
;
;******************************************************************************

VXD_LOCKED_CODE_SEG

DECLARE_VIRTUAL_DEVICE RINZE,  \
        RINZE_MAJOR_VERSION,   \
        RINZE_MINOR_VERSION,   \
        RINZE_Control, ,       \
 UNDEFINED_INIT_ORDER
 

;******************************************************************************
;                      P A G E   L O C K E D   C O D E
;------------------------------------------------------------------------------
;       Memory is a scarce resource. Use this only where necessary.
;******************************************************************************
 

;******************************************************************************
;
;   VXD_Control
;
;   DESCRIPTION:
;
;       This is a call-back routine to handle the messages that are sent
;       to VxD's to control system operation. Every VxD needs this function
;       regardless if messages are processed or not. The control proc must
;       be in the LOCKED code segment.
;
;       The Control_Dispatch macro used in this procedure simplifies
;       the handling of messages. To handle a particular message, add
;       a Control_Dispatch statement with the message name, followed
;       by the procedure that should handle the message.
;
;       The two messages handled in this sample control proc, Device_Init
;       and Create_VM, are done only to illustrate how messages are
;       typically handled by a VxD. A VxD is not required to handle any
;       messages.
;
;   ENTRY:
;       EAX = Message number
;       EBX = VM Handle
;
;==============================================================================

public RINZE_Control
RINZE_Control PROC NEAR

        Control_Dispatch SYS_DYNAMIC_DEVICE_INIT,       RINZE_Device_Init
        Control_Dispatch SYS_DYNAMIC_DEVICE_EXIT,       RINZE_Device_Exit
        Control_Dispatch W32_DEVICEIOCONTROL,           RINZE_ioctl
 clc
 ret

RINZE_Control ENDP
---------------------------------------
Dispatcher per i messaggi mandati al vxd, rimanda
a RINZE_Device_Init, RINZE_Device_Exit, RINZE_Device_Exit
rispettivamente per i messaggi di init, exit e tutti gli altri!
---------------------------------------

Public RINZE_ioctl
BeginProc RINZE_ioctl
        ; jump to the service pointed by dwIoControlCode
        mov ecx,[esi].dwIoControlCode ; get ioctl code
        cmp ecx,4
        ja  RetSuccess
        jmp dword ptr [jmptable+ecx*4]
        jmp RetSuccess
---------------------------------------
Controlla i messaggi inviati e manda al sottoprogramma per
che gestisce il servizio selezionato. In pratica viene chiamata
da DeviceIoControl.
Ottiene il codice del servizio passato a DeviceIoControl dall'appz
a ring 3 e controlla che sia un servizio valido, quindi invia il
controllo alla routine giusta altrimenti, ritorna.
---------------------------------------

IPC_SHARE_BLOCK: ;*** servizio IPC_SHARE_BLOCK
     cmp [LinAddress],0 ;the block exists??
        jz globalize
Errore: mov eax,0 ;Error
        mov ebx, [esi].lpvOutBuffer
        mov dword ptr [ebx], eax
        jmp RetSuccess
---------------------------------------
controlla che esista già un blocco pubblico.
Se esiste ritorna 0 nel buffer di output.
---------------------------------------

globalize:
        mov eax, [esi].lpvInBuffer  ; Parameter
 mov eax,[eax]
        mov ebx,[eax] ; linear address of the  buffer that we can make public
        mov ecx,[eax+4] ; size in 4kb units
        mov [SizeAddress],ecx ;save the size of the block
        shr ebx,12
 VMMCall _LinPageLock <ebx, ecx, PAGEMAPGLOBAL > ;create an Address Alias in shared
                                                  page table
        cmp eax,0
        jz Errore
        mov [LinAddress], eax
---------------------------------------
Il servizio crea un selettore ed un indirizzo lineare per il blocco
da rendere pubblico.
Esegue il service Linpagelock con il parametro PAGEMAPGLOBAL
per crearsi un alias del buffer in un'area shared.
Il buffer da rendere pubblico è passato come parametro. Da notare
l'istruzione shr ebx,12 che serve per ricavare il numero della
pagina a cui fà riferimento l'indirizzo lineare presente in ebx.
Ora eax al ritorno dalla Linpagelock mi indicherà l'indirizzo lineare
pubblico del buffer!
---------------------------------------

        VMMCall _BuildDescriptorDWORDs, <eax, 1, 0f2h, 0c0h, BDDExplicitDPL> ;create
                                                        the descriptor to ring 3 data
        VMMCall _Allocate_GDT_Selector, <edx, eax, 0> ;Allocate the GDT
        mov ecx, eax              ; zero in eax and edx if error
        or  ecx, edx
        jz  Errore
        mov [Selector], eax       ; new selector of the block
        mov ebx, [esi].lpvOutBuffer
        mov dword ptr [ebx], 1
 jmp RetSuccess
---------------------------------------
ora mi creo un descrittore ad un segmento che contiene
perfettamente il buffer ed avrà DPL (destination privilege
level) uguale a 3 (per essere usato a ring 3).
Quindi chiamo AllocateGDTSelector per allocarmi un selettore
nella GDT. Da notare che il Base address del descrittore è
uguale all'indirizzo lineare pubblico non a quello passato come
parametro!
All'uscita se tutto è andato bene eax conterrà il
Selettore.
---------------------------------------

IPC_LEAVE_BLOCK: ;*** servizio IPC_LEAVE_BLOCK
        mov eax,[LinAddress]
        or eax, [Selector]
        jz RetSuccess ;the block exists??
        mov eax, [Selector]
        VMMCall _Free_GDT_Selector, <eax, 0> ;Free the GDT selector
        mov eax, [LinAddress]
        mov ebx, [SizeAddress]
        shr eax, 12
        VMMCall _LinPageUnLock <eax, ebx, PAGEMAPGLOBAL > ;remove the shared alias
                                                        of the page
        mov [LinAddress],0
        mov [SizeAddress],0
        jmp RetSuccess
---------------------------------------
Il servizio elimina il blocco pubblico, cioè lo
rende di nuovo privato :DDD
Prima controllo che ci sia un blocco pubblico definito,
quidni Elimino il selettore dalla GDT e quindi l'alias
del blocco nell'area shared.
---------------------------------------

IPC_GET_SHARE_BLOCK: ;*** servizio IPC_GET_SHARE_BLOCK
        mov eax, [LinAddress]
        or eax, [SizeAddress] ;the block exists??
        jz Err
        mov ebx, [esi].lpvOutBuffer
        mov edx, [LinAddress] ;return the Linear Address to the block
        mov [ebx], edx
        mov edx, [Selector] ;return the Selector to the Block
        mov word ptr [ebx+4], dx
        jmp RetSuccess
Err:    mov eax,0
        mov ebx, [esi].lpvOutBuffer
        mov [ebx], eax
        mov [ebx+4],ax
        jmp RetSuccess
---------------------------------------
Non fà altro che restituire all'appz ring 3 che lo chiama
l'indirizzo lineare ed il selettore al blocco! Se nessun
blocco è stato definito restituisce 0.
---------------------------------------

IPC_BLOCK_PRESENT: ;*** servizio IPC_BLOCK_PRESENT
        mov ecx,0
        mov eax, [LinAddress]
        or eax, [SizeAddress]
        jz noblock ;the block exists?? if no return 0 else go on
        mov ecx,1 ;return 1
noblock:
        mov eax, [esi].lpvOutBuffer
        mov [eax], ecx
        jmp RetSuccess

RetSuccess: ; All Ok!!
        xor     eax, eax     ;return zero = success
 clc
 ret
---------------------------------------
Restituisce 0 se esiste un blocco pubblico
1 altrimenti!
---------------------------------------
EndProc RINZE_ioctl
 
 

Public RINZE_Device_Exit
BeginProc RINZE_Device_Exit

 clc
 ret
EndProc RINZE_Device_Exit
---------------------------------------
non usato!!!!!
---------------------------------------
VXD_LOCKED_CODE_ENDS
 
 

;******************************************************************************
;                  I N I T I A L I Z A T I O N   C O D E
;------------------------------------------------------------------------------
;    Code in the initialization segment is discarded after Init_Complete
;******************************************************************************

VXD_ICODE_SEG

;******************************************************************************
;
;   VXD_Device_Init
;
;   DESCRIPTION:
;       This is a shell for a routine that is called at system BOOT.
;       Typically, a VxD would do its initialization in this routine.
;
;   ENTRY:
;       EBX = System VM handle
;
;   EXIT:
;       Carry clear to indicate load success
;       Carry set to abort loading this VxD
;
;   USES:
;       flags
;
;==============================================================================
 

BeginProc RINZE_Device_Init

 clc
 ret

EndProc RINZE_Device_Init
---------------------------------------
non usato!!!!!
---------------------------------------
VXD_ICODE_ENDS

end

Fine VXD!!!!!!!!

Come vedete l'esempio non è niente di particolare, ma può essere una buona base per incominciare a giocare con il gestore della memoria di win9x :-)

Se i commenti non sono stati chiari non prendetevela con me... ho fatto del mio meglio per spiegare nel modo + semplice e conciso possibile... ma l'ho scritto di notte :D.

Un'ultima nota compilate i programmi Server e Client con Tasm 5.x e RZvxd con Masm 6.1x.

Ora i SALUTI:

Insanity: poveraccio...gli facciamo sempre cambiare la hp :DD
D4eMoN: oracle???!!! hai finito o nooo?????
Kill3xx: quando riprendiamo il ppatcher??
NeuRal_NoiSE: chiamtelo NEUTRAL NORISEEE :)
YanOrel: Mitica la sua pagina web!
T3x: SoftICE... ti dice qualkosa??
KRY0: !-! ti ricordi??
MetalheaD: dove sei finito???
beh non voglio dilungarmi troppo (ho sonno!!) quindi saluto tutti gli amici di #crack-it ed in maniera particolare tutti i members dei RingZer0.