Assembler Tutorial - Grundlagen Und Theorie

15
Assembler–Tutorial Grundlagen und Theorie © Hubertus Loobert & seaw0lf (pdf-only) http://www.amok.notrix.de

description

assembler tut

Transcript of Assembler Tutorial - Grundlagen Und Theorie

  • AssemblerTutorialGrundlagen und Theorie

    Hubertus Loobert & seaw0lf (pdf-only)

    http://www.amok.notrix.de

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 2 - 06.11.1999

    Vorwort

    In diesem Tutorial werden wir Grundlagenarbeit betreiben. Diese besteht daraus, da wirBegriffe wie Register, oder Stack erlutern. Wir werden uns auch den Segmenten einesProgrammes zuwenden, in Bezug auf den 8086 bzw. den neueren Prozessoren mit Windows 9xals Betriebssystem. Dieses Kapitel habe ich leider noch in keinem Tutorial vorgefunden,obwohl es sehr viel zum Verstndnis eines Programmes auf der AssemblerEbene beitrgt.Doch genug fr den Anfang. Beginnen wir.

    Zahlensysteme und deren Darstellung

    Wie jeder PC Anfnger wei, kann der Computer nur mit Einsen oder Nullen umgehen. DiesesZahlensystem nennt man das Binr- oder Dualsystem. Weiterhin existieren dasDezimalsystem, welches uns am gelufigsten ist, und mit dem wir uns Tag fr Tagauseinandersetzten, sowie das HexadezimalSystem (auf der Basis der Zahl 16) und dasOktalSystem (auf der Basis 8). Ein genauere Einfhrung ist wohl eher uninteressant, daherlasse ich sie weg.

    Nur eine Sache sollt geklrt werden: Die Darstellung negativer Zahlen im Binrformat. Damitman eine Zahl im Binrformat mit einem Vorzeichen behaften kann, wurde folgende Lsungerdacht: Man bestimmt ein Bit, welches angibt, ob die Zahl - oder + ist. Dadurch verschiebtsich allerdings die Menge der darstellbaren Zahlen: So kann man mit einem 8 Bit groen Wert2^8 = 265 mgliche Zahlen darstellen. Somit lassen sich bei einem vorzeichenlosen Wert dieZahlen 0 - 255 darstellen. Doch sobald ein Vorzeichen Bit dazu kommt, hat man nur noch 7Bit brig (Das erste Bit, ist das Vorzeichen Bit). Somit bleiben folgende Zahlen brig:00000000-01111111 fr 0 bis 127; sowie 10000000-11111111 fr die Zahlen -1 bis -127.Somit geht zwar nicht direkt die Menge der darstellbaren Zahlen zurck, doch es verschiebtsich der Bereich von 0 bis 255 auf -127 bis 127.

    Will man nun eine positive Zahl in eine negative verwandeln, bildet man ein so genanntesZweiKomplement. Hierzu ein Beispiel: 5 ist im Dualsystem gleich 00000101. Um die Zahl -5darzustellen, dreht man jedes Zeichen um; so wird aus 00000101 11111010. Das ist einZweiKomplement.

    Es werden solche Begriffe wie Word (Wort) oder DWord (Doppelwort) vorkommen,daher mchte ich sie gleich klren:

    Byte: Ein 8 Bit groer Wert.

    Ein Byte ist folgender maen aufgeteilt:

    7 6 5 4 3 2 1 0

    Die Zhlung der Bits beginnt bei 0 und endet bei 7. Das 8. Bit (Bit Nr. 7) ist das Vorzeichenbit.

    Word: Ein 16 Bit groer Wert.

    DoubleWord (DWord): Ein 32 Bit groer Wert.

    QuadWord (QWord): Ein 64 Bit groer Wert.

    Integer: Ein vorzeichenbehafteter Wert, welcher die Gre von einem Byte, Word oderDWord haben kann.

    Arithmetische Operation: Eine der 4 Grundrechenarten: Addition, Subtraktion, Multiplikationoder Division.

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 3 - 06.11.1999

    Noch zu beachten:

    In SoftICE und W32DASM werden Zahlen in hexadezimaler Schreibweise dargestellt.

    Wenn in Assembler eine Zahl in einer eckigen Klammer ( '[' und ']' ) steht, so wird diese alsZeiger (Pointer) auf eine Speicherstelle interpretiert.

    AssemblerBefehle folgen dem Syntax , .

    Operanden werden durch eine Komma getrennt.

    Die Register

    Ein Register ist ein Teil des Prozessors, welcher Daten beinhaltet. Diese Daten dienen demProzessor dazu, um auf der eine Seite die vom Programmierer angeordneten Operationendurchzufhren und auf der anderen Seite, um ein Programm berhaupt zum Laufen zubringen. Der Prozessor hlt ab dem 80386 16 Register zur Programmierung bereit. Intelunterteilt die Register wie folgt (beschrieben im Intel Architecture Software DeveloperManual):

    General-purpose data registers (Allzweckregister)

    EAX accu register AkkumulatorEBX base register BasisregisterECX counter register ZhlregisterEDX data register DatenregisterESI source index register QuellIndexEDI destination index register ZielIndexEBP base pointer register BasiszeigerESP stack pointer register StackZeiger

    Segment registers (Segmentregister)

    CS code segment registerDS data segment registerES extra segment registerSS stack segment register

    FS help segment 1 registerGS help segment 2 register

    Status & control registers (Status- und Kontrollregister)

    EFLAGS EFLAGSRegister (FlagRegister)EIP instruction pointer register (Befehlszeiger)

    Das FlagRegister hat eine besondere Bedeutung, und wird gleich gesondert behandelt. Dahergelten die folgenden Aussagen nicht fr dieses Register.

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 4 - 06.11.1999

    Die Gre der Register

    Smtliche Allzweckregister sowie die Status- und Kontrollregister haben eine Gre von 32 Bit(Gekennzeichnet durch das 'E' am Anfang). Die Segmentregister sind nur 16 Bit gro. Alle 32Bit groen Register lassen sich aber auch als 16 Bit Register ansprechen, indem man das 'E'am Anfang des Krzels weglt. Die ersten 4 Register besitzen auerdem noch eineBesonderheit (deswegen der Absatz): Sie lassen sich zustzlich als zwei 8 Bit Registeransprechen. Das heit folgendes:

    EAX Ein maximal 32 Bit groer Wert kann in diesem Register gespeichert werden.AX Bedeutet, da nur die ersten 16 Bit gemeint sind.

    Diese beiden Mglichkeiten der Behandlung haben alle 32 Bit Register gemeinsam. Die beidenfolgenden weiteren Mglichkeiten beschrnken sich auf EAX, EBX, ECX und EDX.

    AL Dies sind nur die ersten 8 Bit des Registers. ('L' steht fr low).AH Dies sind die zweiten 8 Bit des Registers. ('H' steht fr high).

    Die Verwendung bzw. die Aufgaben der Register

    Die Allzweckregister

    Die ersten 4 Allzweckregister sind die, mit denen der Programmierer am hufigsten arbeitet.Sie knnen beliebig kombiniert werden. Doch jedes dieser Register hat spezielleAufgabengebiete, die durch Befehle deutlich gemacht werden.

    EAX Diese Register dient hauptschlich fr arithmetischen OperationenEBX EBX ist dazu gedacht, um auf Speicherstellen zu zeigenECX ECX wird bei Schleifen eingesetztEDX I/O Zeiger

    Diese Aufgaben durch Beispiele darzustellen, halte ich an diesem Punkt fr falsch, denn dafrbentigt man weiteres Wissen, welches erst spter dazu kommt. Daher lassen wir es, undgehen zu den nchsten Registern.

    Die vier weiteren Register dienen dazu um auf spezielle Bereiche in einem Segment (was dasist, wird gleicht behandelt) zu zeigen. Da das Wissen noch fehlt, um diese Sachen genauer zuerlutern sei nur folgendes gesagt: ESI und EDI sind die einzigen weiteren Register, diemanchmal vom Programmierer wie EAX, EBX, ECX, oder EDX eingesetzt werden knnen. ESPund EBP haben spezielle Aufgaben, die im Kapitel ber den Stack behandelt werden.

    Die Segmentregister

    Auch fr diese Register gilt, da sie erst im spteren Teil behandelt werden knnen.

    Status- und Kontrollregister

    Das FlagRegister wird ausfhrlich im Kapitel Flags behandelt werden. Das EIP Register istvielleicht das wichtigste Register fr den Prozessor, da es auf die Stelle im Speicher zeigt,welches den nchsten Befehl beinhaltet. EIP ist fr den Programmierer recht uninteressant, daman es nur indirekt beeinflussen kann.

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 5 - 06.11.1999

    FlagRegister

    Einige werden sich vielleicht wundern, warum ich diesem Register ein eigenes Kapitel widme.Doch das ist gerechtfertigt, wie wir gleich sehen werden.

    Ein Flag ist, wie der Name schon sagt eine Flagge, die etwas signalisiert. Das FlagRegister ist32 Bit gro, und kann damit 32 mal 'ja' oder 'nein' sagen, in Form von einer 0 fr ein 'nein'bzw. fr eine nichtgesetzte Flagge; oder in Form von einer 1 fr ein 'ja', bzw. fr einegesetzte Flagge.

    Doch wozu diese Flaggen? Ganz einfach: Sie dienen dazu um den Ausgang bestimmterOperationen anzuzeigen, oder bestimmen das Verhalten des Prozessors, bei besonderenAktionen.

    Es ist zwar mglich mit dem Register 32 Flaggen zu besetzten, doch es gibt nur 17 Stck. Dieanderen Bits sind reservierte Positionen und drfen nicht genutzt werden. Und auch vondiesen 17 Flags sind fr uns nur einige relevant, nmlich 9 Stck. Diese 9 sind folgende:

    OF DF IF TF SF ZF AF PF

    OF Overflow FlagDF Direction FlagIF Interrupt Enable FlagTF Trap FlagSF Sign FlagZF Zero FlagAF Auxiliary Cary FlagPF Parity FlagCF Carry Flag

    Die Bedeutung der Flags

    Was die Flags im einzelnen bedeuten, oder bewirken, mchte ich natrlich niemandemvorenthalten: Allerdings ist das Parity Flag, Trap Flag und das Interrupt Enable Flag rechtuninteressant fr einen Cracker, und daher werden sie nur kurz angeschnitten. Und auch dieanderen Flags sind nur selten fr einen Cracker wirklich wichtig (ausgenommen das ZeroFlag), trotzdem werden sie behandelt, damit im Fall der Flle man immer noch auf diesesDokument zurckgreifen kann.

    In dem folgenden Abschnitt werden leider solche Begriffe wie StringOperationen undInterrupt benutzt. Diese werden nicht erklrt (Um bestimmte Befehle, oder Befehlsarten zuverstehen ist es Empfehlenswert, sich ein Buch darber zu besorgen), trotzdem mssen siebenutzt werden, um die Funktionen der Flags zu klren. Ein Anfnger sollte sich nicht davonabhalten lassen, das trotzdem zu lesen, da doch einiges erklrt wird, was auch ohneVorwissen zu verstehen ist.

    Das Carry Flag (bertrageFlag)

    Diese Flag wird gesetzt, wenn nach einer arithmetischen Operation ein berlauf statt gefundenhat. Wenn man z.B. zwei 8 Bit Werte wie 100 und 200 addiert, ist das Ergebnis 300. Doch dieZahl 300 bersteigt, die mgliche Anzahl der darstellbaren vorzeichenlosen Zahlen um 45. Um300 darzustellen bentigt man 9 Bit. Damit diese Zahl nicht verloren geht, wird das CarryFlag gesetzt; somit erhlt man die 9 Bit (8 Bit, das normale Byte + das Carry Flag).

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 6 - 06.11.1999

    Das Parity Flag (ParittsFlag)

    Diese Flag dient zur Fehlerberprfung bei einer Datenbertragung auf eine serielleSchnittstelle.

    Das Auxiliary Cary Flag (bertrageHilfsFlag)

    Dieses Flag ist gesetzt wenn ein bertrag von Bit 3 (das 4. Bit, da das 1. Bit, Bit 0 ist) auf Bit4 erfolgt ist. Es wird im Umgang mit dem BCDSystem benutzt. Dieses Zahlensystem wirdhier nicht behandelt, da es im PC-Bereich kaum Verwendung findet.

    Das Zero Flag (NullFlag)

    Dieses Flag ist zweifellos das wichtigste fr einen Cracker, und wahrscheinlich auch daswichtigste fr einen Assembler Programmierer. Dieses Flag zeigt an, ob das Ergebnis einerOperation Null ist, oder nicht. Falls es Null ist, ist das Zero Flag gesetzt, falls das Ergebnisungleich Null ist, wird es nicht gesetzt. Eine wichtige Benutzung des Zero Flag aus der Sichteines Crackers ist sicherlich, wenn aus einem Unterprogramm der Rckgabewert ermitteltwird. Doch das ist fr den Anfnger noch nicht so interessant.

    Das Sign Flag (VorzeichenFlag)

    Dieses Flag ist gesetzt, wenn das Ergebnis einer arithmetischen oder logischen Operationnegativ ist. Falls das Ergebnis positiv ist, ist das Flag nicht gesetzt.

    Das Trap Flag (EinzelSchrittFlag)

    Dieses Flag (falls es gesetzt ist) versetzt den Prozessor in einen Zustand, wo er jeden Befehleinzeln ausfhrt (tut er ja sowieso) und danach den Interrupt 1 aufruft. Dadurch ist es mglichDebugger einzusetzen, um dem Programmierer z.B. bei der Fehlersuche, erheblich seineArbeit zu erleichtern.

    Das Interrupt Enable Flag (UnterbrechungsFlag)

    Dieses Flag gibt an, ob das Programm durch Interrupts, z.B. von der Tastatur unterbrochenwerden darf. Falls es gesetzt ist, kann das Programm unterbrochen werden. Falls es nichtgesetzt ist, lt der PC keine Unterbrechung des Programms zu.

    Das Direction Flag (RichtungsFlag)

    Diese Flag gibt die Richtung bei sogenannten StringOperationen an. Falls es gesetzt ist, wirddie StringVerarbeitung nach aufsteigenden Adressen durchgefhrt. Falls es nicht gesetzt ist,wird die StringVerarbeitung nach absteigenden Adressen durchgefhrt.

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 7 - 06.11.1999

    Das Overflow Flag (berlaufsFlag)

    Dieses Flag ist gesetzt, wenn das Vorzeichenbit durch eine arithmetische Operation zerstrtist.

    Noch etwas zu negativen und positiven Zahlen

    Wie wir ganz am Anfang gelernt haben, wird die Darstellung von negativen und positivenZahlen im Dualsystem durch ein Vorzeichenbit gelst. Doch woher soll der Prozessor wissen,ob er bei einer Addition das Bit 7 (oder das Bit 15, oder Bit 31) als Vorzeichen, oder als Teileiner Zahl, die kein Vorzeichen hat behandeln soll. So kann 10011010 gleich 154 oder -102sein. Der Prozessor kennt den Unterschied nicht. (In SoftICE wie folgt zu berprfen: Wennein Register grer als 80000000h ist, so kann man sich durch den Befehl '? 'den Wert des Registers in Hex und Dezimal anzeigen lassen. Dadurch das der Wert desRegisters mindestens 80000000h ist, wird hinter der Dezimal Zahl noch eine weitere Zahl inKlammern angezeigt. Diese Zahl ist negativ, da SoftICE bei ihr das hherwertigste Bit alsVorzeichen interpretiert hat. Da SoftICE genauso wenig wie der Prozessor wei, ob die Zahlmit Vorzeichen oder ohne gedacht war, mu SoftICE beides in Betracht ziehen und zeigt beideMglichkeiten an.) Doch was soll das Ganze dann, wenn der Prozessor den Unterschied nichtkennt? Ganz einfach: Es kommt auf den Befehl an. So z.B. fhrt der Befehl MUL eineMultiplikation durch, ohne dabei auf das hherwertigste Bit zu achten. Im Gegensatz zu IMUL,wo das hherwertigste Bit als Vorzeichen gewertet wird.

    Die Segmente

    Die Segmente beim 8086

    Einige werden sich jetzt vielleicht Fragen, warum nehmen wir hier die Segmente beim 8086durch, wobei doch in der heutigen Zeit dieser Prozessor hoffnungslos veraltet ist. Die Antwortist relativ einfach: Das was wir jetzt besprechen gilt heute immer noch. Also aufgepat.Im vorherigen Abschnitt habe ich bei den SegmentRegistern darauf verwiesen, da wir dieseerst spter behandeln. Und jetzt ist spter. Wenn ich hier von Registern spreche, mu mannoch folgendes Wissen: Beim 8086 gab es noch keine 32 Bit groen Register, sondern eswaren alle 16 Bit gro. Das bedeutet es gab kein Register mit dem Namen EAX, sondern AX.

    Der Bus

    Beim 8086 gibt es folgende Busse: Der Steuerbus, der Adrebus und der Datenbus. Davoninteressieren uns nur der Adrebus und der Datenbus. Der Steuerbus dient nur zur Regelungder Datenbertragung am Computer (nicht, das es nicht wichtig wre, aber er ist fr uns nichtrelevant im Bezug auf die Segmente).Beim 8086 ist der Adrebus 20 und der Datenbus 16 Bit breit. Und das ist nicht gut. DerAdrebus dient dazu eine Speicherstelle im Arbeitsspeicher zu adressieren. Der Adrebus ist20 Bit breit und 2^20 ergibt 1048576 Byte bzw. 1024 KB und dies wiederum ist 1 MB. Damitwre klar, da der 8086 maximal ein MB ansprechen konnte. Von der Adresse 0 bis 1048575.Der Datenbus hat wiederum die Aufgabe den Inhalt der Stelle im RAM, der vom Adrebusdefiniert worden ist, zu transportieren; entweder zum Prozessor hin, und von ihm weg. Dabeitransportiert er Code (also ausfhrbare Befehle) und Daten (Informationen, welches dasProgramm bentigt, um mit den Befehlen vernnftig zu arbeiten).

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 8 - 06.11.1999

    Das Problem

    Okay, wir haben einen 20 Bit groen Adrebus und einen 16 Bit groen Datenbus. Dadurchknnen die Register maximal 16 Bit gro sein. Eine Adresse, auf die man mittels des Adrebuszugreifen will, mu ja irgendwo gespeichert sein. Und dies irgendwo sind die Register. Dochwie will man mit einem 16 Bit groem Wert voll auf 20 Bit (= 1 MB) zugreifen? Genau das istdas Problem. Wenn wir z.B. auf die Adresse 10000h zugreifen wollen, welche 20 Bit zurDarstellung bentigt, so ist es nicht mglich diese Zahl in einem Register zu speichern, da einRegister beim 8086 maximal 16 Bit gro ist.

    Die Lsung

    Dieses Problem bedarf einer Lsung, die wie folgt aussah: Man benutzt 2 Register. Dies klingtnicht sehr einfallsreich; doch wie wir jetzt sehen werden, ist es nicht ganz so einfach. Wirhaben einen Adreraum vom 1 MB (= 1024 kB). Um diese 1 MB sinnvoll aufzuteilen auf 2Register, dividierte man 2^20 (= 1024 KB; die maximale Gre des Adreraums) durch 2^16(die maximale Gre eines Registers) und erhlt 16. Somit war klar, da man den Adreraumin Blcke zu je 16 Byte aufteilte. Das bedeutet, da der Adreraum ab sofort nicht mehr nur1024 KB gro ist, sondern auch aufgeteilt ist in Blcke zu je 16 Byte. Diese Blcke heienParagraphen. Doch wieviele dieser Paragraphen gibt es denn? Ganz einfach: Man dividiert die2^20 durch 16, und bekommt die Zahl 65.536.Nochmals zusammengefat: Man teilte den Adreraum in Segmente auf, die je mindestens 16Byte gro sind, deren Anzahl 65.535 betrgt. Soweit, so gut. Solch eine Zahl, die zwischen 0und 65.535 gro sein kann, wird in den SegmentRegistern gespeichert. Also CS, DS, ... .Doch das konnte ja nicht alles sein, denn mit Hilfe von diesen SegmentRegistern, konnteman sich zwar im Adreraum im Abstand von 16 Byte "bewegen", doch man mute ja jedeseinzelne Byte explizit ansprechen knnen (und nicht nur jedes 16.). An diesem Punkt kommendie sogenannten OffsetRegister ins Spiel. Durch dieses zweite Register kann man sichinnerhalb eines Segmentes bewegen. Denn es gibt den Abstand vom Beginn des Segments(welcher, wie wir ja wissen in den SegmentRegistern gespeichert ist), bis zu dergewnschten Speicherstelle an. Dieses OffsetRegister ist der Zeiger auf den SegmentInhalt.

    Somit erhalten wir eine Methode, bei der wir mit 2 Registern jede Stelle in dem 1 MB groenAdreraum ansprechen knnen.

    Die Segmentregister

    Wir haben besprochen, wie die Segmentierung funktioniert, nun mssen wir noch dieAufgaben der Segmentregister klren. Es existieren folgende Segmentregister (wie wir amAnfang schon gelernt haben):

    CS code segment registerDS data segment registerES extra segment registerSS stack segment register

    FS help segment 1 register (erst ab dem 80386 vorhanden)GS help segment 2 register (erst ab dem 80386 vorhanden)

    Die Aufgaben der Register CS und DS sind wohl klar: In ihnen ist die SegmentGrenze einmalfr den Code und einmal fr die Daten gespeichert. Das stack segment register beinhaltetdie SegmentGrenze fr den Stack, welcher in einem extra Kapitel behandelt wird. Das extrasegment register wird bei StringOperationen benutzt. Die help segment register dienen zurweiteren Aufnahme, und finden meines Wissens nach kaum Beachtung.

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 9 - 06.11.1999

    Der Leser, der die Segmentierung verstanden hat, wird sich jetzt fragen, welche die dazugehrigen OffsetRegister sind. Diese sind nur zweimal klar definiert: Nmlich fr das codesegment register, welches als OffsetRegister das IP (EIP) Register hat. Und fr das stacksegment register ist das SP (ESP) Register zustndig. Fr die brigen Register kommt es aufden Befehl an, von dem es dann abhngt, welches andere Register den OffsetAnteil bildet.

    Glossar / Zusammenfassung

    Das Kapitel ber die Segmente beim 80386 ist sicherlich eines der schwierigeren Sorte,deshalb folgt jetzt noch einmal so etwas wie eine Zusammenfassung, mit einer nherenErklrung:

    Segment

    Ein Segment ist mindestens 16 Byte gro, kann aber bis zu 65.536 Byte gro sein. Das hngtdamit zusammen, da ein OffsetRegister (welches 16 Byte gro ist) einen maximalen Wertvon 2^16 aufnehmen kann. Wenn dies der Fall ist, wird die nchste SegmentGrenzeberschritten, und kann somit das Segment auf den Wert von 65.536 Byte erhhen.

    SegmentGrenze

    Die Zahl, die in einem Segmentregister gespeichert wird, nennt man SegmentGrenze, da esauf den Anfang eines Segmentes zeigt.

    Adresse

    Die Adresse einer Speicherstelle wird in einem Segmentregister und einem OffsetRegistergespeichert, welcher folgender Notation folgt: SEGMENTREGISTER : OFFSETREGISTER. z.B.merkt sich der Prozessor ber die Registerkombination CS:IP (ab dem 80386 CS:EIP) welchenBefehl er als nchstes ausfhren mu. Die physikalische Adresse bekommt man indem manden Wert im Segmentregister * 16 nimmt (da man den Adreraum in Blcke zu je 16 Byteaufgeteilt hat) und den Wert im OffsetRegister hinzu addiert. Daraus folgt: Adresse = 16 *Segment + Offset.

    Offset(Register)

    Der OffsetAnteil einer Adresse wird im OffsetRegister gespeichert. Ein OffsetRegister ist einZeiger um sich innerhalb eines Segmentes zu "bewegen". Der OffsetAnteil einer Adresse wirdzu der SegmentGrenze hinzu addiert.

    Physikalische Adresse

    Eine physikalische Adresse ist eine wahre Adresse im Speicher. Eine normale Adressebesteht aus einem Segmentregister, und einem OffsetRegister. Daraus lt sich einephysikalische Adresse errechnen. (siehe Adresse)

    Die Segmente ab dem 80386

    Das was wir gerade besprochen haben war nicht sinnlos, da diese Regeln heute fr DOSProgramme immer noch gelten. Doch derjenige der sich am letzten Teil fast die Zhneausgebissen hat, wird jetzt froh sein, denn fr Windows Programme geltendiese Regeln nicht mehr.

    Der Bus und dessen Auswirkungen

    Es gibt immer noch einen Adrebus und einen Datenbus, doch sind seit dem 80386 beidegleich gro. Das bedeutet, da man mit einem Adrebus von 32 Bit maximal 2^32 Byteansprechen kann. Dies sind 4 GB. Da nun auch der Datenbus 32 Bit gro ist, braucht man

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 10 - 06.11.1999

    keine Segmente mehr. Es existiert nun ein "flat memory model". Dieses neue Speichermodellhat zur Folge, da alles linear ist. Doch wozu werden dann noch die Segmentregister bentigt,die ja noch da sind, und sogar Zuwachs bekommen haben mit FS und GS. Das hat folgendenGrund: Die 4 GB Adreraum, die jedes Programm besitzt sind virtuell. Dies bedeutet, da dasBetriebssystem mit Adressen arbeitet, die gar nicht existieren. Und das Betriebssystem istdafr verantwortlich, da die aktuellen Daten im physikalischen Speicher zur Verfgungstehen. Um dies zu bewerkstelligen braucht Windows sogenannte Deskriptoren. In diesenDeskriptoren stehen Informationen die Windows dazu bentigt, wie z.B.Zugriffsberichtigungen. Genau an diesem Punkt kommen die Segmentregister ins Spiel; siezeigen nmlich auf die Deskriptoren. Doch diese Vorgnge sind fr eine Crackeruninteressant. Es ist nur wichtig zu wissen, da mit Windows ein "flat memory model"eingefhrt wurde. Die Segmentregister knnen somit beim Cracken auer acht gelassenwerden. (Wer sich trotzdem fr diese Vorgnge interessiert, findet Informationen im IntelArchitecture Software Developer`s Manual im Abschnitt Protected-Mode MemoryManagement.)

    Der Stack

    Der Stack allgemein

    Der Stack ist ein wichtiger Bestandteil eines Programmes. Er ist so wichtig (und sovollkommen unbekannt in den CrackingTutorials), da ich ihm ein eigenes Tutorialgewidmet habe. Ich werde ihn hier ausfhrlich behandeln, da er sehr wichtig ist im Bezug auf'API Funktionen'. Das StackEnde findet man zu jeder Zeit in der Registerkombination SS:ESP.(Das Segmentregister SS, und das OffsetRegister ESP).

    Der Stack ist eine Art Ablageplatz. Dort knnen Daten gespeichert werden. Dies mu man zumBeispiel manchmal vor dem Aufruf eines Unterprogrammes tun, um die Inhalte wichtigerRegister zu "retten", die sonst im Laufe des Unterprogrammes verloren gehen wrden. Durchden Befehl PUSH kopiert man einen Wert auf den Stack; durch den Befehl POP holt man einenWert wieder herunter. Mit dieser Erklrung knnte man sich zufrieden geben. Doch daswerden wir nicht.

    Was also passiert wenn man z. B. mittels des Befehls PUSH EAX (Der Befehl PUSH erwartetnatrlich eine Angabe, was er auf den Stack kopieren soll. Diese Angabe wird immer nach demBefehl gemacht.) Durch diesen Befehl verndert sich der Zeiger des Stack. Danach zeigt ernmlich auf den Inhalt von EAX.

    Vor dem Befehl:

    ???

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 11 - 06.11.1999

    Doch nicht nur der Programmierer sondern auch der Prozessor nutzt den Stack. Bei einemAufruf von einem Unterprogramm durch den Befehl "CALL " wird die Adresse aufden Stack gepusht, an welcher der Prozessor nach dem Beenden des Unterprogrammesseine Arbeit fortsetzt. Jetzt werden vielleicht, die welche bereits etwas mehr AssemblerErfahrung haben sagen, da der Prozessor EIP auf den Stack kopiert, und somit die Adressebewahrt, an der er spter seine Arbeit fortsetzt. Doch einmal kurz nachgedacht, erkennt man,da das in einer EndlosSchleife enden mu. So darf der Prozessor beim CALL Befehl nichtEIP auf den Stack kopieren, sondern die darauf folgende Adresse. Nach einem CALL Befehlsieht der Stack so aus:

    . ; Vorherige Daten.

    .

    .

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 12 - 06.11.1999

    Doch eins nach dem anderen. Nach den ersten beiden Befehlen, sieht unser Stack so aus:

    EIP ; Die Rcksprung Adresse, wo das Programm spter; fortgesetzt wird.

    EBP=> EBP EBP ; Der gesicherte Wert..

    . ; Freier Speicher.

    .

    .

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 13 - 06.11.1999

    Die Gre des StackRahmens, der durch den Befehl ENTER, oder durch diegleichbedeutende Befehlssequenz erzeugt wurde, ist nicht statisch, sondern kann, und wirdauch sehr hufig verndert; und zwar durch die blichen Befehle PUSH bzw. POP.

    Parameterbergabe

    Die Einrichtung bringt einen Vorteil: ber das Register EBP kann man jederzeit auf lokaleDaten zugreifen, und zwar indem man zu EBP einfach einen bestimmten Wert addiert odersubtrahiert. Und dies geschieht so: Bei Hochsprachen werden die Parameter fr eine Funktion,ber den Stack bergeben; dies bedeutet, da diese vorher mittels des Befehls PUSH auf denStack kopiert werden. Dazu ein Beispiel:

    PUSH EAX ; Der erste Parameter wird kopiert.PUSH EBX ; Der zweite Parameter wird kopiert.PUSH ECX ; Der dritte Parameter wird kopiert.PUSH EDX ; Der vierte Parameter wird kopiert.CALL ?????? ; Die Funktion wird aufgerufen.

    Diese Funktion wird in diesem Beispiel mit 4 Parametern aufgerufen. Danach erfolgt dieEinrichtung eines StackRahmens, wie oben besprochen. Danach sieht der Stack wie folgt aus:

    EAX ; Unsere vier Parameter.EBXECXEDXEIP ; Die RcksprungAdresse.EBP=>EBP ; EBP zeigt auf den gesicherten Wert..

    .

    .

    .

    .

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 14 - 06.11.1999

    So sieht natrlich kein richtiger ASMCode aus, er sollte nur noch einmal klarmachen, wieParameter bergeben werden. In Wirklichkeit wrden die Parameter in Form von Registern,oder Zeigern bergeben werden. Diese Regel gilt vor allem fr API Funktionen. Bei APIFunktionen werden die Parameter immer in umgekehrter Reihenfolge auf den Stack gepusht(also bergeben) als es der Programmierer angibt.

    Um das Kapitel vom Stack abzuschlieen fehlt nur noch eine Sache: Das Bereinigen desStack. Wenn ein Unterprogramm die Parameter auf den Stack pusht und dasUnterprogramm greift auf diese Parameter ber EBP zu, bedeutet das, da diese Werte nichtvom Stack wieder herunter genommen wurden; und das der Stack weiterhin diese Wertebesitzt. Dazu ein Beispiel:

    PUSH EAX ; ParameterPUSH 006PUSH EBXCALL ?????? ; Das Unterprogramm

    Das Unterprogramm sieht so aus:

    ?????: PUSH EBP ; Erzeugung des StackRahmensMOV EBP, ESPSUB ESP, 100.

    .

    .

    .

    MOV ESP, EBP ; Lschen des StackRahmensPOP EBPRET ; Rcksprung aus dem Unterprogramm

    Das bedeutet doch, da nachdem das Unterprogramm beendet ist, SS:ESP immer noch aufden letzten bergebenen Parameter zeigt. Dies mu bereinigt werden, da diese Werte nichtmehr bentigt werden. Und dies geschieht indem ein Wert zu ESP addiert wird, der bewirktda ESP wieder auf die Stelle zeigt bevor die Parameter auf den Stack gepusht wurden. Wiegro dieser Wert ist, hngt davon ab, wieviele Parameter bergeben wurden. Die Anzahldieser Parameter * 4, da ESP immer um 4 verringert wird. Bei unserem Beispiel wre das diezahl 0Ch (= 12). Also wrde unser Beispiel so aussehen:

    PUSH EAX ; ParameterPUSH 006PUSH EBXCALL ?????? ; Das UnterprogrammADD ESP, 0C ; Reinigung des Stacks

    Diese beschriebene Vorgehensweise gilt nur fr C/C++ Programme. AndereProgrammiersprachen gehen unter Umstnden anders vor. Eine weitere Mglichkeit bestehtdurch den RET Befehl. Dieser oben beschriebene Befehl, kann auch eine solche Bereinigungdes Stack durchfhren, indem man dem Befehl einen Operand hinzufgt. Dieser Operand gibtan, um wieviel Bytes der Stack gereinigt werden soll. Somit wrde sich bei unserem Beispieldiesmal das Unterprogramm ndern:

    ?????: PUSH EBP ; Erzeugung des StackRahmensMOV EBP, ESPSUB ESP, 100.

    .

    .

    .

  • AssemblerTutorial Hubertus Loobert & seaw0lf (pdf-only)Grundlagen und Theorie http://www.amok.notrix.de

    - 15 - 06.11.1999

    MOV ESP, EBP ; Lschen des StackRahmensPOP EBPRET 0C ; Reinigung des Stack und Rcksprung aus dem

    ; Unterprogramm

    Wenn der RET Befehl diese Reinigung durchfhrt, ist die Addition von 0Ch nach dem CALLnatrlich nicht mehr ntig, und entfllt.

    Damit ist das Kapitel ber den Stack abgeschlossen.

    Etwas bers Cracken und der Schlu

    Wenn Sie sich alle Kapitel aufmerksam durchgelesen haben, so besitzen Sie eine solideGrundlage frs Cracken. Die einzelnen Kapitel fhren teilweise weiter in Assembler hinein,als da Sie es jemals beim Cracken brauchen knnten, doch dies lt sich nicht vermeiden,wenn man die Zusammenhnge verstanden haben will. Das Cracken konzentriert sichheutzutage auf Win9x/NT Programme. Daher kurz noch eine Erklrung dazu:

    Das Cracken eines Programmes unter Win9x und NT setzt zu 99% auf das Windows API. Ichkann mir sicherlich vorstellen, da einige Cracker oder die, die von sich solches behaupten,noch nie etwas davon gehrt haben.API steht fr "application programming interface". Und um das zu erklren folgenderAusschnitt aus der MSDNBibliothek:

    API

    Eine Reihe von Routinen, die eine Anwendung verwendet, um systemnahe Diensteanzufordern und aufzurufen, die dann vom Betriebssystem eines Computers bereitgestelltwerden. Bei Computern mit einer grafischen Benutzeroberflche verwaltet ein API die Fenster,Symbole, Mens und Dialogfelder einer Anwendung.

    Wem noch immer nicht klar ist was das API ist nochmals: Diese Funktionen sind imBetriebssystem integriert, so da sie jeder Programmierer nutzen kann. Diese Funktionenerleichtern dem Programmierer seine Aufgaben ungemein, denn er kann so immer wieder aufvorgefertigte Mens und Dialogboxen zurckgreifen. Und dies benutzen alle Cracker alsEinstiegsPunkt fr ihre Cracks.

    Diese API Funktionen sind sehr wichtig, und daher sollte man sich eine Referenz darberbesorgen.

    Schlu

    Ich hoffe das Lesen hat Spa gemacht und ihr Wissen erweitert.

    Ich bin zu erreichen [email protected]

    Formatierung, Korrekturen & PDFUmsetzung:[email protected]

    Hubertus Loobert,13.10.1999

    VorwortZahlensysteme und deren DarstellungDie RegisterGeneral-purpose data registers (Allzweckregister)Segment registers (Segmentregister)Status & control registers (Status- und Kontrollregister)Die Gre der RegisterDie Verwendung bzw. die Aufgaben der RegisterDie AllzweckregisterDie SegmentregisterStatus- und Kontrollregister

    FlagRegisterDie Bedeutung der FlagsDas Carry Flag (bertrageFlag)Das Parity Flag (ParittsFlag)Das Auxiliary Cary Flag (bertrageHilfsFlag)Das Zero Flag (NullFlag)Das Sign Flag (VorzeichenFlag)Das Trap Flag (EinzelSchrittFlag)Das Interrupt Enable Flag (UnterbrechungsFlag)Das Direction Flag (RichtungsFlag)Das Overflow Flag (berlaufsFlag)

    Die SegmenteDie Segmente beim 8086Der BusDas ProblemDie LsungDie Segmentregister

    Der Stack bei HochsprachenParameterbergabeSchlu