InterProcess Communications II
Another simple method
By GEnius
Piu' che campare, si campeggia!
NeuRaL_NOISE.
--==[ PREMESSA ]==--------------------------------------------------------------Eccomi di nuovo (hey chi di voi si è permesso di dire: ekepalle???)...
nuovo tut su come permettere a due o + processi di comunicare tramite l'ausilio di un semplice VxD. Quest'altro metodo di IPC (InterProcess Communications) si basa sul service _PageAttch, che permette di mappare delle pagine da un processo nell'address space di un'altro. 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 un buffer. Il metodo di IPC è veramente semplice, e non fà altro che mappare una serie di pagine in un processo. Ripeto non è questo il metodo migliore per far comunicare due processi, 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 (e non kiamatela pubblicità okkulta!) :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 una messagebox con la seguente stringa: "Messaggio dal Server: GEnius... funziona!!!!"
Ora chiudete il client tramite il pulsante Ok, e cliccate su ok del Server, vedrete
un'altro msgbox comparire con la scritta: "GEnius... ha detto Suby: è logico che funza!!" (eheheheh Suby te l'ho detto che ti tiravo in mezzo con le msgbox!).
Provate ora ad eseguire il client 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.--==[ UNDOCUMENTED??!! ]==-----------------------------------------------------------
Per implementare questo metodo di IPC ho dovuto fare uso del service VMM _PageAttach. La documentazione m$ è questa:
ULONG EXTERNAL _PageAttach(ULONG page, PCD hcontextsrc, ULONG npages);
Maps a range of linear pages in the current memory context to the same physical storage that those pages are mapped to in a specified context (the source context). Do not call this service.
Returns a nonzero value if successful, zero otherwise.
page and npages
Linear page number of the first page to map, and the number of pages to map.
hcontextsrc
Handle of the source memory context.This service should only be called by the Win32 program loader, which uses it to map the pages containing a program image from one context into another.
Beh, direte voi a parte l'inopportuna avvertenza di non usare questa servizio (cz... m$ ma se non vuoi farcelo usare fai come tuo solito no?? Non documentarlo!), il servizio è del tutto documentato. In effetti è quello che credevo anch'io, ma in realtà non è così. Infatti facendo un pò di prove chiamando _PageAttach con i parametri descritti, la funzione resituisce sempre True, ma nulla sembra accadere! Non convinto faccio 200.000 cambiamenti nel codice pensando di essere io l'imbecile che non sà leggere nemmeno la documentazione. Esaurite tutte le prove che mi sono venute in mente e dopo una incazzatura di livello astronomico, decido di vedere come czzzz viene chiamata _PageAttach da vWin32. SOPRESA!!!!! CHE TE VADO A SCOPRI'??!! Che stì cazzoni del m$ si sono dimenticati di documentare un parametro! E che parametro! Il prototipo diverrà quindi:
ULONG EXTERNAL _PageAttach(ULONG SRCpage, PCD hcontextsrc,ULONG DESTpage, ULONG npages)
Il nuovo parametro DESTpage indica la pagina iniziale del processo corrente in cui saranno le pagine del processo sorgente (SRCpage). In effetti sin dalla prima volta che ho letto il prototipo di questo funzione mi sembrava strano che la m$ non avesse dato la possibilità di mappare le pagine sorgenti in indirizzi lineari diversi. E' infatti logico pensare che gli indirizzi lineari che fanno riferimento alla pagina sorgente possano essere già usati nel processo corrente :) Cmq a conclusione del discorso non fidatevi cecamente della documentazione m$ :-P
--==[ I SERVICE DEL VxD PER IL SERVER ]==--------------------------------------------
Prima di spiegare il VxD parlerò dei servizi messi a disposizione dallo stesso e dei 2 programmi che lo utilizzano. Un'ultimo 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.
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)
- Controllo degli errori limitato!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 da mappare in altri processi
DD SizeOfBuffer - è la grandezza del blocco in unità di 4kbNB: SizeOfBuffer è 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 deve essere abbastanza grande da ricevere 4 byte
riceve 1 se il servizio è andato a buon fineIPC_LEAVE_BLOCK
servizio usato per non permettere più
ad altri processi di mappare il blocco. Parametri: Nessuno :)--==[ SERVER.ASM ]==-----------------------------------------------------------------
.486
locals
jumpsUNICODE = 0
.model flat,STDCALL
extrn GetProcAddress : PROC
extrn GetCurrentProcess : PROC
extrn DeviceIoControl : PROC
extrn VirtualAlloc : PROCinclude W32.inc
---------------------------------------
solito header di un file assembler :).
---------------------------------------
L EQU <LARGE>
IPC_SHARE_BLOCK EQU 1
IPC_MAP_BLOCK EQU 2
IPC_BLOCK_PRESENT EQU 3
IPC_LEAVE_BLOCK EQU 4---------------------------------------
servizi messi a disposizione dal VxD
---------------------------------------
.data;******** blocco che potrà essere mappato in agltri processi *********
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 ;numero di pagine da mappareAspetta db 'Il Blocco può essere mappato ora!',0
Server db 'Server: ',0Inputbuffer dd offset IndirizzoBuffer
hInst dd 0ControlCode dd 1
vxdReturn dd 4 dup(0) ;buffer per ricevere dati dal vxd
Vxd_Handle dd 0 ;Handle del Vxd
VxDName db '\\.\RZvxd.vxd',0
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 :)
---------------------------------------
.codestart:
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---------------------------------------
Carico il vxd e controllo
che non ci siano errori.
---------------------------------------NoError:
;int 3
mov ControlCode, IPC_SHARE_BLOCK
Call VxDUse ;assegnamo il blocco da poter mappare
cmp [vxdReturn],0
jz exit ;error??
Call MessageBox, 0, offset Aspetta, offset Server,0 ;pausamov eax, offset provabuff
mov ebx, eax
add ebx, [eax]
add eax, [eax+4]
Call MessageBox, 0, EAX, EBX ,0 ;visualizza le modifiche fatte dal client!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
di informazione sulle pagine da da mappare ed
infine VxdReturn conterrà il risultato
dell'elaborazione (fatta dal vxd!).
Poi chiamo l'api messagebox ed aspetto l'input dell'utente.
Quindi di nuovo la messagebox per vedere se c'è stato una modifica
del blocco da parte del client.
Infine chiudo il vxd ed esco dal programma.
ahhh...dimeticavo Vxd_Handle contiene l'handle del vxd è
inizializzata 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 startOK fine primo sorgente.
--==[ I SERVICE DEL VxD PER IL CLIENT ]==--------------------------------------------
Breve descrizione dei servizi per il client messi a
disposizione da RZvxd.vxd:IPC_MAP_BLOCK
servizio usato per acquisire mappare un blocco di
memoria reso pubblico dal server nel proprio address space.
Parametri:
OutputBuffer è un buffer riceve l'indirizzo lineare del blocco pubblico
se è 0 il se non c'è nessun blocco da mappare.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 c'è un blocco
da mappare 0 altrimenti.--==[ CLIENT.ASM ]==--------------------------------------------------------------
.486
locals
jumpsUNICODE = 0
.model flat,STDCALL
extrn GetProcAddress : PROC
extrn GetCurrentProcess : PROC
extrn DeviceIoControl : PROCinclude W32.inc
L EQU <LARGE>
IPC_SHARE_BLOCK EQU 1
IPC_MAP_BLOCK EQU 2
IPC_BLOCK_PRESENT EQU 3
IPC_LEAVE_BLOCK EQU 4
---------------------------------------
solito header e definizione dei servizi.
---------------------------------------.data
hInst dd 0
client db 'Messaggio dal Client:',0
reply db 'GEnius... ha detto Suby: è logico che funza!!',0ControlCode dd 1
vxdReturn dd 0 ;buffer per ricevere dati dal vxdIndLinear dd 0 ;indirizzo lineare del blocco
Testo db 'Non esiste nessun blocco da mappare 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??!!!)
Le altre var sono messaggi o sono autoesplicative :)
---------------------------------------.code
start:
push L 0
call GetModuleHandle ; get hmod
mov [hInst], eax ; hInstance is same as HMODULEcall 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_BLOCK_PRESENT
Call VxDUse ;controllo che un blocco esista!
cmp word ptr [vxdReturn],0
jz mess
---------------------------------------
chiamo il servizio IPC_BLOCK_PRESENT. Controllo
che vxdReturn sia 0, in questo caso vuol dire che
non ci sono blocchi pubblici definiti quindi visualizzo il
messaggio di errore.
---------------------------------------mov ControlCode, IPC_MAP_BLOCK
Call VxDUse ;voglio mappare il blocco
cmp [vxdReturn],0
jz chiudi---------------------------------------
Chiamo il servizio IPC_MAP_BLOCK per mappare il
blocco nel mio address space. Se tutto è andato
bene vxdReturn conterrà l'indirizzo del blocco
mappato, altrimenti conterrà 0.
---------------------------------------mov eax, [vxdReturn] ;indirizzo privato del blocco mappato
mov ebx, eax
add ebx, [eax]
add eax, [eax+4]
Call MessageBox, 0, eax, ebx,0 ;visualizzo le stringhe (dal blocco mappato)---------------------------------------
ora visualizzo le stringhe che sono nel blocco
appena mappato, attraverso una msgbox.
---------------------------------------mov eax, [vxdReturn]
mov ebx, eax
add ebx, [eax]
add eax, [eax+4];Copio le nuove stringhe nel blocco
mov ecx, 22
mov esi, offset client
mov edi, ebx
rep movsb---------------------------------------
modifico le stringhe che sono le blocco, per
vedere se gli effetti si riflettono anche sul
Server.
---------------------------------------chiudi:
Call CloseVxDexit:
push LARGE-1
call ExitProcess ;fine programma!mess:
Call MessageBox, 0, offset Testo, offset client,0
jmp exit
---------------------------------------
Chiudo il VxD ed esco dal programma.
-----------------------------------------==[ IL VxD: RZVxd.ASM ]==----------------------------------------------------------
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 <'RINZE2 VXD '> ;Must be 16 chars
RINZERev EQU 00HRINZE_MAJOR_VERSION EQU 1
RINZE_MINOR_VERSION EQU 0ErrorCode 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_MAP_BLOCK
dd IPC_BLOCK_PRESENT
dd IPC_LEAVE_BLOCK
SourceAddress dd 0 ;linear address of the private address space; 0 se if no
;blocks are presents
DestAddress dd 0 ;linear address where the pages are mapped
HContext dd 0 ;context handle of the Server
SizeAddress dd 0 ;Size of the block in unit of 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
retEndProc 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 NEARControl_Dispatch SYS_DYNAMIC_DEVICE_INIT, RINZE_Device_Init
Control_Dispatch SYS_DYNAMIC_DEVICE_EXIT, RINZE_Device_Exit
Control_Dispatch W32_DEVICEIOCONTROL, RINZE_ioctl
clc
retRINZE_Control ENDP
---------------------------------------
Dispatcher per i messaggi mandati al vxd, rimanda
a RINZE_Device_Init, RINZE_Device_Exit, RINZE_ioctl
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, infatti 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
mov eax, [esi].lpvInBuffer ; Parameter
mov eax,[eax]
mov ebx,[eax] ; linear address of the buffer that we can map in processes
mov [SourceAddress], ebx
mov ecx,[eax+4] ; size in 4kb units
mov [SizeAddress],ecx ;save the size of the block
VmmCall _GetCurrentContext < >
mov [HContext],eaxmov eax,1 ;All ok
mov ebx, [esi].lpvOutBuffer
mov dword ptr [ebx], eaxjmp RetSuccess
---------------------------------------
Legge l'indirizzo lineare sorgente e la size del blocco e
lo memorizza in SourceAddress e SizeAddress. Infine
memorizza l'handle al context corrente in HContext e ritorna 1.
---------------------------------------IPC_MAP_BLOCK: ;*** servizio IPC_MAP_BLOCK
mov eax, [SourceAddress]
or eax, [SizeAddress] ;the block exists??
jz Err
mov ecx, [SizeAddress]
;reserve the page in private arena
VMMCall _PageReserve < PR_PRIVATE, ecx, PR_FIXED >
cmp eax, -1
jz Err
push eax ;save the address where i want to map
mov ecx, [SourceAddress]
shr eax, 12
shr ecx, 12
mov ebx, [HContext]
mov edx, [SizeAddress]
VMMCall _PageAttach < ecx, ebx, eax, edx > ;the last parameter is npages
;not documented in ddk!!!!
pop edx ;restore the private Linear Address to the block
cmp eax, 1
jnz Err
mov ebx, [esi].lpvOutBuffer
mov [ebx], edxjmp RetSuccess
Err: mov eax,0
mov ebx, [esi].lpvOutBuffer
mov [ebx], eax
jmp RetSuccess---------------------------------------
Controllo che esiste un blocco da mappare, quindi
riservo SizeAddress pagine nello spazio di indirizzamento
privato del processo. Infine mappo le pagine dal processo
sorgente in quello corrente.
NB: prima di mappare le pagine in processo bisogna riservarle,
esse cmq non devono essere committed solo reserved.
---------------------------------------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 RetSuccessRetSuccess: ; All Ok!!
xor eax, eax ;return zero = success
clc
ret
---------------------------------------
Restituisce 0 se esiste un blocco da mappare
1 altrimenti!
---------------------------------------IPC_LEAVE_BLOCK: ;*** servizio IPC_LEAVE_BLOCK
mov [SourceAddress],0
mov [SizeAddress],0
jz RetSuccessRetSuccess: ; All Ok!!
xor eax, eax ;return zero = success
clc
ret
---------------------------------------
Il servizio elimina l'indirizzo lineare del blocco
da mapprae con la conseguente impossibilità di mapparlo
in un'altro processo.
---------------------------------------
EndProc RINZE_ioctl
Public RINZE_Device_Exit
BeginProc RINZE_Device_Exitclc
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
retEndProc RINZE_Device_Init
---------------------------------------
non usato!!!!!
---------------------------------------
VXD_ICODE_ENDSend
Fine VXD!!!!!!!!
--==[ CONCLUSIONI ]==----------------------------------------------------------------
Questo è il secondo e penso ultimo metodo di IPC tramite Vxd che presento (non me ne vengono in mente altri :P ). Tiriamo un pò le somme su i due metodi:
- il primo non faceva altro che crearsi un alias globale delle pagine da condividere.
Quindi restituiva al client l'indirizzo lineare al blocco ed un selettore ad un
descrittore di segmento dati avente come base address l'address del blocco stesso.
- il secondo invece mappa direttamente il blocco nell'address space del processo.La principale differenza tra i due metodi è che il primo lavora nell'area shared, mentre il secondo gioca direttamente con l'address space privato dei processi. Il primo è il metodo più rapido per accedere ad una pagina privata di un processo da un qualsiasi contesto, il secondo invece può essere utile se stiamo lavorando sui dati di un'altro processo e vogliamo essere sicuri che nessun'altro processo li possa modificare. In effetti il primo metodo mappando le pagine nell'area shared è comunque indifeso dagli attachi di altri processi che possono scriverci sù (senza nemmeno dover usare WriteProcessMemory o trucchetti del genere, ma semplicemente con una mov [address], registro :P). Il secondo metodo io lo preferisco soprattuto per questo e comunque ha dei vantaggi rispetto all'uso di WriteProcessMemory. Si pensi ad un process patcher od un trainer, che si mappi le pagine da modificare di un processo target nel proprio address space... le modifiche le farebbe come se stesse lavorando con i propri dati... altro che WriteProcessMemory!!!!! In particolare nei trainer in cui spesso si cambia ad intervalli regolari una determinata locazione (ad esempio l'energia del nostro eroe :D ) usando questo metodo anzicchè WriteProcessMemory saranno molto + efficienti e le prestazioni del gioco ne risentiranno notevolmente... in maniera positiva ovviamente!
In conclusione penso che questi 2 metodi di IPC possano essere un valido aiuto a chi vuole andare più a fondo nella conoscenza di Win9x. In particolare in questi tut è stato visto come da ring 0 è possibile:
- Riservare pagine di memoria
- fare il commit di queste pagine (aka renderle realmente utilizzabili!)
- crearsi un descrittore di segmento
- mappare delle pagina in un'area shared
- mappare delle pagine di un processo in un'altroBeh direi che tutto sommato qualcosa ho spiegato in questi tut, no??
--==[ ULTIMA NOTA ]==----------------------------------------------------------------
Ho fatto del mio meglio per spiegare il tutto nel modo più semplice e conciso possibile, cmq se avete ancora qualke dubbio l'unica cosa da fare è leggersi la documentazione del DDK.
Per quanto riguarda i src, compilate i programmi Server e Client con Tasm 5.x e RZvxd con Masm 6.1x.--==[ I SALUTI!!! ORDER: AD CAZZUM ]==-----------------------------------------------
Insanity: anke se non fai + parte del gruppo potresti farti vedere ogni tanto, no??:D
D4eMoN: Ke czzzz di fine hai fatto??? ti 6 sposato?
Kill3xx: il mito vivente! Secondo me è parente di Pietrek :P
NeuRal_NoiSE: ormai è diventato un guru! Neural_Guru :)
Ah czz.. dimenticavo è il + "pazzo" del gruppo :-) quando mi vieni a trovare?
YanOrel: Volete qualcuno che vi tenga informati su tutto? avete trovato il tipo
giusto!
T3X: Ora è BoTmAsTeR.... ha 700 bot nel chan.. e non sono nemmeno suoi :-D
KRY0: Quando esce il tuo tut su VB & Wdasm??
XoANINO: beh ke dire di lui è.... csoa... no additional information at this time :-;
Along3x: alle prese con la maturità... pooraccio :D
Suby: il mio win95 beta tester :)) non credevi che cambiavo i msgbox!?! eheh?
+Malattia: dopo l'hack IT è scomparso... subito dopo aver conosciuto neu..
non ha retto all'emozione :)
Marcus: è tornato... e se n'è riandato... bah il militare fà male!
Furb3t: non ti becco mai in irc... mi devi spiegà una cosa...
Pusillus: è una vita che non ci sentiamo... czzzz
Alor: ummm....ummmmm... ummmm... ummm.. un'altro che non lo becco da tempo :(
MetalheaD: MP3!!!! ti dice qualkosa??? e torna tra i non morti ogni tanto.. no??Infine saluto tutti gli amici di #crack-it ed in maniera particolare tutti i members dei RingZer0 (così non faccio un figura di m. con quelli di cui mi sò dimenticato!).