Metode de interceptare a apelurilor api în win32

Interceptarea funcțiilor de sistem ale sistemului de operare este o tehnică cunoscută de mult timp în urmă. De obicei, o anumită funcție a sistemului este interceptată pentru a-și monitoriza sau schimba comportamentul. În momentul DOS, programatorii au interceptat întreruperi de software (int 21h, int 16h, int 10h). Odată cu sosirea Win16, au fost necesare unelte pentru a intercepta funcțiile API. Și, în sfârșit, odată cu apariția Win32, instrumentele de interceptare au evoluat din nou, adaptându-se la noul sistem. Sistemele de operare ale familiei Windows nu au conținut niciodată instrumente încorporate special concepute pentru a intercepta funcțiile sistemului. Și este clar de ce - este încă un pic hacking. Prin urmare, interceptarea este de obicei efectuată prin "mijloace improvizate", iar pentru implementarea acesteia este necesar să se prezinte în mod clar multe aspecte profunde ale dispozitivului și funcționarea sistemului de operare.







Caracteristicile organizării memoriei în Windows

Deoarece interceptarea este aproape întotdeauna asociată cu o modificare a memoriei (sau funcțiile de cod de interceptare sau tabele de import / export), pentru punerea sa în aplicare trebuie să ia în considerare caracteristicile arhitecturii și memoria WinNT Win9x.

  • Cei mai tineri de doi gigabytes (00400000-7FFFFFFF) - cod și date ale user-mode (în intervalul 00000000-003FFFFF aranjate secțiuni pentru detectarea de indicii nule, precum și pentru compatibilitate cu programele DOS și Win16);
  • Al treilea gigabyte este pentru fișiere partajate proiectate în memorie (MMF) și DLL-uri de sistem.
  • Al patrulea gigabyte - pentru codul și datele din modul kernel (aici este nucleul sistemului de operare și al driverelor).

Toate aceste diferențe afectează în mod semnificativ modurile de implementare a intercepției funcțiilor localizate în DLL-urile de sistem.

Intercepțiile pot fi împărțite în două tipuri: interceptarea locală (într-un singur proces) și globală (la scară globală).

Interceptarea locală

Interceptarea locală utilizând partiția de import

La punerea în aplicare această metodă ar trebui să se țină seama de faptul că DllMain apelurile din bibliotecă în care funcția interceptat, intercepta nu. Acest lucru se datorează faptului că interceptarea se poate face numai după punerea în aplicare a LoadLibrary, dar de data aceasta deja DllMain se numește. Desigur, puteți scrie versiunea dvs. de LoadLibrary (DLL descărcăm exemple de „manual“ acolo) și intercepta între încărcarea DLL și apelați DllMain, dar complică foarte mult sarcina.

Principalul avantaj al acestei metode este că este implementat la fel în Win9X și WinNT.

În Windows NT, funcțiile Module32First și Module32Next nu sunt implementate și, pentru a enumera modulele procesului, ele vor trebui să utilizeze funcțiile din PSAPI.dll în schimb.

Interceptarea locală prin schimbarea funcției interceptate (numai WinNT)

Există multe exemple ale acestei metode. Voi lua în considerare metoda oferită de biblioteca Microsoft - Detours.

Detours este prima bibliotecă oficială concepută pentru a intercepta funcțiile (nu numai sistemul, ci și orice altele). Conceptele de bază ale Detours sunt:

  • funcția țintă (funcție) - o funcție care este interceptată;
  • funcția interceptor (funcția de ocolire) - funcție, înlocuirea interceptată;
  • funcția de trambulină (funcție de trambulină) - o funcție constând din antetul funcției obiectiv și comanda pentru a merge la restul codului funcției țintă.

Trambulina este tradusă din limba engleză - "trambulină", ​​însă expresia "funcția-traversă" exprimă cu mai multă precizie logica muncii sale.

Astfel, dacă funcția țintă are următoarea antet:

DETOUR_TRAMPOLINE DetourFunction și funcția macro includ dezasamblor foaie de calcul care determină modul în care trebuie să fie copiat în rampă de lansare-funcția (nu mai puțin de 5 octeți (JMP mărimea echipei) care constituie instrucțiuni procesorul întreg de) octeți ai multe antetul funcției obiectiv încorporat. Dacă funcția țintă durează mai puțin de 5 octeți, interceptarea eșuează.

În momentul capturării / eliminării intercepției, este necesar să se oprească toate celelalte fire ale procesului în care are loc interceptarea (sau să se asigure că nu pot apela funcția interceptată).

Principalul dezavantaj al acestei metode este viteza extrem de scăzută (tratarea excepțiilor în Windows durează destul de mult timp). În plus, prezența unui handler de excepție în procesul interceptat va duce la faptul că această metodă nu va funcționa. De asemenea, această metodă nu va funcționa în cadrul programului de depanare.

Interceptarea globală

Interceptarea globală poate fi implementată în diverse moduri. Prima metodă este de a aplica o interceptare locală tuturor aplicațiilor din sistem (începute în momentul interceptării sau mai târziu). A doua modalitate - "hacking-ul sistemului" - implică înlocuirea codului funcției interceptate direct în fișierul DLL sau imaginea acestuia în memorie.

Interceptarea globală prin metoda interceptării locale totale

Această metodă se bazează pe următoarele: dacă puteți intercepta o funcție din procesul curent, trebuie să executați codul de interceptare în toate procesele din sistem. Există mai multe metode pentru a determina pe altcineva să execute un cod de interceptare. Cel mai simplu lucru este să faceți acest cod în DllMain a unei anumite biblioteci și apoi să îl introduceți în procesul altcuiva. Există, de asemenea, mai multe metode pentru implementarea unui DLL (a se vedea Jeffrey Richter). Cea mai ușoară lucrare în Win9X și în WinNT - introducerea DLL cu ajutorul capcanelor. El a realizat: sistemul este instalat capcana (folosind funcția SetWindowsHookEx) de tip WH_GETMESSAGE (această capcană este de a intercepta mesaje pentru Windows). În acest caz, modulul în care capcana este conectat automat la fluxul specificat în ultimul SetWindowsHookEx argument (dacă specificați 0, conexiunea se face la toate fluxurile din sistem). Cu toate acestea, conexiunea nu are loc imediat, dar înainte ca orice mesaj să fie trimis în coada de mesaje de flux. Prin urmare, interceptarea nu se efectuează imediat după pornirea aplicației, dar înainte de procesul de procesare a primului mesaj. Deci, toate apelurile către funcția interceptată nu vor fi interceptate înainte de procesarea primului mesaj. Iar în aplicațiile fără cozi de mesaje (de exemplu, cele de consolă) acest mod de implementare nu funcționează deloc.







Am scris un exemplu care implementează captura globală a funcției GetDriveTypeA folosind injectarea DLL folosind capcane și interceptarea utilizând secțiunea de import.

Funcția GetDriveTypeA din biblioteca kernel32.dll este folosită de programele Windows pentru a determina tipul de disc (local, CD-ROM, rețea, virtual, etc.). Are prototipul următor:

lpRootPathName este calea către disc (A: \, B: \, etc.)

GetDriveTypeA returnează una dintre următoarele valori:

Interceptarea acestei funcții vă permite să "trimiți" programele Windows prin redefinirea valorii returnate de această funcție pentru orice disc.

Programul DriveType2 este format din două module: DriveType2.exe și DT2lib.dll.

DriveType2.exe implementează interfața și toate lucrările sunt realizate în DT2lib.dll.

Proiectul DT2lib este format din trei fișiere principale:

APIHook.cpp - acest fișier a fost scris de Jeffrey Richter (cu excepția unor corecții făcute de mine, le voi descrie mai jos). Acest fișier descrie clasa CAPIHook, care implementează interceptarea unei funcții API date în toate modulele procesului curent. Aici, funcțiile LoadLibraryA, LoadLibraryW, LoadLibraryExA, LoadLibraryExW și GetProcAddress sunt interceptate automat.

Toolhelp.h - acest fișier este scris și de Jeffrey Richter. Descrie clasa CToolhelp, care implementează un apel la funcțiile toolhelp de sistem. În acest caz, este folosit de clasa CAPIHook pentru a enumera toate modulele conectate la proces.

DT2Lib.cpp - în acest dosar, am realizat funcția de interceptare GetDriveTypeA folosind clasa CAPIHook, precum și tipul de instalare capcana WH_GETMESSAGE, care oferă o conexiune a modulului (DT2lib.dll) tuturor fluxurilor din sistem.

Cum are loc interceptarea?

Imediat după pornirea DriveType2.exe, este apelată funcția DT2_HookAllApps din DT2lib.dll, care stabilește capcana.

După conectarea DLL-ului la fir, toate variabilele sunt inițializate (fiecare proces în care DLL-ul este conectat are copii ale tuturor variabilelor globale și statice descrise în el). Dintre variabilele globale avem 6 instanțe ale clasei CAPIHook (pentru GetDriveTypeA în DT2Lib.cpp și LoadLibraryA, LoadLibraryW, LoadLibraryExA, LoadLibraryExW și GetProcAddress - în APIHook.cpp). Astfel, atunci când conectarea DLL are loc de șase ori mai numesc CAPIHook clasa constructor pentru a intercepta funcțiile de mai sus, în curent (adică, de fapt, legătură cu care au avut loc doar) de proces.

La sfârșitul procesului, DLL-ul încorporat este dezactivat. Aceasta numește destructorul CAPIHook pentru toate instanțele clasei.

Această funcție va fi apelată de fiecare dată când acest modul accesează GetDriveTypeA.

Funcția Hook_GetDriveTypeA numește inițial GetDriveTypeA original. Apoi, în cazul în care valoarea returnată este mai mare decât DRIVE_NO_ROOT_DIR (de exemplu, funcția corectă a argumentului, și este executat fără eroare a fost transferată), se verifică dacă discul este suprascrisă, al cărui tip este solicitat. Informații despre valorile funcțiilor interceptate în acest caz, sunt stocate în realizate mine matrice BYTE Drives [26], ceea ce permite interceptarea a 26 unități de la A: la valorile stocate Z. a revenit funcția GetDriveTypeA în matrice pentru fiecare dintre unități. Deci, în cazul în care valoarea elementului matrice care corespunde GetDriveTypeA argument egal 0xFF, atunci valoarea returnată este neschimbată, în caz contrar returnează valoarea de matrice. Scrierea valorilor la această matrice este implementată în DriveType2.cpp.

Dacă doriți ca acest program să funcționeze pe deplin în WinNT, ar trebui să apucați și funcția GetDriveTypeW.

Această metodă are un alt dezavantaj: unele programe comerciale (de exemplu, un manager de fișiere populare Total Commander, ambalat ASPack) folosesc diferite sisteme de protecție (ASProtect, VBox, etc ...), cifrarea tabelul de import a cererii protejate. Cu astfel de programe această metodă nu funcționează.

Interceptarea globală poate fi implementată cu ajutorul Detours (numai în WinNT). Deoarece există mai multe metode cunoscute de implementare a DLL, este posibil să se ofere o varietate de opțiuni diferite pentru implementarea unei intercepții globale.

Interceptarea globală prin substituirea codului în DLL

Această metodă poate fi implementată în două moduri: editarea directă a codului pentru DLL, care este funcția obiectiv, sau înlocuirea unui alt DLL exportator același set facilitate. Cea de-a doua metodă este cunoscută sub numele de "Înlocuirea prin utilizarea învelitorilor".

Prima metodă vă permite să implementați doar funcții interceptoare relativ mici, deoarece codul trebuie să fie încorporat în zone libere DLL - în special în spațiul de intersecție. Un alt dezavantaj este că codul trebuie scris în asamblare. Ideologia generală a lucrării acestei metode este aceeași ca în Detours. În codul funcției țintă, comanda jmp la funcția de interceptor este implementată. Bytes copiat „de sub“ jmp'a, sa mutat la interceptor (ca separatorului este încă scris în limbaj de asamblare, în acest caz, este mai ușor să se combine cu dreapta-trambulină). Iată un exemplu de implementare a acestei metode.

Directorul DriveType0 conține fișierul kernel32.dll, în care am făcut următoarele remedii (utilizând hiew32.exe):

Astfel, atunci când LED-ul nu este aprins ScrollLock, funcția GetDriveTypeA funcționează ca de obicei, dar dacă există o - ceva pentru toate aplicațiile bazate pe Windows toate unitățile locale (a mea este C: \ și D: \) sunt convertite la CD-ROM-uri.

Pentru ca toate acestea să funcționeze, trebuie să înlocuiți fișierul C: \ Windows \ System \ Kernel32.dll la fișierul kernel32.dll DriveType0 \. Acest lucru poate fi făcut, trebuie doar să porniți computerul în modul MS-DOS, ca kernel32.dll - una dintre bibliotecile de sistem Windows. Acest exemplu este pus în aplicare pentru Windows 98. Deoarece bibliotecile de sistem variază în funcție de versiunea de Windows (chiar și numărul de a construi), apoi în alte sisteme de operare, acest exemplu nu va funcționa (ar trebui să fie puse în aplicare pentru fiecare versiune a kernel32.dll din nou).

Această metodă de interceptare este una dintre cele mai puternice. Cu toate acestea, nu va fi posibil să-l utilizați în produse comerciale, deoarece evident că încalcă aproape orice acord de licență.

O altă modalitate de a implementa această metodă este de a utiliza învelitori. Esența sa este de a crea propriul DLL cu același set de funcții exportate ca și cel original. De exemplu, pot cita următoarea implementare a exemplului de mai sus:

În acest caz, funcția interceptor poate apela funcția originală din kernel31.dll.

Principalul dezavantaj al acestei metode este că nu este potrivit pentru variabilele exportatoare DLL.

Interceptarea globală prin metoda de substituire a codului DLL în memorie (numai Win9X)

Exemplul DriveType1 este format din două părți - drivere DTDrv.sys și script-ul de instalare DTDrv.inf, precum și programul DriveType.exe.

DriveType.exe este compilat dintr-un singur modul DriveType.cpp, care implementează interfața cu utilizatorul și interfața cu driverul. Interfața cu driver-ul este implementată prin intermediul funcțiilor CreateFile (deschiderea driverului), DeviceIoControl (operații I / O) și CloseHandle (închiderea driverului). Pus în aplicare patru comenzi numite prin DeviceIoControl - funcția GetDriveTypeA interceptarea, îndepărtarea de interceptare, stabilind valoarea de returnare a funcției de interceptare pentru fiecare disc A. Z. citește starea curentă de interceptare.

Principalele variabile utilizate de DriveType.cpp sunt:







Articole similare

Trimiteți-le prietenilor: