Ist es möglich, die Signatur einer Funktion in einer gemeinsam genutzten Bibliothek programmgesteuert abzurufen?

Lesezeit: 6 Minuten

Benutzeravatar von Je Rog
Je Rog

Der Titel ist klar, wir können eine Bibliothek laden dl_open usw..

Aber wie bekomme ich die Signatur von Funktionen darin?

  • Möglicherweise finden Sie den Wikipedia-Artikel zum Thema Name Mangling informativ, um die Informationen zu sehen, die in Objektcodenamen für C vs. C++ codiert sind, und wie sie je nach Compiler variieren: en.wikipedia.org/wiki/Name_mangling

    – HostileFork sagt, vertraue SE nicht

    30. Juli 2011 um 5:57 Uhr

  • @Hostile Fork, in a einzel .so,ist es möglich, verschiedene Namensfehler zu haben?

    – Je Rog

    30. Juli 2011 um 6:07 Uhr

  • Wie im Wikipedia-Artikel erwähnt, dient die Namensverstümmelung in C nur zur Unterstützung von Windows-Konventionen und würde nicht in C erscheinen .so Dateien. Für C++ ja, verschiedene Mangel desselben Funktionsnamens erscheinen in einem .so um die Sprachfunktion des Überladens zu unterstützen. en.wikipedia.org/wiki/Function_overloading

    – HostileFork sagt, vertraue SE nicht

    30. Juli 2011 um 6:30 Uhr

  • Angesichts der Tatsache, dass die Anzahl populärer Sprachen in den letzten zwei Jahrzehnten stark zugenommen hat, wäre es nicht fair zu sagen, dass das Hinzufügen einiger introspektiver Metadaten zu Elf-Dateien allen helfen würde? ELF wird nicht nur von C/C++ verwendet und es wäre ein guter Schritt in die richtige Richtung, Binärdateien mit Informationen anzureichern, die das Verlinken mit zB Shared Libraries erlauben, egal in welcher Sprache sie geschrieben wurden.

    – BitTickler

    9. März 2022 um 23:32 Uhr

Benutzeravatar von datenwolf
Datenwolf

Diese Antwort kann nicht pauschal beantwortet werden. Technisch gesehen, wenn Sie Ihre ausführbare Datei mit umfassenden Debugging-Informationen kompiliert haben (der Code kann immer noch eine optimierte Release-Version sein), enthält die ausführbare Datei zusätzliche Abschnitte, die eine Art Reflektivität der Binärdatei bieten. Auf *nix-Systemen (Sie erwähnten dl_open) Dies wird durch implementiert ZWERG Debuggen von Daten in zusätzlichen Abschnitten der ELF binär. Ähnlich funktioniert es für Mach universelle Binärdateien auf MacOS X.

Windows PEs verwenden jedoch ein völlig anderes Format, daher ist DWARF leider nicht wirklich plattformübergreifend (eigentlich habe ich in den frühen Entwicklungsstadien meiner 3D-Engine einen ELF/DWARF-Loader für Windows implementiert, damit ich ein gemeinsames Format für die verschiedenen Engines verwenden konnte Modulen, so dass dies mit einigem ernsthaften Aufwand möglich ist).

Wenn Sie nicht in die Implementierung Ihrer eigenen Lader oder Debugging-Informationszugriffsmethoden einsteigen möchten, können Sie die Reflexionsinformationen durch einige zusätzliche exportierte Symbole (durch ein Standard-Namensschema) einbetten, die auf eine Tabelle mit Funktionsnamen verweisen und auf ihre abbilden Unterschrift. Im Fall von C-Quelldateien ist das Schreiben eines Parsers zum Extrahieren der Informationen aus der Quelldatei selbst ziemlich trivial. C++ OTOH ist so notorisch schwer korrekt zu analysieren, dass Sie einen vollwertigen Compiler benötigen, um es richtig hinzubekommen. Zu diesem Zweck wurde GCCXML entwickelt, technisch gesehen ein GCC, der die AST anstelle einer Objektbinärdatei in XML-Form ausgibt. Das ausgegebene XML ist dann viel einfacher zu analysieren.

Erstellen Sie aus den extrahierten Informationen eine Quelldatei mit einer Art verknüpfter Liste/Array/etc. Struktur, die jede Funktion beschreibt. Wenn Sie das Symbol jeder Funktion nicht direkt exportieren, sondern stattdessen ein Feld in der Reflexionsstruktur mit dem Funktionszeiger initialisieren, erhalten Sie ein wirklich schönes und sauber kommentiertes Exportschema. Technisch gesehen könnten Sie diese Informationen auch in einem separaten Abschnitt der Binärdatei platzieren, aber das Einfügen in den schreibgeschützten Datenabschnitt funktioniert auch.


Wenn Sie jedoch eine Binärdatei eines Drittanbieters erhalten – sagen wir im schlimmsten Fall, dass sie aus C-Quellen kompiliert wurde, keine Debugging-Informationen und alle Symbole, auf die nicht extern verwiesen wird, entfernt wurden – sind Sie ziemlich am Arsch. Das Beste, was Sie tun konnten, war eine binäre Analyse der Art und Weise, wie die Funktion auf die verschiedenen Stellen zugreift, an denen Parameter übergeben werden können.

Dadurch erfahren Sie nur die Anzahl der Parameter und die Größe jedes Parameterwerts, nicht jedoch den Typ oder den Namen/die Bedeutung. Beim Reverse Engineering eines Programms (z. B. Malware-Analyse oder Sicherheitsüberprüfung) ist die Identifizierung von Art und Bedeutung der an Funktionen übergebenen Parameter eine der Hauptaufgaben. Kürzlich bin ich auf einen Treiber gestoßen, den ich zu Debugging-Zwecken rückgängig machen musste, und Sie können nicht glauben, wie erstaunt ich darüber war, dass ich C++-Symbole in einem Linux-Kernel-Modul gefunden habe (Sie können C++ im Linux-Kernel nicht auf vernünftige Weise verwenden ), aber auch erleichtert, weil mir die C++-Namensverstümmelung viele Informationen lieferte.

Unter Linux (oder Mac) können Sie eine Kombination aus „nm“ und „c++filt“ (für C++-Bibliotheken) verwenden.

nm mylibrary.so | c++filt

oder

nm mylibrary.a | c++filt

“nm” gibt Ihnen die entstellte Form und “c++filt” versucht, sie in ein besser lesbares Format zu bringen. Möglicherweise möchten Sie einige Optionen in nm verwenden, um die Ergebnisse zu filtern, insbesondere wenn die Bibliothek groß ist (oder Sie können die endgültige Ausgabe “grep”, um ein bestimmtes Element zu finden).

  • Auf meinem Mac musste ich tun nm -D -Ca mylibrary.so | c++filt

    – Colin

    23. April 2019 um 19:12 Uhr

Benutzeravatar von jman
Jman

Nein das ist nicht möglich. Die Signatur einer Funktion bedeutet zur Laufzeit nichts, es ist eine Information, die zur Kompilierzeit für den Compiler nützlich ist, um Ihr Programm zu validieren.

  • Ich glaube nicht, dass diese Aussage richtig ist, Sie sagen im Grunde nur kategorisch, dass es nicht möglich ist. Es gibt eine Menge Dinge, die getan werden können, um eine Signatur wiederherzustellen; Sie können sich die Aufrufkonventionen ansehen, und wenn Sie die Taint-Analyse verwenden können, können Sie Argumente von anderen bekannten Signaturen verfolgen und Typen an die gewünschte Funktion zurückgeben.

    – Adam Müller

    27. August 2014 um 13:49 Uhr

Du kannst nicht. Entweder veröffentlicht die Bibliothek eine öffentliche API in einem Header, oder Sie müssen die Signatur auf andere Weise kennen.

Die Parameter einer Funktion auf der unteren Ebene hängen davon ab, wie viele Stapelargumente im Stapelrahmen Sie berücksichtigen und wie Sie sie interpretieren. Sobald die Funktion in Objektcode kompiliert ist, ist es daher nicht möglich, die Signatur so zu erhalten. Eine entfernte Möglichkeit besteht darin, den Code zu zerlegen und zu lesen, wie er funktioniert, um die Anzahl der Parameter zu kennen, aber der Typ wäre immer noch schwierig oder unmöglich zu bestimmen. Mit einem Wort, es ist nicht möglich.

Benutzeravatar von mpontillo
mpontillo

Diese Informationen sind nicht verfügbar. Nicht einmal der Debugger weiß:

$ cat foo.c
#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{
    char foo[10] = { 0 };
    char bar[10] = { 0 };
    printf("%s\n", "foo");
    memcpy(bar, foo, sizeof(foo));
    return 0;
}

$ gcc -g -o foo foo.c
$ gdb foo
Reading symbols from foo...done.
(gdb) b main
Breakpoint 1 at 0x4005f3: file foo.c, line 5.
(gdb) r
Starting program: foo 

Breakpoint 1, main (argc=1, argv=0x7fffffffe3e8) at foo.c:5
5   {
(gdb) ptype printf
type = int ()
(gdb) ptype memcpy
type = int ()
(gdb) 

1447160cookie-checkIst es möglich, die Signatur einer Funktion in einer gemeinsam genutzten Bibliothek programmgesteuert abzurufen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy