XOR Algorithmus, Problem mit uninitialisierter Variable

Hier könnt ihr sowohl zur x86 Architektur als auch zu Win32ASM Fragen stellen.

Moderatoren: crack, Krüsty, Marwin

XOR Algorithmus, Problem mit uninitialisierter Variable

Beitragvon Magister » Mittwoch 27. April 2005, 22:54

Hallo Leute

Ich bin gerade dabei einen XOR Algorithmus in Assembler zu schreiben. Ich weiss natürlich schon, dass es schon massenhaft vorgefertigtes, optimiertes Zeug in dieser Art gibt (z.B. auch im MASM32 Packet), doch ich hab mir halt vorgenommen einen eigenen zu schreiben...

...wenn da nicht ein Problem aufgetaucht wäre: Mein Programm stürzt immer ab. Irgendwo muss da ein harter Fehler sein.
Grob beschrieben funktioniert mein Programm (mehr Test als Programm :) ) so:
1. Der Schlüssel wird aus einer Datei ausgelesen (Schluessel.txt)
2. Der Klartext (zu verschlüsselnder Text) wird aus einer Datei ausgelesen (Klartext.txt)
3. Das ganze wird Byteweise verschlüsselt und in einen Buffer geschrieben
4. Wenn der ganze Klartext verschlüsselt ist, wird das verschlüsselte Zeug in die Datei Geheimtext.txt geschrieben

So viel zum groben Ablauf des Programms. Hier der Quelltext...

Code: Alles auswählen
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib


.data
DateinameSchluessel   db "Schluessel.txt",0
DateinameKText      db "Klartext.txt",0
DateinameGText      db "Geheimtext.txt",0

MsgCaption      db "Meldung",0
MsgText         db "Die Datei wurde vollständig verschlüsselt",0


.data?
hDatei          dd ?

Schluesselgroesse   dd ?
Klartextgroesse    dd ?
GeleseneBytes       dd ?
GeschriebeneBytes   dd ?

SBuffer        dd ?   ;Schlüssel Buffer
KBuffer          dd ?   ;Geheimtext Buffer
NBuffer         dd ?   ;Neuer Buffer

Dat1         db ?   ;1 Schlüsselzeichen -> 1 Byte
Dat2         db ?   ;1 Klartextzeichen -> 1 Byte

SPosition      dd ?   ;Position im SBuffer
KPosition      dd ?   ;Position im KBuffer
NPosition      dd ?   ;Position im NBuffer (Neuer Buffer)

.code
start:
;/////////////////////////////////////////////////////////////////
;***ZEUGs auslesen: Schlüssel und Klartext***
invoke CreateFile, addr DateinameSchluessel, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL
mov hDatei, eax
invoke GetFileSize,hDatei, NULL
mov Schluesselgroesse,eax
invoke ReadFile, hDatei, addr SBuffer,Schluesselgroesse, addr GeleseneBytes, NULL
invoke CloseHandle, hDatei
;/////////////////////////////////////////////////////////////////
invoke CreateFile, addr DateinameKText, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL
mov hDatei, eax
invoke GetFileSize,hDatei, NULL
mov Klartextgroesse,eax
invoke ReadFile, hDatei, addr KBuffer,Klartextgroesse, addr GeleseneBytes, NULL
invoke CloseHandle, hDatei
;***Jetzt ist alles Zeug ausgelesen und befindet sich im Speicher.***
;/////////////////////////////////////////////////////////////////

Verschluesseln:
mov ebx,offset SBuffer      
mov ecx,SPosition   
mov al, [ebx + ecx]         
mov Dat1, al            

   inc SPosition         ;erhöhe (inkrementiere) SPosition um 1 Byte
   mov eax,SPosition
   .if eax==Schluesselgroesse
   mov SPosition,0   
   .endif


mov ebx,offset KBuffer      
mov ecx,KPosition
mov al, [ebx + ecx]         
mov Dat2, al            

   inc KPosition         ; erhöhe (inkrementiere) KPosition um 1 Byte

;***Hier wird verschlüsselt***
mov al,Dat1   
mov bl,Dat2
xor al,bl
;*************
mov ebx,offset NBuffer      
mov ecx,NPosition
mov [ebx + ecx],al         
inc NPosition

mov eax, KPosition
.if eax!=Klartextgroesse
jmp Verschluesseln
.endif


;***Wenn das Zeug verschlüsselt ist, wird es in eine Datei geschrieben***
invoke CreateFile,addr DateinameGText,GENERIC_WRITE,0,0,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
mov hDatei,eax
invoke SetFilePointer, hDatei, NULL, NULL, FILE_END
invoke WriteFile, hDatei,addr NBuffer, Klartextgroesse, addr GeschriebeneBytes, NULL
invoke CloseHandle, hDatei

invoke MessageBox, NULL,addr MsgText, addr MsgCaption, MB_OK
invoke ExitProcess,0


end start


Mein Problem: Wenn ich NBuffer als uninitialisiert deklariere (wie oben im Quelltext), stürzt das Programm ab. Wenn ich NBuffer mit "db 262144 dup (?)" deklariere (und die anderen Buffer als uninitialisiert) funktioniert alles bestens. Eigentlich hätte ich aber gerne einen uninitialisierten Buffer (--> weniger Einschränkungen).

Ich rätsle nun schon ziemlich lange an diesem Problem herum. Kann mir jemand helfen? Was mache ich falsch? Warum stürzt das Programm ab?
Magister
Newbie
 
Beiträge: 4
Registriert: Mittwoch 27. April 2005, 22:10

Beitragvon CDW » Donnerstag 28. April 2005, 01:51

auf die schnelle würde ich sagen:
man sollte sein Zählvariablen immer vorher initialisieren :D
denn:
NPosition wird das erste mal hier eingesetzt:
Code: Alles auswählen
mov ecx,NPosition

Welchen Wert hat Nposition? einen nicht definierten bzw. einen zufälligen. Wenn man dann versucht auf ebx+ecx zuzugreifen, greift man in die Datennirvana ;).
Genauso SPosition und KPosition.Auch wenn es im Moment läuft, so sind das trotzdem uninitialisierte Werte und wer weiß was man damit jedesmal in Speicher ver-entshlüsselt ;)
PS: kleine optimization tipp:
Schluesselgroesse wird öfters gebraucht und verdient es vor der schleife in einen extra register geladen zu werden, damit entfällt auch mov eax,SPosition
bzw. man kann mov ebx,offset KBuffer und mov ebx,offset SBuffer
vor die Schleife auslagern und statt ebx z.B EDI,ESI benutzen (diese werden in der Schleife nicht gebraucht). Grundsätzlich darf man die Register alle benutzen... EAX,EBX,ECX,EDX,ESI,EDI
Bei ESP,EBP muss man etwas aufpassen.[/code]
CDW
Alter Hase
 
Beiträge: 62
Registriert: Donnerstag 2. Oktober 2003, 17:17

Beitragvon Magister » Donnerstag 28. April 2005, 16:07

Hallo CDW


Danke für deine Vorschläge und die Optimisations Tipps!

Ich hab jetzt die Zählvariablen im Datensegment initialisiert und zwar so...
Code: Alles auswählen
SPosition      dd 0   ;Position im SBuffer
KPosition      dd 0   ;Position im KBuffer
NPosition      dd 0   ;Position im NBuffer (Neuer Buffer)


Die Optimisations Tipps habe ich noch nicht alle ausgeführt.
Das Programm stürzt leider immer noch ab. :cry: Ich hab jetzt mal ein bisschen mit dem OllyDbg herumgespielt. Ich bin zwar noch ein blutiger Anfänger im Gebrauch mit Olly, doch ich glaube das Programm stürzt hier ab ...

Code: Alles auswählen
mov [ebx + ecx],al


Ausserdem habe ich durchs Debuggen rausgefunden, dass die Zählvariablen
einwandfrei funktionieren. Nachdem die Schleife jedoch ca. 1000 mal durchgemacht wurde stürzt das Programm aber ab.

Ich bin hilflos :cry: . Ich weiss nicht mehr wie weiter :cry: . Oder stimmt etwas mit der Adressierung nicht? Ich habe sogar ebx mit esi ausgetauscht. Auch das funktioniert nicht.


P.S. Ich benutze eine zirka 40 KB grosse Datei als Klartext (weiss nicht ob das zur Lösung des Problems führt...)
Magister
Newbie
 
Beiträge: 4
Registriert: Mittwoch 27. April 2005, 22:10

Beitragvon crack » Donnerstag 28. April 2005, 18:42

:D Ja, Du hast recht, wenn Du mit:
NBuffer "db 262144 dup (?)" den Puffer initialisierts dann funktioniert es...
so dann ist mir aufgefallen das Du den Puffer mit dd ? initialisieren willst geht nicht, DefineDoubleWord reserviert lediglich vier Byte, wärend db 262144 dup (?) auch 262144 Byte reserviert das ist doch wesentlich mehr als 4 byte, wenn dein Datensegment vor dem Codesegment liegt, und du lädst mehr Daten aus einer Datei als Du Puffer reserviert hast, dann 'Schreiben' die Daten dein Prg kaputt. Windows übernimmt das Speichermanagement nur für verschiedene Prg's, innerhalb eines Prg's musst Du das übernehmen.
Schau doch mal auf den MSDN Seiten ob's nicht eine API Funktion gibt, die Puffer dynamisch reserviert.
Mach dir nix drauss, solche ärgerlichen Laufzeitfehler (da nützt dir meistens auch der beste Debugger nix) können selbst jahrelangen Profi's unterlaufen :wink:
Äh, verschlüsselt hats prima, und was ist mit entschlüsseln???
mit freundlichen grüssen,
with best regards,

crack
Benutzeravatar
crack
Administrator
 
Beiträge: 280
Registriert: Dienstag 21. Dezember 2004, 15:02
Wohnort: 53783 Eitorf

Beitragvon Magister » Donnerstag 28. April 2005, 20:19

Hallo Crack

Ich habe mal im Platform SDK nachgeschaut was es da für Funktionen zur Speicherreservierung gibt. Die Funktionen die mir bei meinem Programm helfen könnten um Speicher zu reservieren sind wahrscheinlich GlobalAlloc, GlobalLock, ...

Ich hab das ganze dann mal im Quelltext eingebaut ...

Code: Alles auswählen
.data?

hMemory      dd ?


.code

;Dieser Codeabschnitt wird vor der Schleife eingebaut   
invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT, Klartextgroesse
mov  hMemory,eax
invoke GlobalLock,hMemory
mov NBuffer,eax


Doch das Programm funktioniert immer noch nicht :cry: . Die Funktion GlobalAlloc erzeugt die Fehlermeldung --> "Unzulässiger Zugriff auf einen Speicherbereich."
Ich hab auch in anderen Quelltexten (z.B. von Iczelion) nachgeschaut. Dort wird die Funktion GlobalAlloc auch so benutzt.

Was mache ich falsch? Auf jeden Fall denke ich das GlobalAlloc die richtige Funktion ist, um Speicher zu reservieren.

Äh, verschlüsselt hats prima, und was ist mit entschlüsseln???


Bei der Verschlüsselung mit dem logischen Operator XOR (Exclusive Or) sind die Ver- und Entschlüsselung symmetrische Vorgänge. Das heisst, dass du mit dem selben Schlüssel den Geheimtext wieder entschlüsseln kannst.
Magister
Newbie
 
Beiträge: 4
Registriert: Mittwoch 27. April 2005, 22:10

Beitragvon CDW » Donnerstag 28. April 2005, 22:57

NBuffer "db 262144 dup (?)"

wie konnte ich das übersehen, war wohl schon spät ;)
aber nun zum GlobalLock:
habe die Funktion getestet und sie funktioniert auch (bei mir im TestProgramm wird speicher reserviert)
Jedoch:
;Dieser Codeabschnitt wird vor der Schleife eingebaut

heißt das dass Du den Buffer reservierst nach dem du die Datei schon ausgelesen hast? Oder noch davor? Dann ist aber Klartextgroesse auch nicht richtig. Also mal versuchen nach dem GetFileSize aufruf einzubauen.
Wobei: bei den Dateioperation gibt es noch solche "netten" sachen wie:
CreateFileMapping
MapViewOfFile
(und natürlich)
UnmapViewOfFile
CloseHandle (von CreateFileMapping)
ich bin mir sicher dass Icz das auch erwähnt, aber nicht destotroz mal ein Beispiel:
Code: Alles auswählen
DateiEinlesen proc hWnd:DWORD,Dialog:DWORD
LOCAL hFile1:HANDLE
LOCAL hFile1Map,pFile1:HANDLE
LOCAL FileSize:DWORD   
   invoke CreateFile,addr OpenFileNameBuffer,GENERIC_WRITE or GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
   mov hFile1,eax   
   push eax
    invoke GetFileSize,eax,0   
    .if eax==0
       invoke CloseHandle,hFile1
       ret
    .endif
    mov FileSize,eax
   
    pop eax
   .if eax==INVALID_HANDLE_VALUE
       ret
   .endif   
   
   invoke CreateFileMapping,eax,0,PAGE_READWRITE,0,FileSize,0
   mov hFile1Map,eax;2
   invoke MapViewOfFile,eax,FILE_MAP_WRITE,0,0,FileSize
   mov pFile1,eax
    ;hier irgendeine bearbeitungsroutine wie "gewohnt"
   


    invoke UnmapViewOfFile,pFile1
    invoke CloseHandle,hFile1Map
    invoke CloseHandle,hFile1
   ret

DateiEinlesen endp
CDW
Alter Hase
 
Beiträge: 62
Registriert: Donnerstag 2. Oktober 2003, 17:17

Beitragvon crack » Freitag 29. April 2005, 11:21

:D

Hi, hatte nur einen der drei Puffer auf die richtige Grösse gesetzt, deswegen hat das mit dem Entschlüsseln nicht geklappt wenn man alle auf z.B. 256000 Byte setzt funktioniert das soweit ganz gut. Um Speicher zu sparen könnte man nur zwei Puffer verwenden: einen für den Schlüssel, und in den anderen die zu verschlüsselnde Datei, wobei jedes Byte ausgelesen, verschlüsselt und an die selbe Stelle zurückgeschrieben wird, und dann wird der Pufferinhalt in die Datei geschrieben!
Ausserdem könnte man den Vorgang: Datei öffnen, Datei lesen, Datei schliessen als SubRoutine definieren, das bringt zwar keinen Geschwindigkeitsvorteil, aber spart nochmal Speicherplatz!
GlobalAlloc müsste die korrekte Funktion sein um Puffer zu reservieren :wink:
mit freundlichen grüssen,
with best regards,

crack
Benutzeravatar
crack
Administrator
 
Beiträge: 280
Registriert: Dienstag 21. Dezember 2004, 15:02
Wohnort: 53783 Eitorf

Beitragvon Magister » Freitag 29. April 2005, 18:53

Hallo zusammen

Ich habe mich jetzt ein bisschen mit den Memory Mapped Files auseinandergesetzt und rausgefunden, dass das eine super Methode ist um Dateien in den Speicher zu laden oder auch um Speicher zu reservieren.

Das Programm funktioniert jetzt. Ich bin so glücklich!!! :D :D :D
Danke auch für die Optimisations-Vorschläge.
Nur noch eine kleine Frage: Ist es schneller eine Variable in ein Register zu laden (mit mov) oder sollte man lieber keine Variablen benutzen und das Zeug pushen bzw. poppen?


Danke für eure Hilfe! :D
Magister
Newbie
 
Beiträge: 4
Registriert: Mittwoch 27. April 2005, 22:10

Beitragvon crack » Freitag 29. April 2005, 20:55

Suuper!!!

Die Speichervariable ist idR schneller als PUSHen und POPen :wink:
mit freundlichen grüssen,
with best regards,

crack
Benutzeravatar
crack
Administrator
 
Beiträge: 280
Registriert: Dienstag 21. Dezember 2004, 15:02
Wohnort: 53783 Eitorf


Zurück zu Assembler

 


  • { RELATED_TOPICS }
    Antworten
    Zugriffe
    Letzter Beitrag

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot]

cron