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...