Eine Listbox im Speicher

Der folgende Artikel bezieht sich auf die Betriebsysteme Windows2000/XP. Die hier aufgeführten Tests wurden unter Windows2000 unter einem Administratoraccount durchgeführt.
Für das Nachvollziehen der hier gemachten Aussagen sind folgende Zusatzprogramme erforderlich:
- Tasks and Token
- Eine Version von Profan² bzw. XProfan.
- Profan2Cpp

Als Ausgangslage nehmen wir mal folgenden kleinen Quelltext:

Windowstyle 31

Windowtitle "Listboxtest"

Window 0,0-640,440

Declare Listbox&,Zähler%

LET LISTBOX&=@Createlistbox(%HWND,"",20,40,300,300)

Clear Zähler%

PRINT Listbox&

While Zähler%<1000

@ADDSTRING(LISTBOX&,"Hallo, hier spricht AH!")

inc Zähler%

wend

Beep

While 0=0

Waitinput

wend


Da Profan etwas verschwenderisch mit Heaps umgeht, empfehle ich, das Programm mit Profan2Cpp zu compilieren. Nach dem Ausführen sieht man folgendes auf dem Bildschirm:


Danach starten wir Tasks and Token und lassen uns erst einmal die Heaps des Testprozesses mit der Listbox listen:


Unter "Programm/Optionen" befindet sich der Menüpunkt "String in Bytefolge umwandeln". Nach dem Anklicken geben wir das Wort "Hallo" ein und drücken OK.


Nach einem Rechtsklick ins Treeview von Tasks and Token wählen wir "Speicher durchsuchen" aus.


Im Unteren Edit steht nun das Wort "Hallo" bereits als hexadezimale Bytefolge.


Alle Texte von Controls stehen im Speicher als Unicodestrings, wir müsse da also noch nach jedem Byte ein Nullbyte einfügen, d.h. nach jedem zweiten Zeichen zwei Nullen. Das ganze sieht dann so aus:


Was gefunden wird, sieht in etwa so aus:


Wir wählen nun ein paar beliebige Adressen aus, einmal aus dem oberen drittel, einmal aus der mitte und einmal aus dem unteren drittel und schauen nach, in welchem Heapblock diese Adressen liegen. Die Blöcke, in denen die Adressen liegen, lassen wir uns als Strings anzeigen. Der Heapblock, den wir suchen, ist in etwa 48136 Bytes groß und liegt wahrscheinlich am Ende des ersten Heaps. Das Wort "Hallo" steht komplett am Anfang des Blockes, so wie hier zu sehen:


Jetzt kopieren wir mittels Rechtsklick die Startadresse des Blocks - dann ein Rechtsklick ins Treeview und "Speicherbereich ändern" auswählen. Als Adresse des Speicherbereichs fügen wir hier die vorher kopierte Startadresse ein, den hexadezimalen neuen Inhalt setzen wir auf 41 und klicken danach auf "Speicherbereich ändern".


Wenn wir uns jetzt die Listbox ansehen, ist mit ihr folgendes passiert:


Das was wir da gefunden haben ist also der Speicherbereich, an dem alle Einträge der Listbox gespeichert sind! Das ist ja schon mal ganz Interessant - aber wo ist der Rest der Listbox? Danach suchen wir jetzt! Wenn die Zeilen einer Listbox in einem Speicherbereich stehen, müßte ein anderer Speicherbereich wiederum auf diese Adresse verweisen - ist doch logisch, oder? Wir gehen also folgendermaßen vor: Zuerst kopieren wir wieder die Adresse des Heapblocks mit den Listviewzeilen. Danach klicken wir unter "Programm/Optionen" auf den Menüpunkt "Zahl in Bytefolge umwandeln" und fügen hier die Adresse ein.


Danach klicken wir auf OK. Nun durchsuchen wir wieder den Prozessspeicher des Testprozesses mit der Listbox - und zwar nach der Adresse als Doubleword in hexadezimaler Bytefolge (siehe Bild):


Das wurde bei mir gefunden:


Unter den gefundenen Adressen suchen wir nach einer Adresse innerhalb eines Heapblocks des ersten Heaps (bei mir 38184396). Der gesuchte Bereich dürfte 720 Bytes groß sein. Wir stellen nun den Inhalt dieses Bereichs als dezimale Doublewords da (bei mir 38183824):


Danach kopieren wir den ganzen Bereich mittels Rechtsklick in die Zwischenablage:


Das kommt bei mir dabei heraus:

X1=0

X2=0

X3=0

X4=1572865

X5=0

X6=768

X7=0

X8=0

X9=0

X10=0

X11=0

X12=0

X13=0

X14=0

X15=0

X16=0

X17=0

X18=0

X19=0

X20=0

X21=0

X22=0

X23=0

X24=0

X25=0

x26=0

x27=0

x28=0

x29=0

x30=0

x31=0

x32=0

x33=0

x34=0

x35=0

x36=0

x37=0

x38=0

x39=0

x40=0

x41=0

x42=0

x43=0

x44=0

x45=0

x46=0

x47=38183832

x48=0

x49=0

x50=0

x51=0

x52=0

x53=0

x54=0

x55=0

x56=0

x57=0

x58=0

x59=0

x60=0

x61=0

x62=0

x63=0

x64=0

x65=0

x66=0

x67=0

x68=0

x69=0

x70=0

x71=0

x72=0

x73=0

x74=0

x75=0

x76=0

x77=0

x78=0

x79=0

x80=0

x81=0

x82=0

x83=0

x84=0

x85=0

x86=0

x87=0

x88=0

x89=0

x90=0

x91=38184008

x92=0

x93=0

x94=0

x95=0

x96=0

x97=0

x98=0

x99=0

x100=0

x101=0

x102=0

x103=0

x104=0

x105=0

x106=0

x107=0

x108=0

x109=0

x110=0

x111=0

x112=0

x113=0

x114=0

x115=0

x116=0

x117=0

x118=0

x119=0

x120=0

x121=0

x122=0

x123=0

x124=0

x125=0

x126=0

x127=0

x128=0

x129=0

x130=0

x131=0

x132=0

x133=0

x134=0

x135=41681216

x136=41681440

x137=0

x138=-1

x139=0

x140=18

x141=1000

x142=1024

x143=38256320

x144=38187408

x145=48128

x146=48000

x147=8

x148=16

x149=0

x150=0

x151=0

x152=0

x153=0

x154=1288421508

x155=2

x156=0

x157=-1

x158=-1

x159=-1

x160=0

x161=0

x162=0

x163=0

x164=0

x165=0

x166=1031

x167=0

x168=0

x169=0

x170=278

x171=0

x172=23

x173=0

x174=999

x175=18

x176=0

x177=23

x178=0

x179=5898242

x180=1048832


Was wir hier sehen, dürften die Daten der Listbox sein - an Stelle X144 steht dabei die schon bekannte Adresse, die die Zeilen der Listbox enthält. Wir schauen uns nun Stelle X141 mal etwas genauer an, die Zahl 1000. Kommt sie jemandem bekannt vor?. Die Adresse von X141 berechnen wir folgendermaßen:
Startadresse des Heapblock+(141*4)-4
Bei mir wäre das 38183824+(141*4)-4 = 38184384
Zur Kontrolle bitte einmal 4 Bytes ab dieser Adresse als dezimale Doublewords auslesen lassen, es müßte die Zahl 1000 herauskommen!
Nun ändern wir das Doubleword an dieser Stelle wie im Bild zu sehen auf den dezimalen Wert 10:


Jetzt sschauen wir mal zwischendurch die Listbox an:


Oops - die Zeilenzahl hat sich (wie beabsichtigt) auf 10 verringert!

PS: X143 hat übrigens was mit der Sortierung der Listbox zu tun...



Impressum