| |
|
|
- Seite 1 - |
|
Frank Abbing | Ein kleines Tool von mir auf API-Hooking Basis. In einer Listbox werden alle Dlls aufgelistest, die gerade von Programmen geladen wurden.
Einfach Exe starten und dann irgendwelche Programme starten. Deren Dlls sollten jetzt gelistet werden und es pieps kurz. Bitte testet mal, ob es noch irgendwo hakt. |
|
|
| |
|
|
| |
|
- Seite 4 - |
|
|
RGH | He, he, Frank, das war ja auch eher als Gag gedacht.
Beides hat halt seine Vorteile: dynamisches oder statisches Linken.
Und ich widerspreche ja nicht, daß statisches Linken schneller ist. Der Hauptgrund dafür ist aber, daß beim dynamischen Linken vor dem Call eben ein GetProcAdress notwendig ist, daß beim statischen linken wegfällt. (Das ist ja auch ein Grund, weshalb, die OpenGL-DLLs für die XProfan-eigene OGL-Funktion in XProfan statisch gelinkt sind. Das ging natürlich nur, weil jede XProfan-fähige Windowsversion OpenGL unterstützt.)
Beides läßt sich auch mit XProfan programmieren: KompilierenMarkierenSeparieren $H Windows.ph WindowsHeaderdatei nutzen
Declare hDLL&, Time&, Text$
hDLL& = @UseDLL(USER32.DLL)
Print Dynamisches Linken mit DEF: ;
Def GetWText(3) !User32.dll, GetWindowTextA
Text$ = @Space$(40)
Time& = &GetTickCount
whileLoop 1, 100000
GetWText(%hWnd, @Addr(Text$), 40)
endwhile
print Int(&GetTickCount - Time&)
Print Dynamisches Linken mit EXTERNAL: ;
Text$ = @Space$(40)
Time& = &GetTickCount
whileLoop 1, 100000
External(User32.dll, GetWindowTextA, %hWnd, @Addr(Text$), 40)
endwhile
print Int(&GetTickCount - Time&)
Print Dynamisches Linken mit Header-Datei: ;
Text$ = @Space$(40)
Time& = &GetTickCount
whileLoop 1, 100000
~GetWindowText(%hWnd, @Addr(Text$), 40)
endwhile
print Int(&GetTickCount - Time&)
Print Statisches Linken: ;
Declare GetWText&
GetWText& = ~GetProcAddress(hDLL&, GetWindowTextA)
Text$ = @Space$(40)
Time& = &GetTickCount
whileLoop 1, 100000
@Call(GetWText&, %hWnd, @Addr(Text$), 40)
endwhile
print Int(&GetTickCount - Time&)
waitinput
end
Um das statische Linken zu vereinfachen, könnte man natürlich eine zusätzliche Funktion einbauen, etwa:
GetWText& = GetLibAddr(User32.DLL, GetWindowTextA)
Gruß Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 27.03.2007 ▲ |
|
|
|
|
RGH | Andreas Hötker
Ich könnte mir vorstellen, dass da GetProcAdress unter Umständen viel mehr Zeit verbraucht.
Sag ich doch!
Zwei ..., ein Gedanke!
Gruß Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 27.03.2007 ▲ |
|
|
|
|
| Was ich damit sagen wollte: Wenn ich das im Augenblick richtig sehe, teilt Windows die Handles in verschiedene Kathegorien auf - und speichert die auch unterschiedlich ab (Kernel-, GDI-, Userhandles...). Handles auf geladene DLLs wirst du nicht unter den Kernelhandles finden; die werden also (genau so wie Handles auf Speicherbereiche) gesondert behandelt. Wenn ich das richtig sehe, müssen aber bei GetProcAdress unter Umständen bis zu 1000 verschiedene Pointer durchgesehen werden... |
|
|
| |
|
|
|
RGH | |
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 27.03.2007 ▲ |
|
|
|
|
Frank Abbing |
Als Untermauerung der Vermutung, daß ~GetProcAdress mehr Zeit kostet:
Oooch Roland. Hast aber nicht beachtet, das man im Programm GetProcAdress() pro Funktion nur EINMAL benutzen muss. Zum Speichern der Adresse genügt dann eine simple Variable. Dein Code geht ganz am Thema vorbei, sodass dein Vergleich mächtig hinkt...
Wenn ich das im Augenblick richtig sehe, teilt Windows die Handles in verschiedene Kathegorien auf - und speichert die auch unterschiedlich ab (Kernel-, GDI-, Userhandles...). Handles auf geladene DLLs wirst du nicht unter den Kernelhandles finden; die werden also (genau so wie Handles auf Speicherbereiche) gesondert behandelt. Wenn ich das richtig sehe, müssen aber bei GetProcAdress unter Umständen bis zu 1000 verschiedene Pointer durchgesehen werden...
Ja, wenn du es richtig sehen würdest. Hast du dir den Quellcode mal angesehen? Ich hab reingesehen... Das hat damit aber rein gar nichts zu tun. Ich sagte bereits, GetProcAdress ist nur einmal pro Funktion nötig. Mit dieser Technik ist es nicht nötig Daueraufrufe zu produzieren, wie Roland es derzeit macht. Dass Profancodes effizienter ausgeführt werden können, zeigt XPSE mehr als deutlich. Hast du das auch mal getestet, Roland? Ich denke - nein. Hab deinen Code ein kleines bischen modifiziert und jetzt funktioniert er so, wie WhichDlls es dargelegt hat. Da sieht es rabenschwarz aus für deine Technik. Der Geschwindigkeitszuwachs mit statischer Adresse beträgt 100 Prozent, ist also doppelt so schnell... KompilierenMarkierenSeparieren hehe |
|
|
| |
|
|
|
| Das erinnert mich doch sehr an den xpse-Selbsttest: [...]
Ich finde das Zeigt schon sehr genau den Geschwindigkeitsunterschied.
Ich finde das XProfan von Haus aus diese xpseTechnik mitbringen sollte - und gebe Frank recht damit wenn er meinte das XProfan hier in den meisten Fällen völlig übertrieben und unnötig die Funktionsadresse jedes Mal neu ermittelt oder gar die DLL mit LoadLibrary laden will. Wofür soll das gut sein? |
|
|
| |
|
|
|
RGH | Frank Abbing
Oooch Roland. Hast aber nicht beachtet, das man im Programm GetProcAdress() pro Funktion nur EINMAL benutzen muss. Zum Speichern der Adresse genügt dann eine simple Variable.
Oooch Frank, hast Du nicht beachtet, daß mein erstes Programm GetProcAdress() auch nur einmal aufruft und das zweite nur dazu dient, den Zeitaufwand zwischen GetProcAdress() und LoadLibrary() zu vergleichen, um festzustellen, wer beim dynamischen Aufruf die Zeit verbrät?
Wenn ich in XProfan das dynamische Linken bevorzuge, dann muß ich die Adresse dann bestimmen, wenn die Funktion das erste Mal verwandt wird. Wenn sie dann an anderer Stelle im Programm wieder verwandt wird, muß ich sie wieder bestimmen oder ich müßte in einer Tabelle nachsehen, ob die bereits bekannt (und auch noch gültig) ist und sie dann verwenden. Das wäre zusätzlicher Verwaltungsaufwand.
Die andere Alternative ist die Umwandlung in einen statischen Aufruf, so wie es der XPSE (und mein obiges Beispiel) macht. Da das bei zeitkritischen Dingen Sinn machen kann, habe ich ja bereits vorgeschlagen, das in die nächste XProfan-Version als Alternative einzubauen. Wie gesagt: beide Varianten haben ihre Vor- und Nachteile.
Gruß Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 27.03.2007 ▲ |
|
|
|
|
Frank Abbing |
und das zweite nur dazu dient, den Zeitaufwand zwischen GetProcAdress() und LoadLibrary() zu vergleichen, um festzustellen, wer beim dynamischen Aufruf die Zeit verbrät?
Wie schon gesagt - am Thema vorbei.
Es liegt mir fern dir etwas vorschreiben zu wollen und ich mag solche Diskussionen auch gar nicht. Du hast hier eine Möglichkeit die Effizienz von XProfan noch zu steigern. Was du letztendlich daraus machst, und ob und wie du die Kritik deiner User umsetzt, ist deine Sache. |
|
|
| |
|
|
|
| Hallo Roland...
Mal zu deinem Code: Kann es sein, dass du da etwas mogelst? Usedll ist doch ein statischer Aufruf und GetProcAdress - wird das da nicht dynamisch aufgerufen??? |
|
|
| |
|
|
|
| Hallo Frank...
Hast du dir den Quellcode mal angesehen? Ich hab reingesehen... Das hat damit aber rein gar nichts zu tun.
Bin alles andere als ein Experte für ASM. Was mach der Code von GetProcAdress denn genau? Durchsucht der nicht den Table nach der angegebenen Funktion? Lerne gerne was dazu. |
|
|
| |
|
|
|
| Wo liegt der Denkfehler in folgendem Code: KompilierenMarkierenSeparieren $H Windows.ph WindowsHeaderdatei nutzen
Declare hDLL&, Time&, DLL$,LoadLibraryA&,GetProcAddress&,Funktion$,StringAddr&
LET DLL$=Kernel32.DLL
hDLL& = ~LoadLibraryA(@addr(DLL$))
LET Funktion$=GetProcAddress
LET GetProcAddress&=~GetProcAddress(hDLL&, @addr(Funktion$))
LET Funktion$=LoadLibraryA
LET LoadLibraryA&=~GetProcAddress(hDLL&, @addr(Funktion$))
LET DLL$=USER32.DLL
hDLL& = ~LoadLibraryA(@addr(DLL$))
Print Ohne irgendwas: ;
Time& = &GetTickCount
whileLoop 1, 100000
endwhile
print Int(&GetTickCount - Time&)
LET DLL$=$SYSPATH+USER32.DLL
Print LoadLibraryA +DLL$+ :;
StringAddr& = addr(DLL$)
Time& = &GetTickCount
whileLoop 1, 100000
call(LoadLibraryA&,StringAddr&)
endwhile
print Int(&GetTickCount - Time&)
LET DLL$=USER32
Print LoadLibraryA +DLL$+ :;
StringAddr& = addr(DLL$)
Time& = &GetTickCount
whileLoop 1, 100000
call(LoadLibraryA&,StringAddr&)
endwhile
print Int(&GetTickCount - Time&)
Print GetProcAdress ActivateKeyboardLayout: ;
Let Funktion$=ActivateKeyboardLayout
StringAddr& = addr(Funktion$)
Time& = &GetTickCount
whileLoop 1, 100000
call(GetProcAddress&,hDLL&, StringAddr&)
endwhile
print Int(&GetTickCount - Time&)
Print GetProcAdress wvsprintfW: ;
Let Funktion$=wvsprintfW
StringAddr& = addr(Funktion$)
Time& = &GetTickCount
whileLoop 1, 100000
call(GetProcAddress&,hDLL&, StringAddr&)
endwhile
print Int(&GetTickCount - Time&)
waitinput
end
|
|
|
| |
|
|
|
RGH | Andreas Hötker
Was mach der Code von GetProcAdress denn genau? Durchsucht der nicht den Table nach der angegebenen Funktion?
Es ist halt eine API-Funktion, die die absolute Adresse einer Funktion eines geladenen Moduls zurückgibt. Wie sie das macht, entzieht sich meiner Kenntnis. Da Microsoft seine Quellcodes (weitestgehend C und C++ mit ASM-Teilen) nicht veröffentlicht, ist es auch nicht ganz einfach das herauszubekommen. (Außerdem würde das eh nicht weiterhelfen.) Ich vermute aber einfach folgendes: Eine DLL enthält in ihrem Header eine Liste der in ihr exportierten Funktionen mit den Einsprungadressen. Ich nehme daher an, daß GetProcAdress über das Handle der DLL auf diese Liste zugreift.
Gruß Roland |
|
|
| Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4 | 28.03.2007 ▲ |
|
|
|