Synthetische Symbole und Module (WinDbg / DbgEng)

    In dieser Veröffentlichung konzentrieren wir uns auf synthetische Module und Symbole der Windows Debugging Engine (Debugger Engine). Das heißt, über Entitäten, die dem Debugger künstlich hinzugefügt werden können, um Speicheradressen zu färben .



    Synthetische Module


    Im Allgemeinen ist ein Modul innerhalb einer Debugging-Engine (Debugger-Engine) ein bestimmter fortlaufender Bereich des virtuellen Speichers: die Basisadresse des Moduls (die Adresse des ersten Bytes der projizierten Datei) und seine Größe. Für jede Art von Debugging (Live-Debugging / Dump-Analyse, Benutzermodus / Kernel-Modus usw.) verfügt der Debugger über einen eigenen Mechanismus, um die Liste der geladenen Module zu lesen und auf dem neuesten Stand zu halten. Die Aktualisierung der Liste der geladenen Module lässt sich am einfachsten mit dem Befehl .reload mit dem Parameter / s erzwingen .


    Wenn wir beispielsweise über das Live-Debugging des Benutzermodusprozesses sprechen, basiert die Liste der geladenen Module auf drei Hauptladerlisten : der Liste der Modulladereihenfolgen (InLoadOrderModuleList), der Liste der im Speicher befindlichen Module (InMemoryOrderModuleList) und der Liste der Initialisierungsreihenfolge (InInitializationOrderModuleList). Einerseits stören wir uns ( fast ) nicht daran, beliebige Daten ( z. B. von einer PE- Datei auf einer Platte) zu nehmen und sie manuell zur Ausführung im Speicher zu markieren. Andererseits sind die Techniken zum Entfernen einer regulären DLL, die aus den oben genannten drei Bootloader-Listen (ein Modul verborgen) geladen ist, seit langem bekannt .


    In beiden Fällen ist es beim Debuggen einer solchen Situation hilfreich, den Bereich des verborgenen Moduls markieren zu können. Dazu passen Kunststoffmodule. Als praktisches Experiment können Sie WinDbg einfach zwingen, das geladene Modul mit demselben Befehl .reload, aber mit dem Parameter / u aus seiner internen Liste zu löschen .


    Als nächstes werde ich als Auflistung den üblichen Debugging-Prozess des Benutzermodus (notepad.exe) verwenden. Zuerst erinnern wir uns an die Basisadresse des ntdll-Moduls (0x07ffa8a160000) und berechnen seine Größe (0x01e1000):


    0:007> lm m ntdll
    Browse full module list
    start             end                 module name
    00007ffa`8a160000 00007ffa`8a341000   ntdll
    0:007> ? 00007ffa`8a341000-00007ffa`8a160000
    Evaluate expression: 1970176 = 00000000`001e1000

    Betrachten Sie die Liste der einfachen Funktion RtlFreeSid aus dem ntdll-Modul, die die Funktion RtlFreeHeap aus diesem Modul aufruft, wobei sie sich gleichzeitig die Adressen der Zeichen RtlFreeSid und RtlFreeHeap (0x7ffa8a1cbc20 und 0x7ffa8a176df0) speichert:


    0:007> uf ntdll!RtlFreeSid
    ntdll!RtlFreeSid:
    00007ffa`8a1cbc20 4053            push    rbx
    00007ffa`8a1cbc22 4883ec20        sub     rsp,20h
    00007ffa`8a1cbc26 488bd9          mov     rbx,rcx
    00007ffa`8a1cbc29 33d2            xor     edx,edx
    00007ffa`8a1cbc2b 65488b0c2560000000 mov   rcx,qword ptr gs:[60h]
    00007ffa`8a1cbc34 4c8bc3          mov     r8,rbx
    00007ffa`8a1cbc37 488b4930        mov     rcx,qword ptr [rcx+30h]
    00007ffa`8a1cbc3b e8b0b1faff      call    ntdll!RtlFreeHeap (00007ffa`8a176df0)
    00007ffa`8a1cbc40 33c9            xor     ecx,ecx
    00007ffa`8a1cbc42 85c0            test    eax,eax
    00007ffa`8a1cbc44 480f45d9        cmovne  rbx,rcx
    00007ffa`8a1cbc48 488bc3          mov     rax,rbx
    00007ffa`8a1cbc4b 4883c420        add     rsp,20h
    00007ffa`8a1cbc4f 5b              pop     rbx
    00007ffa`8a1cbc50 c3              ret

    Entsprechend der obigen Auflistung ist es auch einfach, die Größe der Funktion ntdll zu berechnen! RtlFreeSid:


    0:007> ? 00007ffa`8a1cbc51 - 0x07ffa8a1cbc20
    Evaluate expression: 49 = 00000000`00000031

    Und die Größe der Funktion ntdll! RtlFreeHeap ist für unser Experiment nicht wichtig, daher können wir sie der Einfachheit halber mit einem Byte vergleichen.


    Simulieren Sie nun das Ausblenden des ntdll-Moduls:


    0:007> .reload /u ntdll
    Unloaded ntdll

    Das Feld dieser Operation mit der Adresse der Funktion ntdll! RtlFreeSid im Debugger ist nicht mehr so ​​informativ (und Sie können bereits auf den Anfang der Funktion nur an der virtuellen Adresse zugreifen):


    0:007> uf 00007ffa`8a1cbc20
    00007ffa`8a1cbc20 4053            push    rbx
    00007ffa`8a1cbc22 4883ec20        sub     rsp,20h
    00007ffa`8a1cbc26 488bd9          mov     rbx,rcx
    00007ffa`8a1cbc29 33d2            xor     edx,edx
    00007ffa`8a1cbc2b 65488b0c2560000000 mov   rcx,qword ptr gs:[60h]
    00007ffa`8a1cbc34 4c8bc3          mov     r8,rbx
    00007ffa`8a1cbc37 488b4930        mov     rcx,qword ptr [rcx+30h]
    00007ffa`8a1cbc3b e8b0b1faff      call    00007ffa`8a176df0
    00007ffa`8a1cbc40 33c9            xor     ecx,ecx
    00007ffa`8a1cbc42 85c0            test    eax,eax
    00007ffa`8a1cbc44 480f45d9        cmovne  rbx,rcx
    00007ffa`8a1cbc48 488bc3          mov     rax,rbx
    00007ffa`8a1cbc4b 4883c420        add     rsp,20h
    00007ffa`8a1cbc4f 5b              pop     rbx
    00007ffa`8a1cbc50 c3              ret

    Um ein synthetisches Modul hinzuzufügen, müssen Sie die Programmschnittstelle IDebugSymbols3 :: AddSyntheticModule aufrufen .Es gibt einfach keine integrierten Befehle, mit denen Sie diesen Anruf tätigen könnten (soweit ich weiß).Mikhail I. Izmestev schlug vor, dass es einen ähnlichen Mechanismus gibt - den gleichen .reload , aber mit den Parametern Name, Adresse und Größe: "Module = Address, Size" (und möglicherweise ist dies auf synthetischen Modulen implementiert).


    .reload ntdll = 00007ff8`470e1000.001e1000
    0:007> .reload ntdll=00007ff8`470e1000,001e1000
    *** WARNING: Unable to verify timestamp for ntdll
    *** ERROR: Module load completed but symbols could not be loaded for ntdll
    0:007> uf 00007ff8`4714bc20
    ntdll+0x6ac20:
    00007ff8`4714bc20 4053            push    rbx
    00007ff8`4714bc22 4883ec20        sub     rsp,20h
    00007ff8`4714bc26 488bd9          mov     rbx,rcx
    00007ff8`4714bc29 33d2            xor     edx,edx
    00007ff8`4714bc2b 65488b0c2560000000 mov   rcx,qword ptr gs:[60h]
    00007ff8`4714bc34 4c8bc3          mov     r8,rbx
    00007ff8`4714bc37 488b4930        mov     rcx,qword ptr [rcx+30h]
    00007ff8`4714bc3b e8b0b1faff      call    ntdll+0x15df0 (00007ff8`470f6df0)
    00007ff8`4714bc40 33c9            xor     ecx,ecx
    00007ff8`4714bc42 85c0            test    eax,eax
    00007ff8`4714bc44 480f45d9        cmovne  rbx,rcx
    00007ff8`4714bc48 488bc3          mov     rax,rbx
    00007ff8`4714bc4b 4883c420        add     rsp,20h
    00007ff8`4714bc4f 5b              pop     rbx
    00007ff8`4714bc50 c3              ret

    Nun, wir verwenden die Debugger-Erweiterung und hier kommt pykd . In der neuesten (zum Zeitpunkt des Schreibens) Version 0.3.4.3 wurden die Funktionen zur Verwaltung synthetischer Module hinzugefügt: addSyntheticModule (...) (was in unserem Fall benötigt wird) und removeSyntheticModule (...).


    Für die zuvor gespeicherte Basisadresse und Modulgröße fügen wir dem Debugger Informationen über das ausgeblendete ntdll-Modul hinzu (wenn ein Fehler auftritt, wird eine Ausnahme ausgelöst. Die automatische Ausführung ist ein Zeichen des Erfolgs. Sie können Druckwarnungen ignorieren.)


    0:007> !py
    Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> addSyntheticModule(0x07ffa8a160000, 0x01e1000, 'ntdll')
    *** WARNING: Unable to verify timestamp for ntdll
    >>> exit()

    Nun ist die Disassembler-Auflistung etwas informativer geworden:


    0:007> uf 00007ffa`8a1cbc20
    ntdll+0x6bc20:
    00007ffa`8a1cbc20 4053            push    rbx
    00007ffa`8a1cbc22 4883ec20        sub     rsp,20h
    00007ffa`8a1cbc26 488bd9          mov     rbx,rcx
    00007ffa`8a1cbc29 33d2            xor     edx,edx
    00007ffa`8a1cbc2b 65488b0c2560000000 mov   rcx,qword ptr gs:[60h]
    00007ffa`8a1cbc34 4c8bc3          mov     r8,rbx
    00007ffa`8a1cbc37 488b4930        mov     rcx,qword ptr [rcx+30h]
    00007ffa`8a1cbc3b e8b0b1faff      call    ntdll+0x16df0 (00007ffa`8a176df0)
    00007ffa`8a1cbc40 33c9            xor     ecx,ecx
    00007ffa`8a1cbc42 85c0            test    eax,eax
    00007ffa`8a1cbc44 480f45d9        cmovne  rbx,rcx
    00007ffa`8a1cbc48 488bc3          mov     rax,rbx
    00007ffa`8a1cbc4b 4883c420        add     rsp,20h
    00007ffa`8a1cbc4f 5b              pop     rbx
    00007ffa`8a1cbc50 c3              ret

    Oder vielmehr sehen wir, dass eine Funktion im ntdll-Modul eine andere Funktion innerhalb desselben Moduls aufruft.


    Synthetische Zeichen


    Die Auflistung ist nach dem Hinzufügen eines synthetischen Moduls informativer geworden, jedoch nicht so eloquent wie das ursprüngliche. Es fehlen Zeichen (in unserem Fall die Namen der Funktionen RtlFreeSid und RtlFreeHeap). Um dies wieder zu beheben, ist ein Aufruf erforderlich, aber eine andere Softwareschnittstelle - IDebugSymbols3 :: AddSyntheticSymbol . Wieder pykd bereit , uns dabei zu helfen:


    0:007> !py
    Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> addSyntheticSymbol(0x07ffa8a1cbc20, 0x31, 'RtlFreeSid')
    <pykd.syntheticSymbol object at 0x0000014D47699518>
    >>> addSyntheticSymbol(0x07ffa8a176df0, 1, 'RtlFreeHeap')
    <pykd.syntheticSymbol object at 0x0000014D476994A8>
    >>> exit()

    Das Ergebnis ist dem Ergebnis sehr ähnlich, das bei der Verwendung von Symbolen aus der ptb-Datei ntdll verwendet wurde:


    0:007> uf 00007ffa`8a1cbc20
    ntdll!RtlFreeSid:
    00007ffa`8a1cbc20 4053            push    rbx
    00007ffa`8a1cbc22 4883ec20        sub     rsp,20h
    00007ffa`8a1cbc26 488bd9          mov     rbx,rcx
    00007ffa`8a1cbc29 33d2            xor     edx,edx
    00007ffa`8a1cbc2b 65488b0c2560000000 mov   rcx,qword ptr gs:[60h]
    00007ffa`8a1cbc34 4c8bc3          mov     r8,rbx
    00007ffa`8a1cbc37 488b4930        mov     rcx,qword ptr [rcx+30h]
    00007ffa`8a1cbc3b e8b0b1faff      call    ntdll!RtlFreeHeap (00007ffa`8a176df0)
    00007ffa`8a1cbc40 33c9            xor     ecx,ecx
    00007ffa`8a1cbc42 85c0            test    eax,eax
    00007ffa`8a1cbc44 480f45d9        cmovne  rbx,rcx
    00007ffa`8a1cbc48 488bc3          mov     rax,rbx
    00007ffa`8a1cbc4b 4883c420        add     rsp,20h
    00007ffa`8a1cbc4f 5b              pop     rbx
    00007ffa`8a1cbc50 c3              ret

    Merkmale synthetischer Entitäten


    Es ist zu beachten, dass die Erstellung synthetischer Symbole in allen vorhandenen Modulen zulässig ist, nicht nur in synthetischen. Das heißt, Sie können Zeichen sowohl zu Modulen mit zugänglichen pdb-Dateien als auch zu Modulen hinzufügen , für die wir keine Dateien mit Debug-Informationen haben. Die Zeichen außerhalb der Module können jedoch nicht erstellt werden. Das heißt, um eine beliebige Speicheradresse außerhalb der Grenzen vorhandener Module zu markieren, müssen Sie am Anfang ein synthetisches Einbettungsmodul erstellen. Anschließend können Sie (falls erforderlich, den Namen des Moduls zum Färben ausgeben ), um ein synthetisches Symbol darin zu erstellen.


    Es ist auch nützlich zu erwähnen, dass synthetische Module und Symbole durch unachtsame Handbewegungen entfernt werden können:


    • Durch das Neuladen von Modul-Debugging-Symbolen werden alle synthetischen Symbole dieses Moduls entfernt.
    • Beim Neustart aller Module werden alle synthetischen Module entfernt.

    ! synexts


    Obwohl die Verwendung von pykd in der überwiegenden Mehrheit der Fälle praktisch ist (vor allem angesichts des Vorhandenseins eines Bootstarppers ), können Sie manchmal in Situationen geraten, in denen Sie für die Verwendung von pykd viel Energie aufwenden müssen. Zum Beispiel musste ich einmal mit dem Host-Computer debuggen, auf dem Windows XP ausgeführt wurde. Wie sich herausstellte, unterstützt pykd lange Zeit kein XP und ich brauchte synthetische Symbole und Module. Mir schien, dass es für diese Aufgabe einfacher ist, eine separate kleine Erweiterung zusammenzustellen, die einen engen Kreis von notwendigen Aufgaben löst, als die vollständige XP-Unterstützung für pykd wiederherzustellen. Als Ergebnis wurde ein separates ! Synexts- Projekt erstellt .


    Dies ist eine einfache Erweiterung, die dem Benutzer zwei Exporte zur Verfügung stellt:


    • ! synexts.addsymbol - Erstellt ein synthetisches Symbol in einem vorhandenen Modul.
    • ! synexts.addmodule - Erstellt ein synthetisches Modul in der internen Liste der Debug-Engine.

    Um dies zu demonstrieren, ahmen wir erneut das Verstecken des Moduls ntdll nach:


    0:007> .reload /u ntdll
    Unloaded ntdll
    0:007> uf 00007ffa`8a1cbc20
    00007ffa`8a1cbc20 4053            push    rbx
    00007ffa`8a1cbc22 4883ec20        sub     rsp,20h
    00007ffa`8a1cbc26 488bd9          mov     rbx,rcx
    00007ffa`8a1cbc29 33d2            xor     edx,edx
    00007ffa`8a1cbc2b 65488b0c2560000000 mov   rcx,qword ptr gs:[60h]
    00007ffa`8a1cbc34 4c8bc3          mov     r8,rbx
    00007ffa`8a1cbc37 488b4930        mov     rcx,qword ptr [rcx+30h]
    00007ffa`8a1cbc3b e8b0b1faff      call    00007ffa`8a176df0
    00007ffa`8a1cbc40 33c9            xor     ecx,ecx
    00007ffa`8a1cbc42 85c0            test    eax,eax
    00007ffa`8a1cbc44 480f45d9        cmovne  rbx,rcx
    00007ffa`8a1cbc48 488bc3          mov     rax,rbx
    00007ffa`8a1cbc4b 4883c420        add     rsp,20h
    00007ffa`8a1cbc4f 5b              pop     rbx
    00007ffa`8a1cbc50 c3              ret

    Wir stellen das Wissen über das Modul und die Zeichen in Form synthetischer Entitäten wieder her, verwenden jedoch die Erweiterung! Synexts:


    0:007> !synexts.addmodule ntdll C:\Windows\System32\ntdll.dll 00007ffa`8a160000 0x01e1000
    *** WARNING: Unable to verify timestamp for C:\Windows\System32\ntdll.dll
    Synthetic module successfully added
    0:007> !synexts.addsymbol RtlFreeSid 00007ffa`8a1cbc20 31
    Synthetic symbol successfully added
    0:007> !synexts.addsymbol RtlFreeHeap 00007ffa`8a176df0 1
    Synthetic symbol successfully added

    Es wird davon ausgegangen, dass Sie die kompilierte Bibliothek synexts.dll (entsprechend der von WinDbg verwendeten Bitbreite) bereits in das winext-Verzeichnis des Debuggers kopiert haben:


    0:007> .chain
    Extension DLL search Path:
        C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\WINXP;C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\winext;C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\winext\arcade;C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\pri;C:\Program Files (x86)\Windows Kits\10\Debuggers\x64;<…>
    Extension DLL chain:
        pykd.pyd: image 0.3.4.3, API 1.0.0, built Thu Jan 10 19:56:25 2019
            [path: C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\winext\pykd.pyd]
        synexts: API 1.0.0, built Fri Jan 18 17:38:17 2019
            [path: C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\winext\synexts.dll]
    <…>

    Und wieder sehen wir das Ergebnis, wenn dem synthetischen Modul synthetische Symbole hinzugefügt werden:


    0:007> uf 00007ffa`8a1cbc20
    ntdll!RtlFreeSid:
    00007ffa`8a1cbc20 4053            push    rbx
    00007ffa`8a1cbc22 4883ec20        sub     rsp,20h
    00007ffa`8a1cbc26 488bd9          mov     rbx,rcx
    00007ffa`8a1cbc29 33d2            xor     edx,edx
    00007ffa`8a1cbc2b 65488b0c2560000000 mov   rcx,qword ptr gs:[60h]
    00007ffa`8a1cbc34 4c8bc3          mov     r8,rbx
    00007ffa`8a1cbc37 488b4930        mov     rcx,qword ptr [rcx+30h]
    00007ffa`8a1cbc3b e8b0b1faff      call    ntdll!RtlFreeHeap (00007ffa`8a176df0)
    00007ffa`8a1cbc40 33c9            xor     ecx,ecx
    00007ffa`8a1cbc42 85c0            test    eax,eax
    00007ffa`8a1cbc44 480f45d9        cmovne  rbx,rcx
    00007ffa`8a1cbc48 488bc3          mov     rax,rbx
    00007ffa`8a1cbc4b 4883c420        add     rsp,20h
    00007ffa`8a1cbc4f 5b              pop     rbx
    00007ffa`8a1cbc50 c3              ret

    Jetzt auch beliebt: