(Multi)Pointer

  • Allgemein

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von hate_regex.

    (Multi)Pointer

    Servus!

    Wie die Überschrift schon sagt, eine grundlegende Frage zu Pointern.
    Oft gibt es innerhalb des Speicherbereichs eines Process Multipointer. Diese verweisen mit unterschiedlichen Offsets auf eine BaseAdress.
    Nun frage ich mich: Warum und was verweißt da auf einen Zielbereich? Warum kann ein einzelner Pointer (eine BaseAdress) aus mehreren tausend Multipointern bestehen?

    Wenn ich beispielsweise eine Konstante habe auf die immer wieder zugegriffen wird macht das ja Sinn, aber in der Masse?
    Werden Speicherbereiche/Pointer wieder freigegeben, oder bleiben zur Laufzeit bestehen (oder ist das rein anwendungsabhängig?).

    Vielen Dank für die Aufklärung :)
    Hi
    naja, IntPtr kann als Zeiger angesehen werden. In der Sprache selbst sind Zeigerarithmetik, Zugriff, etc. nicht verankert, außer über Marshal. Aber was soll bitte ein Multipointer sein? Ein Zeiger auf mehere Zeiger? Ein Zeiger ist ja eigentlich nur eine Zahl, die in einem bestimmten Kontext eine Speicheradresse bereitstellt.
    Eine Basisadresse kannst du dir als Referenzadresse vorstellen, relativ zu der andere Zeiger berechnet werden können - eben über die Addition eines Offsets.
    Speicherbereiche werden in .Net von der Garbage Collection bereitgestellt und wieder freigegeben, da hast du keinen direkten Zugriff drauf, .Net macht das eh anders als z.B. C (++). Da bist du für die Speicherverwaltung selber zuständig und bestimmst den Freigabezeitpunkt. Analog wären übrigens System.Runtime.InteropServices.Marshal.AllocHGlobal und FreeHGlobal bzw. AllocCoTaskMem und FreeCoTaskMem (wenn ich mich richtig an die Benennung erinnere).

    Gruß
    ~blaze~
    Falls Du doch eher C / C++ im Hinterkopf hast:

    hate_regex schrieb:

    Multipointer
    könnten da ein Array von Pointern sein:

    Quellcode

    1. int** xx = new int[10];
    2. for(i = 0; i < 10; i++)
    3. {
    4. xx[i] = new int[32];
    5. }
    Das ist allerdings dahingehend stressig, da Du selbst alles fein säuberlich wieder aufräumen musst.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Dank Euch für die Antworten und Infos.

    Ja, die Frage war eher grundlegend, als im speziellen auf VB bezogen.
    Ich habe die Frage vermutlich etwas zu unklar formuliert, aber sowas fällt meist schwer, wenn man selbst recht wenig Ahnung von der Problematik hat (eine verzwickte Sache!).

    Ich habe mich also an Speichermanipulation versucht. Dazu habe ich mir mit gängigen Tools die Speicherbereiche eines Processes angesehen.
    Im nächsten Schritt habe ich ein Pointer gesucht den ich zuordnen konnte. Diesen kann ich auch entsprechend verändern (zur Laufzeit).
    Mit Änderung der ProcessID und des Handle verändert sich jedoch der Speicherbereich. Der Pointer ist nicht mehr 'gültig'. Statt dessen, gibt es einen neuen. Um nun nicht für jede neue ID/Handle einen gültigen Pointer zu finden, suche ich die BaseAdress. Auch diese konnte ich finden, musste dabei jedoch feststellen, dass es meist schwierig ist den richtigen zu finden, da es in meinem Fall 2.5 Mio Pointer-Matches gab.

    Vielleicht habe ich die Begrifflichkeiten falsch verwendet (diese wurden jedenfalls in einschlägiger Lektüre verwendet), aber ich hoffe die Fragen sind nun im Kontext klarer ;(
    Ich kann mir vorstellen, wie sowas zustande kommt. Ich schreib es mal in C# und veranschauliche das an "World, Player, Weapon":
    Spoiler anzeigen

    C-Quellcode

    1. [StructLayout(LayoutKind.Explicit)]
    2. public struct World
    3. {
    4. [FieldOffset(0)]
    5. public uint EinInteger;
    6. [FieldOffset(4)]
    7. public uint EinZweiterInteger;
    8. [FieldOffset(8)]
    9. public Player Player1;
    10. }
    11. [StructLayout(LayoutKind.Explicit)]
    12. public struct Player
    13. {
    14. [FieldOffset(0)]
    15. public byte PlayerId;
    16. [FieldOffset(1)]
    17. public byte TeamId;
    18. [FieldOffset(2)]
    19. public int Color;
    20. [FieldOffset(6)]
    21. public Weapon PrimaryWeapon;
    22. }
    23. [StructLayout(LayoutKind.Explicit)]
    24. public struct Weapon
    25. {
    26. [FieldOffset(0)]
    27. public byte WeaponId;
    28. [FieldOffset(1)]
    29. public int Color;
    30. }
    (Ich habe die Structs explizit gelayouted, damit man die offsets besser sehen kann. Man kann sie auch weglassen.)


    Um an die WeaponId des Player1s zu kommen bräuchstest du das, was man im allgemeinen als Multilevelpointer bezeichnet.
    Die Adresse zum World-Struct wäre z.B. 0x00FF1200 (bei 32-Bit).
    Da jedes Feld in dem Struct eine bestimmte Größe hat (uint: 4 Byte, byte: 1 Byte) musst du diese als "Offsets" miteinbeziehen. Da, wo jeweils ein Typ steht (z. B. bei Weapon PrimaryWeapon), steht im Speicher dann nur eine Adresse, die auf den ersten Eintrag der Rohdaten des angegebenen Structs zeigt. Je nach Architektur ist diese 32 oder 64 Bit breit.
    Zu 0x00FF1200 müsstest du also 8 dazurechnen, da der Player1 erst nach den 2 uints im Struct vorkommt. Dann hast du die Adresse zu Daten des Player1, die wie im Player-Struct angeordnet sind.
    Wenn die Klammern ([]) jeweils die Adresse auflösen (da gibt es einen Fachbegriff für, den ich gerade nicht weiß; bzw. hier steht es bestimmt; ich glaube es war "Dereferenzierung"), dann sieht das am Ende so aus:
    WeaponId = der Bytewert dort: [[0x00FF1200 + 0x8] + 0x6]

    Korrigiert mich bitte, wenn ich (komplett) falsch liege (@Chrisber:). Pointerkrams ist nicht so mein Ding, aber ich denke dass das so zustande kommt. Kann also sein, dass ich gerade hart faile.


    (Hab den Thread mal verschoben, da es hierbei ja um eine Programmierfrage geht)
    Von meinem iPhone gesendet

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „nikeee13“ ()

    Der Groschen ist gefallen! Vielen Dank für die ausführliche Erklärung!

    Zusätzlich habe ich mich nun ein wenig eingelesen und die diversen Unterschiede zu Marshalling und Pointerhandling (VB/C#) kennengelernt. Sehr spannende Sache! Sicherlich ein Thema, dass einen lange beschäftigen kann wenn ich sehe, dass Grundlagenwissen auf ASM-Ebene gefordert ist.

    Meine Frage ist dahingehend erstmal geklärt, die Zeit sollte das übrige erklären :)

    Gerne kann ich für die Folgefrage einen neuen Thread erstellen, aber ich versuchs mal dreist in diesem hier.
    Ich kann mir nun beliebige Speicherbereiche von Prozessen unter den Nagel reißen. Wird hier für jeden Prozess eine Speicherbreite von 0-7fffffffffffffff reserviert (das sind 10^18 Values)? Wenn ich den gesamten Speicherbreich auslesen möchte, rennt das bei mir in einen Timeout. Wie kann ich ggf. die tatsächliche Speicherbreite ermitteln?

    Und Finally: Wie durchsuche ich einen Array mit 10^18 Werten auf Matches effektiv? Selbst rekursiv dürfte das kaum brauchbar sein, oder?

    hate_regex schrieb:

    Wie durchsuche ich einen Array mit 10^18 Werten auf Matches effektiv?

    Für sowas nutzt man Bäume oder Hashmaps.
    Bist du sicher, dass dein Array wirklich so lang ist? Das passt nicht mal in einen 32bit-Prozess!

    Quellcode

    1. >>> 2 ** 32 > 10 ** 18
    2. False
    To make foobar2000 a real random music player, I figured out the only way to achieve this is to use Windows Media Player.

    At some point in time, you recognize that knowing more does not necessarily make you more happy.
    Servus,

    Bist du sicher, dass dein Array wirklich so lang ist? Das passt nicht mal in einen 32bit-Prozess!
    Nein :( Das ist nur der gesamte (imho theroretisch mögliche Adressbereich). Wenn ich mit externen Tools (Process Analyzer) den Speicherbereich durchsuche, geschieht dies immer in o.g. Range. Ich vermute, dass der tatsächliche Bereich jedoch kleiner ist. Ich kann diesen nur nicht abfragen.
    Ich habe versucht aus einem kompletten Dump des aktuellen Prozesses die Adressbreite zu errechnen. Leider ungenau, oder ich mache etwas im encoding falsch.
    @ErfinderDesRades
    Es gibt auch viele nützliche Anwendungsmöglichkeiten dafür. Beispielsweise hat ein Freund mal mittels eines solchen Programmes und eines Arduinos realisiert, dass man bei verschiedenen Spielen Munition, Gesundheit etc. anzeigen kann (ist praktisch bei mehreren großen Monitoren, außerdem sieht es, wenn man es gut macht, genial aus :).
    Malware?
    Weit entfernt davon :) Ich könnte es minutiös erklären, aber ich mag niemanden mit meinen Stories langweilen.
    Kurzfassung: Ein Programm von einem Hersteller (Konkurs) für eine Anlagensteuerung benötigt Anpassungen, da neue Hardware nach Austausch im Einsatz.

    Ich stehe jedenfalls vor der Wahl einen bestehenden Prozess zu manipulieren oder ein neues Programm zu schreiben (niemals!). Nicht zu letzt finde ich das ganze recht interessant, da es imho Grundlagenwissen vermittelt/voraussetzt. Nicht zuletzt macht Reverse Engineering im Sinne der Problemlösung/analyse unheimlich Spass.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „hate_regex“ ()

    @nafets3646
    Ich habe jetzt keine Rechtsberatung vorher eingeholt, aber ich denke mir mal, dass a) wo kein Kläger, da kein Richter - und b) das ganze im Sinne aller Beteiligten ist.

    Dekompilieren ist für mich Neuland. Aber da sogar ich weiss, was ein Obfuscator ist, halte ich das auch für eher ausgeschlossen.
    Die aktuelle Lösung finde ich brauchbar, fange an es zu verstehen und ist imho interessanter als Code zusammenzustückeln ;)

    @ErfinderDesRades
    Theoretische Fragen und Antworten. Abgesehen von exemplarischer Sniplet-Hilfe stricke ich mir den Rest selber. Ich mag es Dinge zu verstehen. Ausser meinem Rücken der bürostuhlgeplagt ist, cracked hier also gar nix 8|
    Zu den CrackerTools selbst muss ich anmerken, dass 80% aller Infos die man zum Thema findet, aus diversen Szene-Boards stammen. Natürlich nebst scriptbasierten Tool, damit einen der Code nicht überfordert. Ich glaube daher, wer wirklich cracken will, findet an jeder Ecke ein dafür vorgefertigtes Tool. Aber wer macht sich schon die Mühe, gibt es doch auch bereits als fertigen Download-Patch/Trainer.. Leider.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „hate_regex“ ()

    Was daran illegal sein soll weiß ich auch nicht. Windows stellt solche Funktionen ja nicht zum Spaß bereit. Jeder kann sie nutzen.
    Ich stimme @hate_regex: zu. Das Thema ist sehr spannend. Ich behaupte mal, dass es keinen besseren Weg gibt, die Arbeitsweise von Computern und Betriebssysteme zu verstehen, als genau so damit rumzuspielen. Das hilft einem nicht nur für das "Allgemeinwissen" am PC, sondern schafft auch enorme Vorteile beim Debuggen und bringt tiefes Wissen, welches in keiner Dokumentation zu finden ist.
    Habe ich übrigens auch gemacht - und illegal gehandelt habe ich deswegen gewiss nicht ;-)
    To make foobar2000 a real random music player, I figured out the only way to achieve this is to use Windows Media Player.

    At some point in time, you recognize that knowing more does not necessarily make you more happy.