Linux-Debugger-Stack-Erweiterung!
Einführung | Manchmal ist die wichtigste Information, die Sie wissen müssen, wie Ihr aktueller Programmstand dorthin gelangt ist. Es gibt einen Backtrace-Befehl, der Ihnen die aktuelle Funktionsaufrufkette Ihres Programms liefert. In diesem Beitrag erfahren Sie, wie Sie das Stack-Unwinding auf x86_64 implementieren, um einen solchen Traceback zu generieren. |
Diese Links werden online geschaltet, sobald andere Beiträge veröffentlicht werden.
- Bereiten Sie die Umgebung vor
- Haltepunkt
- Register und Speicher
- ELF und ZWERG
- Quellcode und Signale
- Schritt-für-Schritt-Ausführung auf Quellcode-Ebene
- Haltepunkte auf Quellenebene
- Stack-Erweiterung
- Variablen lesen
- Nächste Schritte
Nehmen Sie das folgende Programm als Beispiel:
void a() { //stopped here } void b() { a(); } void c() { a(); } int main() { b(); c(); }
Wenn der Debugger an der Zeile //stopped here' stoppt, gibt es zwei Möglichkeiten, dorthin zu gelangen: main->b->a oder main->c->a`. Wenn wir mit LLDB einen Breakpoint setzen, die Ausführung fortsetzen und einen Traceback anfordern, dann erhalten wir Folgendes:
* frame #0: 0x00000000004004da a.out`a() + 4 at bt.cpp:3 frame #1: 0x00000000004004e6 a.out`b() + 9 at bt.cpp:6 frame #2: 0x00000000004004fe a.out`main + 9 at bt.cpp:14 frame #3: 0x00007ffff7a2e830 libc.so.6`__libc_start_main + 240 at libc-start.c:291 frame #4: 0x0000000000400409 a.out`_start + 41
Das bedeutet, wir befinden uns derzeit in Funktion a, a springt von Funktion b, b springt von der Hauptfunktion usw. In den letzten beiden Frames führt der Compiler das Bootstrapping der Hauptfunktion durch.
Die Frage ist nun, wie wir es auf x86_64 umsetzen. Der robusteste Ansatz wäre, den .eh_frame-Teil der ELF-Datei zu analysieren und herauszufinden, wie der Stapel von dort abgewickelt werden kann, aber das wäre mühsam. Sie könnten es mit libunwind oder ähnlichem machen, aber das ist langweilig. Stattdessen gehen wir davon aus, dass der Compiler den Stapel auf irgendeine Weise eingerichtet hat, und durchlaufen ihn manuell. Dazu müssen wir zunächst das Layout des Stapels verstehen.
High | ... | +---------+ +24| Arg 1 | +---------+ +16| Arg 2 | +---------+ + 8| Return | +---------+ EBP+--> |Saved EBP| +---------+ - 8| Var 1 | +---------+ ESP+--> | Var 2 | +---------+ | ... | Low
Wie Sie sehen können, wird der Frame-Zeiger des letzten Stack-Frames am Anfang des aktuellen Stack-Frames gespeichert, wodurch eine verknüpfte Liste von Zeigern erstellt wird. Der Stapel wird basierend auf dieser verknüpften Liste abgewickelt. Wir können die Funktion für den nächsten Frame in der Liste finden, indem wir in der DWARF-Nachricht nach der Rücksprungadresse suchen. Einige Compiler ignorieren die Verfolgung der Frame-Basisadresse von EBP, da diese als Offset von ESP ausgedrückt werden kann und ein zusätzliches Register freigibt. Selbst wenn Optimierungen aktiviert sind, wird die Übergabe von -fno-omit-frame-pointer an GCC oder Clang dazu führen, dass die Konventionen eingehalten werden, auf die wir angewiesen sind.
Wir erledigen die ganze Arbeit in der Funktion print_backtrace:
void debugger::print_backtrace() {
Als Erstes müssen Sie entscheiden, welches Format zum Ausdrucken der Rahmeninformationen verwendet werden soll. Ich habe ein Lambda verwendet, um diese Methode einzuführen:
auto output_frame = [frame_number = 0] (auto&& func) mutable { std::cout <p>Der erste gedruckte Frame ist der aktuell ausgeführte Frame. Informationen zu diesem Frame erhalten wir, indem wir den aktuellen Programmzähler in DWARF nachschlagen: </p> <pre class="brush:php;toolbar:false">auto current_func = get_function_from_pc(get_pc()); output_frame(current_func);
Als nächstes müssen wir den Frame-Zeiger und die Rückgabeadresse der aktuellen Funktion abrufen. Der Frame-Zeiger wird im RBP-Register gespeichert und die Rücksprungadresse beträgt 8 Bytes, gestapelt vom Frame-Zeiger.
auto frame_pointer = get_register_value(m_pid, reg::rbp); auto return_address = read_memory(frame_pointer+8);
Jetzt haben wir alle Informationen, die wir brauchen, um den Stack zu erweitern. Ich spule einfach weiter ab, bis der Debugger die Hauptfunktion erreicht, Sie können aber auch anhalten, wenn der Frame-Zeiger 0x0 ist. Dies sind die Funktionen, die Sie aufrufen, bevor Sie die Hauptfunktion aufrufen. Wir erfassen den Frame-Zeiger und die Rücksprungadresse von jedem Frame und drucken die Informationen aus.
while (dwarf::at_name(current_func) != "main") { current_func = get_function_from_pc(return_address); output_frame(current_func); frame_pointer = read_memory(frame_pointer); return_address = read_memory(frame_pointer+8); } }
Das ist es! Hier ist die gesamte Funktion:
void debugger::print_backtrace() { auto output_frame = [frame_number = 0] (auto&& func) mutable { std::cout <strong>Befehl hinzufügen</strong> <p>Natürlich müssen wir diesen Befehl dem Benutzer zugänglich machen. </p> <pre class="brush:php;toolbar:false">else if(is_prefix(command, "backtrace")) { print_backtrace(); }Test
Eine Möglichkeit, diese Funktionalität zu testen, besteht darin, ein Testprogramm mit einer Reihe kleiner Funktionen zu schreiben, die sich gegenseitig aufrufen. Legen Sie ein paar Haltepunkte fest, springen Sie durch den Code und stellen Sie sicher, dass Ihr Traceback korrekt ist.
Wir haben einen langen Weg von einem Programm zurückgelegt, das nur spawnen und sich an andere Programme anhängen konnte. Der vorletzte Artikel dieser Reihe vervollständigt die Debugger-Implementierung durch die Unterstützung des Lesens und Schreibens von Variablen. Bis dahin finden Sie den Code für diesen Beitrag hier.
Das obige ist der detaillierte Inhalt vonLinux-Debugger-Stack-Erweiterung!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Das Internet stützt sich nicht auf ein einzelnes Betriebssystem, aber Linux spielt eine wichtige Rolle dabei. Linux wird häufig auf Servern und Netzwerkgeräten verwendet und ist für seine Stabilität, Sicherheit und Skalierbarkeit beliebt.

Der Kern des Linux -Betriebssystems ist die Befehlszeilenschnittstelle, die verschiedene Operationen über die Befehlszeile ausführen kann. 1. Datei- und Verzeichnisoperationen verwenden LS, CD, MKDIR, RM und andere Befehle, um Dateien und Verzeichnisse zu verwalten. 2. Benutzer- und Berechtigungsverwaltung sorgt für die Systemsicherheit und die Ressourcenzuweisung über UserAdd, PASSWD, CHMOD und andere Befehle. 3. Process Management verwendet PS, Kill und andere Befehle, um Systemprozesse zu überwachen und zu steuern. 4. Netzwerkoperationen umfassen Ping, IFConfig, SSH und andere Befehle zum Konfigurieren und Verwalten von Netzwerkverbindungen. 5. Systemüberwachung und Wartung Verwenden Sie Befehle wie Top, DF, DU, um den Betriebsstatus und die Ressourcennutzung des Systems zu verstehen.

Einführung Linux ist ein leistungsstarkes Betriebssystem, das aufgrund seiner Flexibilität und Effizienz von Entwicklern, Systemadministratoren und Stromnutzern bevorzugt wird. Die Verwendung langer und komplexer Befehle kann jedoch mühsam und äh sein

Linux eignet sich für Server, Entwicklungsumgebungen und eingebettete Systeme. 1. Als Serverbetriebssystem ist Linux stabil und effizient und wird häufig zur Bereitstellung von Anwendungen mit hoher Konreise verwendet. 2. Als Entwicklungsumgebung bietet Linux effiziente Befehlszeilen -Tools und Paketmanagementsysteme, um die Entwicklungseffizienz zu verbessern. 3. In eingebetteten Systemen ist Linux leicht und anpassbar und für Umgebungen mit begrenzten Ressourcen geeignet.

Einführung: Sicherung der digitalen Grenze mit Linux-basierten ethischen Hacking In unserer zunehmend miteinander verbundenen Welt ist die Cybersicherheit von größter Bedeutung. Ethische Hacking- und Penetrationstests sind von entscheidender Bedeutung, um Schwachstellen proaktiv zu identifizieren und zu mildern

Zu den Methoden für das grundlegende Linux -Lernen von Grund zu Grund gehören: 1. Verstehen Sie das Dateisystem und die Befehlszeilenschnittstelle, 2. Master Basic -Befehle wie LS, CD, MKDIR, 3. Lernen Sie Dateivorgänge wie Erstellen und Bearbeiten von Dateien, 4. Erklären Sie fortgeschrittene Verwendung wie Pipelines und GREP -Befehle, 5.

Linux wird häufig in Servern, eingebetteten Systemen und Desktopumgebungen verwendet. 1) Im Serverfeld ist Linux aufgrund seiner Stabilität und Sicherheit eine ideale Wahl für das Hosting von Websites, Datenbanken und Anwendungen geworden. 2) In eingebetteten Systemen ist Linux für seine hohe Anpassung und Effizienz beliebt. 3) In der Desktop -Umgebung bietet Linux eine Vielzahl von Desktop -Umgebungen, um den Anforderungen verschiedener Benutzer gerecht zu werden.

Die Nachteile von Linux umfassen Benutzererfahrung, Softwarekompatibilität, Hardwareunterstützung und Lernkurve. 1. Die Benutzererfahrung ist nicht so freundlich wie Windows oder MacOS und basiert auf der Befehlszeilenschnittstelle. 2. Die Softwarekompatibilität ist nicht so gut wie andere Systeme und es fehlen native Versionen vieler kommerzieller Software. 3. Die Hardware -Unterstützung ist nicht so umfassend wie Windows, und die Treiber können manuell zusammengestellt werden. 4. Die Lernkurve ist steil, und die Mastering -Befehlszeilenvorgänge erfordert Zeit und Geduld.


Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

AI Hentai Generator
Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

Heiße Werkzeuge

EditPlus chinesische Crack-Version
Geringe Größe, Syntaxhervorhebung, unterstützt keine Code-Eingabeaufforderungsfunktion

VSCode Windows 64-Bit-Download
Ein kostenloser und leistungsstarker IDE-Editor von Microsoft

MinGW – Minimalistisches GNU für Windows
Dieses Projekt wird derzeit auf osdn.net/projects/mingw migriert. Sie können uns dort weiterhin folgen. MinGW: Eine native Windows-Portierung der GNU Compiler Collection (GCC), frei verteilbare Importbibliotheken und Header-Dateien zum Erstellen nativer Windows-Anwendungen, einschließlich Erweiterungen der MSVC-Laufzeit zur Unterstützung der C99-Funktionalität. Die gesamte MinGW-Software kann auf 64-Bit-Windows-Plattformen ausgeführt werden.

SublimeText3 Linux neue Version
SublimeText3 Linux neueste Version

DVWA
Damn Vulnerable Web App (DVWA) ist eine PHP/MySQL-Webanwendung, die sehr anfällig ist. Seine Hauptziele bestehen darin, Sicherheitsexperten dabei zu helfen, ihre Fähigkeiten und Tools in einem rechtlichen Umfeld zu testen, Webentwicklern dabei zu helfen, den Prozess der Sicherung von Webanwendungen besser zu verstehen, und Lehrern/Schülern dabei zu helfen, in einer Unterrichtsumgebung Webanwendungen zu lehren/lernen Sicherheit. Das Ziel von DVWA besteht darin, einige der häufigsten Web-Schwachstellen über eine einfache und unkomplizierte Benutzeroberfläche mit unterschiedlichen Schwierigkeitsgraden zu üben. Bitte beachten Sie, dass diese Software