InterProcess Communications: A simple method using a VxD
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, quindi 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.