Einführung in die Dateistruktur

Dateityp Einführung

Ein Dateiformat (oder Dateityp) bezieht sich auf eine spezielle Kodierungsmethode für Informationen, die von einem Computer zum Speichern von Informationen verwendet wird, und wird verwendet, um intern gespeicherte Daten zu identifizieren. Zum Beispiel speichern einige Bilder, einige speichern Programme und einige speichern Textinformationen. Jeder Informationstyp kann in einem oder mehreren Dateiformaten im Computerspeicher gespeichert werden. Jedes Dateiformat hat normalerweise eine oder mehrere Erweiterungen, anhand derer es identifiziert werden kann, aber möglicherweise hat es keine Erweiterung. Erweiterungen helfen Anwendungen, das Dateiformat zu erkennen.

Für Festplatten oder Computerspeicher sind die einzig gültigen Informationen 0 und 1. Der Computer muss also mit einem entsprechenden Verfahren zur Umwandlung von Informationen in Bits ausgestattet sein. Es gibt unterschiedliche Speicherformate für unterschiedliche Informationen.

Einige Dateiformate dienen zum Speichern spezieller Daten. Beispielsweise wird das JPEG-Dateiformat in Bilddateien nur zum Speichern statischer Bilder verwendet, während GIF sowohl statische Bilder als auch einfache Animationen speichern kann. Das Quicktime-Format kann mehrere verschiedene Medientypen speichern. Zu den Textdateien gehören: txt-Dateien speichern im Allgemeinen nur einfachen und unformatierten ASCII- oder Unicode-Text; HTML-Dateien können formatierten Text speichern; das PDF-Format kann Text mit umfangreichen Inhalten und umfangreichen Bildern und Texten speichern.

Dasselbe Dateiformat, das von verschiedenen Programmen verarbeitet wird, kann zu völlig unterschiedlichen Ergebnissen führen. Wenn Sie beispielsweise eine Word-Datei mit Microsoft Word anzeigen, können Sie den Inhalt des Textes sehen, aber wenn Sie ihn unformatiert in einer Musik-Player-Software abspielen, erzeugt er Rauschen. Ein Dateiformat, das für einige Software aussagekräftige Ergebnisse liefert, kann für andere wie nutzloser digitaler Müll aussehen.

Die Methode zum Identifizieren von Dateiformaten mit Erweiterungen wurde erstmals im CP/M-Betriebssystem der Digital Equipment Corporation übernommen. Es wurde später von DOS- und Windows-Betriebssystemen übernommen. Die Erweiterung ist die Buchstabenfolge nach dem letzten Punkt (.) im Dateinamen. Beispielsweise werden HTML-Dateien durch die Erweiterung .htm oder .html identifiziert, GIF-Grafikdateien werden durch die Erweiterung .gif identifiziert.

Und wie werden unterschiedliche Dateiformate von Maschinen erkannt? Immerhin haben wir auf dem Desktop die Endung von (.txt) auf (.jpg) geändert.Obwohl wir das Dokument in ein Bild geändert haben, wissen wir alle, dass ein Doppelklick zum Öffnen zu diesem Zeitpunkt kein Bild anzeigt . Wie also bestimmt der Computer, was diese Datei ist? Tatsächlich haben verschiedene Dateiformate ihre eigenen eindeutigen Dateiformat-Flags. Am Anfang der Datei befindet sich ein der Datei entsprechendes Zeichen, das angibt, um welchen Dateityp es sich handelt. Nach der Bestimmung des Dateityps wird der folgende Inhalt gemäß dem Dateiformat des entsprechenden Typs geparst. All dies können wir sehen, wenn wir einen Hex-Editor verwenden.

Gemeinsame Dateiformat-Flags:

PE(exe,dll)文件头:4D5A

JPEG (jpg),文件头:FFD8FF

PNG (png),文件头:89504E47

GIF (gif),文件头:47494638

TIFF (tif),文件头:49492A00

Windows Bitmap (bmp),文件头:424D

CAD (dwg),文件头:41433130

Adobe Photoshop (psd),文件头:38425053

Rich Text Format (rtf),文件头:7B5C727466

XML (xml),文件头:3C3F786D6C

HTML (html),文件头:68746D6C3E

Email [thorough only] (eml),文件头:44656C69766572792D646174653A

Outlook Express (dbx),文件头:CFAD12FEC5FD746F

Outlook (pst),文件头:2142444E

MS Word/Excel (xls.or.doc),文件头:D0CF11E0

MS Access (mdb),文件头:5374616E64617264204A

WordPerfect (wpd),文件头:FF575043

Postscript (eps.or.ps),文件头:252150532D41646F6265

Adobe Acrobat (pdf),文件头:255044462D312E

Quicken (qdf),文件头:AC9EBD8F

Windows Password (pwl),文件头:E3828596

ZIP Archive (zip),文件头:504B0304

RAR Archive (rar),文件头:52617221

Wave (wav),文件头:57415645

AVI (avi),文件头:41564920

Real Audio (ram),文件头:2E7261FD

Real Media (rm),文件头:2E524D46

MPEG (mpg),文件头:000001BA

MPEG (mpg),文件头:000001B3

Quicktime (mov),文件头:6D6F6F76

Windows Media (asf),文件头:3026B2758E66CF11

MIDI (mid),文件头:4D546864

PE-Dateistruktur

PE-Dateien (Portable Execute) sind der allgemeine Begriff für ausführbare Dateien unter Windows, gebräuchlich sind DLL, EXE, OCX, SYS usw. Die Struktur von PE-Dateien ist im Allgemeinen wie in der folgenden Abbildung dargestellt: ausgehend von der Startposition dort sind DOS-Header, NT-Header, Abschnittstabelle und spezifische Abschnitte

1. DOS-Header

Die Rolle des DOS-Headers besteht darin, mit ausführbaren Dateien im MS-DOS-Betriebssystem kompatibel zu sein. Bei 32-Bit-PE-Dateien besteht die Rolle von DOS darin, eine Textzeile anzuzeigen, die den Benutzer auffordert: I need to run on 32 -Bit-Fenster. Ich denke, es ist ein guter Witz, denn es scheint nicht deaktiviert zu sein, tut es, es macht einfach nicht das, was der Benutzer unter DOS erwartet, nun, ich gebe zu, das ist nicht der Punkt. Aber lassen Sie uns zumindest einen Blick darauf werfen, wie dieser Header definiert ist:

Wir müssen uns nur auf zwei Bereiche konzentrieren:

e_magic: Ein WORD-Typ, der Wert ist eine Konstante 0x4D5A, verwenden Sie einen Texteditor, um den Wert von „MZ“ anzuzeigen, ausführbare Dateien müssen alle mit „MZ“ beginnen.

e_lfanew: Ein erweitertes Feld für ausführbare 32-Bit-Dateien, das verwendet wird, um den Offset des NT-Headers nach dem DOS-Header relativ zur Dateistartadresse anzugeben.

Zwei, NT-Kopf

Nach dem e_lfanew im DOS-Header können wir leicht den NT-Header finden, der der nützlichste Header in der 32-Bit-PE-Datei ist, der wie folgt definiert ist:


Die folgende Abbildung zeigt eine echte PE-Datei-Header-Struktur und den Wert jedes Felds:


Signatur: Ähnlich wie bei e_magic im DOS-Header sind die oberen 16 Bits 0, die unteren 16 Bits 0x4550 und die Zeichendarstellung ist 'PE'.

IMAGE_FILE_HEADER ist der Header der PE-Datei, und die Definition der Sprache c lautet wie folgt:

Die spezifische Bedeutung der einzelnen Felder ist wie folgt:

Maschine: Die Betriebssystemplattform der Datei, ob x86, x64 oder I64 usw., kann einer der folgenden Werte sein.


NumberOfSections: Wie viele Abschnitte gibt es in der PE-Datei, d. h. die Anzahl der Elemente in der Abschnittstabelle.

TimeDateStamp: Die Erstellungszeit der PE-Datei, die normalerweise vom Konnektor ausgefüllt wird.

PointerToSymbolTable: Offset der COFF-Dateisymboltabelle in der Datei.

NumberOfSymbols: Anzahl der Symboltabellen.

SizeOfOptionalHeader: Die Größe des folgenden optionalen Headers.

Eigenschaften: Die Eigenschaften der ausführbaren Datei, die das phasenweise ODER der folgenden Werte sein können.


Es ist ersichtlich, dass der Header der PE-Datei einige grundlegende Informationen und Attribute der PE-Datei definiert. Diese Attribute werden verwendet, wenn der PE-Loader lädt. Wenn der Loader feststellt, dass einige im Header der PE-Datei definierte Attribute nicht dem aktuellen Betrieb entsprechen Umgebung, wird das Laden des PE beendet.

Ein weiterer wichtiger Header ist der optionale PE-Header. Betrachten Sie seinen Namen nicht als optionalen Header. Tatsächlich fehlt er überhaupt nicht. Er ist jedoch auf verschiedenen Plattformen unterschiedlich. Zum Beispiel ist er IMAGE_OPTIONAL_HEADER32 unter 32-Bit , aber es ist IMAGE_OPTIONAL_HEADER32 unter 64-Bit Unten ist IMAGE_OPTIONAL_HEADER64. Der Einfachheit halber betrachten wir nur 32 Bit.

Magic: Gibt den Typ des optionalen Headers an. 

MajorLinkerVersion und MinorLinkerVersion: Die Versionsnummer des Linkers.

SizeOfCode: Die Länge des Codesegments, bei mehreren Codesegmenten ist dies die Summe der Längen der Codesegmente.

SizeOfInitializedData: Initialisierte Datenlänge.

SizeOfUninitializedData: Nicht initialisierte Datenlänge.

AddressOfEntryPoint: Die RVA des Programmeintrags, für die Adresse von exe kann sie als RVA von WinMain verstanden werden. Für eine DLL kann diese Adresse als RVA von DllMain verstanden werden, und wenn es sich um einen Treiber handelt, kann sie als RVA von DriverEntry verstanden werden. Natürlich ist der eigentliche Einstiegspunkt nicht WinMain, DllMain und DriverEntry, es gibt noch eine Reihe von Initialisierungen, die vor diesen Funktionen abgeschlossen werden müssen, diese stehen natürlich nicht im Mittelpunkt dieses Artikels.

BaseOfCode: Die RVA der Startadresse des Codesegments.

BaseOfData: RVA der Anfangsadresse des Datensegments.

ImageBase: Die Basisadresse des Bildes (in den Speicher geladene PE-Datei. Diese Basisadresse stellt einen Vorschlag dar. Wenn die DLL nicht an diese Adresse geladen werden kann, wählt das System automatisch eine Adresse dafür aus.

SectionAlignment: Abschnittsausrichtung. Wenn ein Abschnitt in PE in den Speicher geladen wird, wird er entsprechend dem durch dieses Feld angegebenen Wert ausgerichtet. Wenn dieser Wert beispielsweise 0x1000 ist, dann sind dies die unteren 12 Bits der Startadresse jedes Abschnitts 0.

FileAlignment: Abschnitte werden nach diesem Wert in der Datei ausgerichtet, und SectionAlignment muss größer oder gleich FileAlignment sein.

MajorOperatingSystemVersion, MinorOperatingSystemVersion: Die Versionsnummer des benötigten Betriebssystems, scheint bei immer mehr Betriebssystemversionen nicht mehr so ​​wichtig zu sein.

MajorImageVersion, MinorImageVersion: Die Versionsnummer des Bildes, die vom Entwickler angegeben und vom Linker ausgefüllt wird.

MajorSubsystemVersion, MinorSubsystemVersion: Die erforderliche Versionsnummer des Subsystems.

Win32VersionValue: reserviert, muss 0 sein.

SizeOfImage: Die Größe des Bildes, das die PE-Datei in den Speicherplatz lädt, ist fortlaufend, dieser Wert gibt die Größe des belegten virtuellen Speicherplatzes an.

SizeOfHeaders: Die Größe aller Dateikopfzeilen (einschließlich Abschnittstabellen), dieser Wert wird an FileAlignment ausgerichtet.

CheckSum: Die Prüfsumme der Bilddatei.

Subsystem: Das zum Ausführen der PE-Datei erforderliche Subsystem kann eine der folgenden Definitionen sein:

SizeOfStackReserve: Die Größe des Speichers, der zur Laufzeit für jeden Thread-Stapel reserviert ist.
SizeOfStackCommit: Die anfängliche Speichergröße jedes Threadstapels zur Laufzeit.

SizeOfHeapReserve: Die Laufzeit reserviert Speichergröße für den Prozessheap.

SizeOfHeapCommit: Die anfängliche Speichergröße des Prozessheaps zur Laufzeit.

LoaderFlags: reserviert, muss 0 sein.

NumberOfRvaAndSizes: Die Anzahl der Elemente im Datenverzeichnis, d. h. die Anzahl der Elemente im folgenden Array.

DataDirectory: Datenverzeichnis, das ein Array ist, und die Elemente des Arrays sind wie folgt definiert:


VirtualAddress: ist eine RVA.
Größe: ist eine Größe.

Wozu dienen diese beiden Zahlen? Das eine ist die Adresse und das andere die Größe.Es ist ersichtlich, dass dieser Datenverzeichniseintrag einen Bereich definiert. Welchen Bereich definiert er also? Wie bereits erwähnt, ist DataDirectory ein Array, und jedes Element im Array entspricht einer bestimmten Datenstruktur, einschließlich Importtabellen, Exporttabellen usw. Unterschiedliche Strukturen werden gemäß unterschiedlichen Indizes extrahiert, und jedes Element ist in der Header-Datei definiert welche Struktur darstellen, wie im folgenden Code gezeigt:

ELF-Dateistruktur

Die ELF-Datei besteht aus 4 Teilen, nämlich ELF-Header (ELF-Header), Programm-Header-Tabelle (Program Header Table), Abschnitt (Section) und Abschnitts-Header-Tabelle (Section Header Table). Tatsächlich enthält eine Datei nicht unbedingt den gesamten Inhalt, und ihre Positionen sind möglicherweise nicht wie gezeigt angeordnet, nur die Position des ELF-Headers ist festgelegt, und die Position, Größe und andere Informationen der anderen Teile werden durch die Werte bestimmt ​​in der ELF-Kopfzeile. zu entscheiden.

Tipp: Sie können einen Hexadezimal-Editor verwenden, um es anzuzeigen

Einführung in die Schale

Die Shell ist ein Programm in einigen Computerprogrammen, das speziell dafür verantwortlich ist, die Software vor illegaler Änderung oder Dekompilierung zu schützen.

Sie laufen im Allgemeinen dem Programm voraus, übernehmen die Kontrolle und erfüllen ihre Aufgabe, die Software zu schützen.

Normalerweise unterteilen wir Shells in zwei Kategorien, eine davon sind komprimierte Shells und die andere verschlüsselte Shells.

Komprimierte Hülle: 

Komprimierungs-Shells sind bereits in der DOS-Ära erschienen, aber zu dieser Zeit waren sie aufgrund der begrenzten Rechenleistung und des übermäßigen Dekomprimierungsaufwands nicht weit verbreitet.

Die Verwendung einer komprimierten Shell kann dazu beitragen, die Größe der PE-Datei zu reduzieren, den internen Code und die Ressourcen der PE-Datei zu verbergen und die Netzwerkübertragung und -speicherung zu erleichtern.

Im Allgemeinen gibt es zwei Arten von Komprimierungs-Shells, eine wird einfach verwendet, um gängige PE-Dateien zu komprimieren, und die andere verformt die Quelldatei stark, beschädigt den Header der PE-Datei schwer und wird häufig zum Komprimieren bösartiger Programme verwendet.

Gängige Kompressionsschalen sind: Upx, ASpack, PECompat

Verschlüsselungs-Shell:

Die Verschlüsselungshülle oder Schutzhülle wird mit verschiedenen Technologien angewendet, um eine Code-Rückwärtsanalyse zu verhindern, und ihre Hauptfunktion besteht darin, PE vor einer Code-Rückwärtsanalyse zu schützen.

Da der Hauptzweck der Verschlüsselungs-Shell nicht mehr darin besteht, Dateiressourcen zu komprimieren, ist das durch die Verschlüsselungs-Shell geschützte PE-Programm normalerweise viel größer als die ursprüngliche Datei.

Derzeit werden verschlüsselte Shells häufig in Anwendungen verwendet, die hohe Sicherheitsanforderungen haben und anfällig für Cracking sind, während gleichzeitig Schadprogramme verwendet werden, um das Erkennen und Töten von Antivirensoftware zu vermeiden (reduzieren).

Gängige Verschlüsselungs-Shells sind: ASProtector, Armadillo, EXECryptor, Themida, VMProtect

Schalenladevorgang:

1. Speichern Sie die Eingabeparameter 

① Speichern Sie den Wert jedes Registers, wenn der Packer initialisiert wird

② Nachdem die Ausführung der Shell abgeschlossen ist, stellen Sie den Wert jedes Registers wieder her

③Springen Sie schließlich zur ursprünglichen Programmausführung

Verwenden Sie normalerweise das Befehlspaar pushad / popad, pushfd / popfd, um die Szenenumgebung zu speichern und wiederherzustellen

2. Besorgen Sie sich die erforderliche Funktions-API

①In der Eingabetabelle der allgemeinen Shell gibt es nur die API-Funktionen GetProcAddress, GetModuleHandle und LoadLibrary

②Wenn andere API-Funktionen benötigt werden, ordnen Sie die DLL-Datei dem Adressraum des aufrufenden Prozesses über LoadLibraryA(W) oder LoadLibraryExA(W) zu.

③Wenn die DLL-Datei in den Adressraum des aufrufenden Prozesses gemappt wurde, können Sie die GetModuleHandleA(W)-Funktion aufrufen, um das DLL-Modul-Handle zu erhalten

④Sobald das DLL-Modul geladen ist, können Sie die GetProcAddress-Funktion aufrufen, um die Adresse der Eingabefunktion zu erhalten

3. Entschlüsseln Sie die Daten jedes Blocks 

① Zum Zweck des Schutzes des Quellprogrammcodes und der Daten wird jeder Block der Quellprogrammdatei im Allgemeinen verschlüsselt. Wenn das Programm ausgeführt wird, entschlüsselt die Shell diese Blockdaten, damit das Programm normal ausgeführt werden kann

②Die Shell wird im Allgemeinen blockweise verschlüsselt, blockweise entschlüsselt, und die entschlüsselten Daten werden wieder an der entsprechenden Speicherstelle abgelegt

4. Springen Sie zurück zum ursprünglichen Programmeinstiegspunkt 

①Vor dem Rücksprung zum Einstiegspunkt wird im Allgemeinen die ursprüngliche PE-Datei-Eingabetabelle (IAT) wiederhergestellt und die Verschiebungselemente (hauptsächlich DLL-Dateien) verarbeitet.

②Da die Shell beim Packen selbst eine Eingabetabelle erstellt, ist es notwendig, die Adressen aller Funktionen, die von jeder DLL eingeführt werden, erneut zu erfassen und sie in die IAT-Tabelle zu füllen

③ Nachdem die obige Arbeit erledigt ist, wird die Steuerung an das ursprüngliche Programm übertragen und weiter ausgeführt

Gemeinsames Werkzeug

1. Verhaltensanalyse-Tools

Tinder Sword (kann nicht in derselben Umgebung wie Sangfor EDR verwendet werden), procexp, processminer usw.

2. Shell-Check-Tool

ExefoPE, DetectItEasy

3. Dynamisches Analysetool

Ollydbg (kann nur 32-Bit-Programme analysieren), X64dbg, Windbg, gdb (Linux)

4. Statische Analysewerkzeuge

IDApro

5. Hilfswerkzeuge

HashMyFiles (berechnet den Hashwert der Datei)

010Editor (überprüfen Sie den hexadezimalen Zustand und ändern Sie ihn)

Auspacktool (spezielles Auspacktool je nach Schalentyp herunterladen)

Pwndbg (gdb-Plugin)

Supongo que te gusta

Origin blog.csdn.net/jd_cx/article/details/126494746
Recomendado
Clasificación