Articol cum se creează invoca

Cum se creează invoca

Aceasta este o scurtă trecere în revistă a modului de creare a unei biblioteci de import care poate fi utilizată împreună cu MASM. Vă sugerez să știți deja ceva despre bibliotecile de import, adică știi că este așa și așa mai departe. Voi face un efort pentru a genera biblioteci de import compatibile cu MASM.

Formatul bibliotecilor interpretului MASM

MASM și Visual C ++ pot folosi aceleași biblioteci de import, ceea ce este foarte convenabil. Importarea bibliotecii Mikrosoft folosește o varietate de formate COFF, care diferă de formatul OMF utilizat de TASM. Din acest motiv, TASM nu poate folosi bibliotecile MASM'ovskie importe și invers. Nu voi intra în detaliile construcției acestor biblioteci. Este suficient să spunem că fiecare bibliotecă de import Microsoft conține informații despre funcții din anumite DLL-uri. Această informație include numele funcțiilor și dimensiunea totală a parametrilor parcurși funcțiilor. Dacă navigați cu kernel32.lib utilizând un hex editor, veți găsi următoarele:

Numele funcțiilor au un prefix "-". Numărul următor @ reprezintă dimensiunea totală a parametrilor acestei funcții în octeți. ExitProcess acceptă doar un singur parametru dword, deci acest număr este egal cu 4. De ce sunt incluse informații despre dimensiunea parametrilor? Aceste informații sunt utilizate de MASM pentru a verifica corectitudinea parametrilor de funcții specificați, atunci când se numește folosind cuvântul cheie "invoca". Dacă shove PARAMETRI pposto INSTRUCTIUNI coș de fum „push“ și începe instrucțiunea funcția este „apel“, MASM nu va verifică ppavilnost parametrilor. Ea ppeimuschestvo face imposibilă crearea unor biblioteci MASM de import în DLL, astfel încât DLL nu este corectă Conține infopmatsii de paapmetpov pazmepe, funcția pepedavaemyh.

Crearea bibliotecilor importului MASM din DLL

Dacă sunteți gata să utilizați funcțiile cu "push" și "call", puteți crea o bibliotecă de import din orice DLL cu următoarele.

Utilizați dumpbin.exe, care vine cu Visual C ++ pentru a obține numele funcțiilor DLL care urmează să fie expuse.

Dumpbin / EXPORTS blah.dll> output.txt

După ce obțineți lista de funcții, creați un modul pentru a determina utilizarea fișierului. De exemplu, dacă DLL conține o singură funcție, GetSomeLine, tastați următoarele:

Biblioteca bla
EXPORTURI
GetSomeLine

Și salvați ca blah.def.
Rulați lib.exe pentru a crea biblioteca de import din modulul de definiție a fișierului:

Asta e tot. Ai blah.lib, pe care îl poți folosi cu MASM, până când trebuie să folosești 'invoke'.

Crearea bibliotecilor de biblioteci invocate

Sunt unul dintre cei care sunt foarte reticenți în a folosi abordarea de mai sus. Utilizați invoca gorado este mai convenabil. Acesta este unul dintre motivele pentru care prefer MASM TASM'u. Dar așa cum sa spus mai devreme, este aproape imposibil să creați o bibliotecă invocabilă a importului utilizând aceeași procedură descrisă mai sus. De exemplu, puteți decide că dacă modificați numele funcțiilor într-un fișier .def pentru a include "; xxx", biblioteca de import poate construi așa cum ar trebui. Crede-mă. Nu va funcționa.

Cea mai ușoară modalitate de a crea o bibliotecă de importuri accesibile invocării este utilizarea MASM-ului în sine. Dacă creați un DLL, atunci descoperiți că împreună cu el aveți biblioteca de import, care va fi complet invocabilă! Strategia noastră este după cum urmează:
  • Obținem informații despre numele funcțiilor și dimensiunea generală a parametrilor.
  • Creăm codul sursă DLL, care va include aceste funcții cu numărul și dimensiunea corectă a argumentelor.
  • Creăm fișierul de definiție a modulului, în care expunem funcțiile corespunzătoare.
  • Asamblați codul sursă asm ca proiect DLL.

Asta e tot. Veți primi o bibliotecă MASM pe deplin funcțională. Pașii de mai sus merită o explicație mai detaliată.

Obținerea numelor funcțiilor și mărimea totală a parametrilor

Aceasta este cea mai dificilă parte a procesului. Dacă aveți doar un DLL, veți avea un inconvenient obositor. Mai jos sunt descrise mai multe metode, pe care le puteți utiliza, deși niciuna dintre ele nu oferă o garanție de 100%.

Utilizați dezasamblarea interactivă (IDA) pentru a dezasambla DLL-ul. Cu ajutorul acestui instrument minunat puteți obține dimensiunea completă a parametrilor acceptați de funcție. Cu toate acestea, aceasta nu este cea mai bună cale. IDA este un dezasamblator consumator, dar uneori numai o persoană poate decide ce este. Va trebui să gândiți și să dezvoltați întreaga listă.

Urmăriți valoarea indicelui în stivă înainte și după apelarea tuturor funcțiilor din DLL. Metoda este după cum urmează:
  • Obțineți adresele funcțiilor utilizând GetProcAddress.
  • Apelați fiecare funcție fără a trimite parametrii prin stivă. Rețineți valoarea esp înainte de apel.
  • Când funcția returnează un control, comparați valoarea esp după apel cu ceea ce a fost înainte de apel. Motivul este aici: atunci când treceți parametrii în formatul stdcall, funcția își asumă responsabilitatea pentru menținerea echilibrului. Diferența dintre valorile esp și dimensiunea parametrilor așteptați de funcție.

Din păcate, această metodă nu este impecabilă. Este posibil să nu reușească în următoarele situații.
  • Dacă funcțiile din DLL folosesc celălalt parametru de trecere a parametrilor, altele decât stdcall sau pascal.
  • Dacă funcția nu reușește să elibereze coșul, de exemplu, dacă apare o excepție.
  • Dacă funcțiile care ne interesează servesc ceva periculos, de exemplu, pentru formatarea șurubului (Upasi Lord!)

Examinați programele existente care utilizează DLL-ul corect. Puteți depana / dezasambla aceste programe pentru a vedea numărul și mărimea parametrilor parcurși funcțiilor din DLL. Cu toate acestea, dacă există funcții în DLL care nu sunt utilizate în niciunul dintre programele disponibile pentru dvs., această metodă nu va funcționa.

Crearea unei surse DLL, care va conține toate aceste funcții

După ce obțineți numele funcțiilor și mărimea parametrilor lor, cea mai tragică va fi în urmă. Va trebui să creați o funcție DLL și să scrieți aceleași nume ca în DLL. De exemplu, există o singură funcție în DLL, GetSomeLine, care obține parametrii de 16 octeți. În sursă, completați următoarele rânduri:

386
.model plat, stdcall
.cod
GetSomeLine proc param1: DWORD, param2: DWORD, param3: DWORD, param4: DWORD
GetSomeline endp
capăt


Puteți să întrebați ce este? Procedură, în care nu există o singură instrucțiune? Biblioteca de import nu conține nicio informație despre ce ar trebui să facă funcția. Singurul său scop este de a furniza informații despre numele funcțiilor și parametrii acestora. Prin urmare, nu este necesar să plasăm instrucțiuni în procedură - necompletate. Totuși, vom șterge DLL-ul inutil după montaj. Tot ce vrem este să amestecăm informațiile despre codul sursă cu privire la numele funcțiilor și mărimea parametrilor, astfel încât MASM să genereze biblioteca importului. Dimensiunea fiecărui parametru individual nu este importantă. Pentru informațiile dvs., MASM tratează întotdeauna fiecare parametru ca DWORD, indiferent de modificatorul de dimensiune pe care l-ați setat. De exemplu, putem face acest lucru:

386
.model plat, stdcall
.cod
GetSomeLine proc param1: BYTE, param2: BYTE, param3: BYTE, param4: BYTE
GetSomeline endp
capăt

Și MASM va crea în bibliotecă importul '_GetSomeLine @ 16'.

Crearea fișierului de definiție a modulului

Acesta este un proces simplu. Veți avea nevoie de acest fișier, că MASM ar putea genera un DLL și o bibliotecă de import. Fișierul șablon pentru definiția modulului este după cum urmează:

BIBLIOTECA
EXPORTURI


Trebuie să specificați numele DLL-ului, care va fi identic cu numele bibliotecii de import, apoi introduceți numele funcțiilor după comanda EXPORTS, un nume de funcție pe fiecare linie. Salvați fișierul și veți obține fișierul de lucru al definiției modulului.

Asamblarea codului sursă ca proiect DLL

Ultimul pas este cel mai simplu. Veți avea nevoie de ml.exe și link.exe.

ml / c / coff / Cp bla.asm
link / DLL / NOENTRY /def:blah.def / subsistem: windows blah.obj

Și veți primi o bibliotecă de bibliotecă invocată.

Expunerea uscată de mai sus poate să nu fie pe deplin înțeleasă. Cred în învățarea prin acțiune. Prin urmare, am făcut exemplul care demonstrează cele de mai sus. Fișierele incluse în exemplu sunt:

Codul sursă din asamblare, care conține toate funcțiile din kernel32.dll (documentat).
Fișier definiție fișier.
Un fișier batch, pe care îl puteți utiliza pentru a compila biblioteca de import.
Compilați exemplul, veți obține kernel32.lib, pe care îl puteți utiliza în loc de cel furnizat de Microsoft.

Dacă doriți să adăugați / eliminați funcții de la / către o anumită bibliotecă de import, puteți utiliza două utilitare simple scrise de mine. De exemplu, dacă doriți să adăugați funcții nedocumentate la kernel32.lib, aceste programe vă vor fi utile.

Extrage nume și mărimi corespunzătoare din orice bibliotecă de import. Porniți-l și va procesa toate bibliotecile care se află în același director. Fișierele de ieșire vor avea .icz. Conținutul lor va arăta astfel:

_ExitProcess @ 4
_ExitThread @ 4
_ExitVDM @ 8
_ExpandEnvironmentStringsA @ 12
_ExpandEnvironmentStringsW @ 12 @ 12


Dacă doriți să adăugați o funcție, trebuie doar să introduceți un nume nou (prin adăugarea de caractere "_") și dimensiunea totală a parametrilor. Dacă funcția este exponentiată printr-o ordinală, atunci numele trebuie setat la @xx. "xx" va fi ordinală. Rețineți că acest utilitar simplu nu verifică numele pentru repetare, deoarece în unele biblioteci de import pot fi repetate numele.

Acest utilitar acceptă fișierele generate de Lib2Def și creează o bibliotecă de import de la acestea. Acesta va procesa toate fișierele cu extensia .icz. Pentru informațiile dvs., analizează liniile fișierului .icz și creează .asm și .def din ele. Apoi se numește ml.exe și link.exe astfel încât să genereze biblioteca de import. .obj fișiere. asm. exp și .dll sunt eliminate și rămâne doar .lib. Dacă acest utilitar nu poate genera fișierul .lib, verificați dacă există linii repetate în fișierul .icz: acesta este cel mai frecvent caz.

Articole similare