kann mir (!! von Assembler keine Ahnung!!) jemand sagen, ob es eine
Möglichkeit gibt Assembler in C oder C++ umzuwandeln? Das Programm ist
für eine x86 CPU unter DOS geschrieben worden....
Hoffend auf Hilfe
Thomas Göbel
> kann mir (!! von Assembler keine Ahnung!!) jemand sagen, ob es eine
> Möglichkeit gibt Assembler in C oder C++ umzuwandeln? Das Programm
> ist für eine x86 CPU unter DOS geschrieben worden....
Es gibt zwar ein paar Entwicklungen in die Richtung, aber wirklich
nutzbar ist das alles noch nicht. Das Problem ist dass die meisten
Compiler beim compilieren stark optimieren. Dabei verwischen die
Grenzen zwischen den sequentiellen Zeilen und es ist fast unmöglich,
da überhaupt noch eine Zeile C wiederzuerkennen. Besonders unter DOS
kann ich mir das nur allzugut vorstellen.
Also meines Wissensnach gibts für C/C++ keine funktionstüchtigen
Compiler, schon garnicht welche, die DOS/BIOS-Calls verstehen
Das Problem ist vorallem: Das was C-Code uebersichtlich macht, sind die
Bezeichnungen der Variablen, die Kommentare, und die Formatierung nach
sinn. Und die Infos gehen beim Compilieren einfach verlohren (wenn man
keine Debug-Infos mit einkompiliert).
> Dabei verwischen die Grenzen zwischen den sequentiellen Zeilen und es
> ist fast unmöglich, da überhaupt noch eine Zeile C wiederzuerkennen.
> Besonders unter DOS kann ich mir das nur allzugut vorstellen.
> Also meines Wissensnach gibts für C/C++ keine funktionstüchtigen
> Compiler, schon garnicht welche, die DOS/BIOS-Calls verstehen
Das ist ja auch nicht die aufgabe des Compilers, dazu hat man Librarys.
FaUl
end
This article does not support incompatible and broken newsreaders.
--
Hint:"Read The Fu**ing Manual!"
Reply:"But I do know how to f**k,
why should I read a _Fu**ing Manual_?"
[unknown]
Aber vielleicht hilft dem Fragesteller schon,
wenn das Programm syntaktisch nach C disassembliert wird.
Bis auf einige Deteils (bspw. "jmp [bx]") sollte das doch
recht einfach sein.
Gruss
Jan
Thomas
Jan Bruns schrieb:
Also ich nehme an, einen 40-Zeiler könnte man Dir hier in der Gruppe
wohl noch manuell verdeutlichen. Wenn es tatsächlich nur 40 Zeilem
sind, poste sie doch hier.
Ansonsten: die x86 Prozessoren haben im wesentlich 6 32 Bit breite
Hauptregister, praktisch fest verdrahtetes RAM.
Diese haben die Bezeichnungen "EAX"..."EDX","ESI","EDI";
Die unteren 16 Bit der Register "EAX" bis "EDX" lasen sich
einzeln ansprechen, heissen dann "AX".."DX", hiervon lassen
sich wiederum die beiden bytes einzeln ansprechen: "AL".."DL"
und "AH".."DH".
Falls der Quelltext haupsächlich Befehle mit 3 Zeichen
enthält, ist meist das linke,erstgenannte "Register" der
Zieloperand.
RAM-Zugriffe sind etwas kompliziert, gerade unter DOS im Realmode
war es noch etwas anders als heute üblich, so daß mir das jetzt zu
umständlich ist, hier kurz zusammenzufassen.
Gruss
Jan
A100 SUB [BP],CX
CMP SP,B139 XOR AX,[BP]
JB 14A XOR AX,CX
MOV BP,5D INC BP
MOV DX,152 CMP BP,66
MOV CX,AD39 JB 139
XOR BX,BX MOV BP,5D
MOV AH,3F DEC BL
INT 21 JNZ 128
JB 14A STOSW
OR AX,AX LOOP 125
JZ 151 POP CX
MOV CX,AX MOV BX,1
PUSH CX MOV AH,40
INC CX INT 21
SHR CX,1 JNB 10C
MOV SI,DX MOV AX,4C07
MOV DI,DX INT 29
LODSW INT 21
MOV BL,11 RET
Das Programm nimmt einen Parameter an (Passwort) und bekommt via Pipe
eine Datei, die es dann auch wieder via Pipe nach der Bearbeitung
speichert. (Bsp. verschl.com passwort < input.txt > output.txt)
Eine Info vom Autor war noch, dass die Inputdaten via XOR mit dem
Passwort verwoben werden.....
Vielleicht wird ja jemand von Euch daraus schlau.
Thomas
Jan Bruns schrieb:
Kommst dir wohl ganz schlau vor!
Das muss doch nicht sein.
Benjamin Kalytta
Und dann noch doppelspaltig und ohne richtige lables.
Naja ich will mich mit so DOS-Sachen nicht beschäftigen, jedoch der das tun
will, für den habe ich das ganze
mal in einer hoffentlich verständlicheren Form erstellt:
(ach ja, ne Fixed Font sollte bei der Betrachtung eingestellt werden)
0CFC:0100 81FC39B1 CMP SP,B139
0CFC:0104 7244 JB 014A
0CFC:0106 BD5D00 MOV BP,005D
0CFC:0109 BA5201 MOV DX,0152
0CFC:010C B939AD MOV CX,AD39
0CFC:010F 31DB XOR BX,BX
0CFC:0111 B43F MOV AH,3F
0CFC:0113 CD21 INT 21
0CFC:0115 7233 JB 014A
0CFC:0117 09C0 OR AX,AX
0CFC:0119 7436 JZ 0151
0CFC:011B 89C1 MOV CX,AX
0CFC:011D 51 PUSH CX
0CFC:011E 41 INC CX
0CFC:011F D1E9 SHR CX,1
0CFC:0121 89D6 MOV SI,DX
0CFC:0123 89D7 MOV DI,DX
0CFC:0125 AD LODSW
0CFC:0126 B311 MOV BL,11
0CFC:0128 294E00 SUB [BP+00],CX
0CFC:012B 334600 XOR AX,[BP+00]
0CFC:012E 31C8 XOR AX,CX
0CFC:0130 45 INC BP
0CFC:0131 83FD66 CMP BP,+66
0CFC:0134 7203 JB 0139
0CFC:0136 BD5D00 MOV BP,005D
0CFC:0139 FECB DEC BL
0CFC:013B 75EB JNZ 0128
0CFC:013D AB STOSW
0CFC:013E E2E5 LOOP 0125
0CFC:0140 59 POP CX
0CFC:0141 BB0100 MOV BX,0001
0CFC:0144 B440 MOV AH,40
0CFC:0146 CD21 INT 21
0CFC:0148 73C2 JNB 010C
0CFC:014A B8074C MOV AX,4C07
0CFC:014D CD29 INT 29
0CFC:014F CD21 INT 21
0CFC:0151 C3 RET
Benjamin Kalytta
Also ich nehme mal an, daß die rechte Spalte unter die linke gehört.
Es hnelt sich m.A.n. nicht um Assembler, sondern lediglich um
Maschinencode in Mnenomic-Notation (zu Assembler gehört für mich eigentlich
auch die Nutzung von Bezeichnern).
Ich habe das mal mit einem "Monitor" "assembliert", damit wenigstens
schonmal
8000:0100 81FC39B1 CMP SP,B139
8000:0104 7244 JB 014A
8000:0106 BD5D00 MOV BP,005D
8000:0109 BA5201 MOV DX,0152
8000:010C B939AD MOV CX,AD39
8000:010F 31DB XOR BX,BX
8000:0111 B43F MOV AH,3F
8000:0113 CD21 INT 21
Hier wird wahrscheinlich die Datei geladen, wohl nach
Adresse DS:152 = CS:[DX], also in den Speicher direkt
hinter das Prgramm selbst.
8000:0115 7233 JB 014A
8000:0117 09C0 OR AX,AX
8000:0119 7436 JZ 0151
8000:011B 89C1 MOV CX,AX
Der int21-Call hat wohl die Dateilänge in AX übergeben
und zudem die Mem-location unveränder iun DX gelassen.
8000:011D 51 PUSH CX
Diese wird nun aud den Stack gebracht, damit sie später
beim schreiben des Ergebnisses verwendet werden kann.
8000:011E 41 INC CX
8000:011F D1E9 SHR CX,1
Workdatalen=(Datalen+1)/2
8000:0121 89D6 MOV SI,DX
8000:0123 89D7 MOV DI,DX
*****Hier beginnt Haupschleife****
8000:0125 AD LODSW
LODSW=
MOV AX,word ptr[SI] ;
add si,0x0002 (kann auch ein sub esi,2 sein, je nach Direction-Flag)
8000:0126 B311 MOV BL,11
BL=00x11
8000:0128 294E00 SUB [BP+00],CX
8000:012B 334600 XOR AX,[BP+00]
8000:012E 31C8 XOR AX,CX
8000:0130 45 INC BP
8000:0131 83FD66 CMP BP,+66
8000:0134 7203 JB 0139
8000:0136 BD5D00 MOV BP,005D
8000:0139 FECB DEC BL
8000:013B 75EB JNZ 0128
8000:013D AB STOSW
STOSW= MOV word ptr[DI],ax ; ádd si,0x0002
8000:013E E2E5 LOOP 0125
CX=CX-1; if cx<>0 then goto 0x0125
*****Hier endet die Hauptschleife
Es folget wohl der Code zum wegschreiben der Datei.
8000:0140 59 POP CX
8000:0141 BB0100 MOV BX,0001
8000:0144 B440 MOV AH,40
8000:0146 CD21 INT 21
8000:0148 73C2 JNB 010C
8000:014A B8074C MOV AX,4C07
8000:014D CD29 INT 29
8000:014F CD21 INT 21
8000:0151 C3 RET
Nochmal die Hauptschleife. Wir haben sowohl in
EDI, als auch in ESI einen Pointer zur Adresse der Daten.
BP wird auf das Passwort zeigen.
8000:0125 MOV AX,word ptr[SI]
add esi,0x0002
8000:0126 B311 MOV BL,11
8000:0128 294E00 SUB [BP+00],CX
8000:012B 334600 XOR AX,[BP+00]
8000:012E 31C8 XOR AX,CX
8000:0130 45 INC BP
8000:0131 83FD66 CMP BP,+66
8000:0134 7203 JB 0139
8000:0136 BD5D00 MOV BP,005D
8000:0139 FECB DEC BL
8000:013B 75EB JNZ 0128
8000:013D AB mov word ptr[DI],ax
add ax,2
8000:013E E2E5 sub ecx,1
jnz 0125
Ist etwa:
repeat
for b := 17 downto 1 do
begin
passwort[b MOD (passwortlen+1)] -= counter;
datenwort[counter] := datenwort[counter] xor passwort[b MOD (passwortlen+1)];
datenwort[counter] := datenwort[counter] xor counter;
end;
counter -= 1;
until counter=0;
Evtl. ein kleiner Fehler in der Übersetzung, aber grob das
macht die Hauptschleife.
Grus
Jan
Mal abgesehen davon, daß Outlook Express (auf das dieser kleine Trick
wahrscheinlich abzielt) tatsächlich eine Krankheit ist, muß sowas nun
wirklich nicht sein...
Und auch im selbigen läßt es sich lesen :-)
(Quelltexte sind immer interessant,
egal ob asm, x-beliebige "Hoch"sprache oder News :-)
MfG
Thomas
(der in Ermangelung eines "orndlichen" News/Mail Clienten, der allen
Anforderungen gerecht wird, Outlook Express verwendet)
>ok, also der quelltext sieht folgendermaßen aus:
Ja, der zweispaltige Satz sieht recht hübsch aus, läßt sich aber nur
ziemlich beschissen kommentieren.
Noch einmal bitte. In vernünftiger Form.
>Und dann noch doppelspaltig und ohne richtige lables.
Noch einer, dem das aufgefallen ist. ;o)
>für den habe ich das ganze
>mal in einer hoffentlich verständlicheren Form erstellt:
Das wäre eigentlich Aufgabe des OP gewesen. Aber da du dir nunmal die
Arbeit gemacht hast, will ich mal nicht so sein und den Kram
auseinandernehmen.
...
>0CFC:0100 81FC39B1 CMP SP,B139
>0CFC:0104 7244 JB 014A
Hier wird erstmal der freie Platz auf dem Stack geprüft und, falls er
nicht "reicht", wird zum Ende (Label Exit) gesprungen. Naja... Wer
verwendet schon Paßwörter mit knapp 65000 Zeichen...
>0CFC:0106 BD5D00 MOV BP,005D
>0CFC:0109 BA5201 MOV DX,0152
Redo:
>0CFC:010C B939AD MOV CX,AD39
>0CFC:010F 31DB XOR BX,BX
>0CFC:0111 B43F MOV AH,3F
>0CFC:0113 CD21 INT 21
>0CFC:0115 7233 JB 014A
Es wird also eine Zeile (also bis Return-Taste) von stdin in den
Speicher gelesen, und zwar ab dem Label Buffer. Maximal werden $ad39
Zeichen eingelesen. Tritt dabei ein Fehler auf, geht's wieder ab nach
Exit.
>0CFC:0117 09C0 OR AX,AX
>0CFC:0119 7436 JZ 0151
Wenn garkein Zeichen gelesen wurde, wird das Programm unsauber per ret
verlassen. Naja, dürfte eh' unwahrscheinlich sein, daß man von stdin
nicht lesen kann.
>0CFC:011B 89C1 MOV CX,AX
>0CFC:011D 51 PUSH CX
Die Anzahl der gelesenen Zeichen kommt in den Schleifenzähler und wird
sich für die Ausgabe des Ergebnisses weiter unten gemerkt.
>0CFC:011E 41 INC CX
>0CFC:011F D1E9 SHR CX,1
Er möchte nicht mit Bytes operieren, sondern mit Words. Also
Schleifenzähler durch Zwei teilen und aufrunden, falls es eine ungerade
Zahl Zeichen in der Eingabe waren.
Tja, und nun kommt der Kern der Sache.
>0CFC:0121 89D6 MOV SI,DX
>0CFC:0123 89D7 MOV DI,DX
Zeiger für In- und Output der Routine auf den Lesepuffer initialisieren.
OuterLoop:
>0CFC:0125 AD LODSW
Ein Wort der Eingabe einlesen. (Danach Eingabezeiger +2)
>0CFC:0126 B311 MOV BL,11
Innerer Schleifenzähler auf $11.
InnerLoop:
>0CFC:0128 294E00 SUB [BP+00],CX
Ooops. Hier pfuscht er im PSP des Programms ab Offset $5d rum. Müßte man
mal nachschauen, was da eigentlich steht, ich hab' aber jetzt keine
brauchbare DOS-Doku hier. Möglicherweise bekommt dieses Proggie hier
eine Art "Schlüssel" von einem aufrufenden Programm übergeben.
Jedenfalls, was da auch immer steht, er zieht jedenfalls die Anzahl der
noch zu bearbeitenden Worte davon ab.
>0CFC:012B 334600 XOR AX,[BP+00]
Was dabei rauskommt, xored er mit dem gelesenen Wort.
>0CFC:012E 31C8 XOR AX,CX
Und dann nochmal mit der Anzahl der noch zu lesenden Worte.
>0CFC:0130 45 INC BP
Und setzt den Zeiger in den PSP eins rauf.
>0CFC:0131 83FD66 CMP BP,+66
>0CFC:0134 7203 JB 0139
Jedenfalls solange der kleiner als $66 ist.
>0CFC:0136 BD5D00 MOV BP,005D
Ansonsten wird der Zeiger wieder auf $5d gesetzt.
>0CFC:0139 FECB DEC BL
>0CFC:013B 75EB JNZ 0128
Ende der inneren Schleife.
>0CFC:013D AB STOSW
Abspeicherung des mühsam errechneten Ergebnisses auf genau die Addresse
im Puffer, von der die Daten gelesen wurden. (Danach Ausgabezeiger +2)
>0CFC:013E E2E5 LOOP 0125
Ende der äußeren Schleife.
>0CFC:0140 59 POP CX
>0CFC:0141 BB0100 MOV BX,0001
>0CFC:0144 B440 MOV AH,40
>0CFC:0146 CD21 INT 21
>0CFC:0148 73C2 JNB 010C
Hier wird die verwurstelte Eingabe dann nach stdout geschrieben. Sollte
dabei ein Fehler auftreten, geht's beim Label Redo fast von vorne neu
los.
Exit:
>0CFC:014A B8074C MOV AX,4C07
;kleiner Sparfuchs. Einmal Parameter laden und gleich in zwei
;Funktionsaufrufen verwenden.
>0CFC:014D CD29 INT 29
;Zeichen Nr. 7 (bell) auf der Konsole ausgeben
>0CFC:014F CD21 INT 21
;und zurück zur Shell mit Fehlercode 7. Unabhängig vom Ergebnis. Naja...
>0CFC:0151 C3 RET
Buffer:
hier noch mal das listing in besserer form.
A100
CMP SP,B139
JB 14A
MOV BP,5D
MOV DX,152
MOV CX,AD39
XOR BX,BX
MOV AH,3F
INT 21
JB 14A
OR AX,AX
JZ 151
MOV CX,AX
PUSH CX
INC CX
SHR CX,1
MOV SI,DX
MOV DI,DX
LODSW
MOV BL,11
SUB [BP],CX
XOR AX,[BP]
XOR AX,CX
INC BP
CMP BP,66
JB 139
MOV BP,5D
DEC BL
JNZ 128
STOSW
LOOP 125
POP CX
MOV BX,1
MOV AH,40
INT 21
JNB 10C
MOV AX,4C07
INT 29
INT 21
RET
Thomas
>hier noch mal das listing in besserer form.
[...]
>MOV BP,5D
[...]
>SUB [BP],CX
[...]
>INC BP
>CMP BP,66
[...]
Ja, hast du fein gemacht. ;o)
Deswegen gibt's auch noch eine Ergänzung zu meinem gestrigen Posting,
denn ich habe meine RBIL wiedergefunden. Da steht zu dem fraglichen Teil
des PSP folgendes:
5Ch 16 BYTEs first default FCB, filled in from first commandline
argument
Da er auf $5d anfängt, ist es also das Feld ab Offset 1 der
FCB-Struktur. Die RBIL sagt dazu:
01h 8 BYTEs blank-padded file name
09h 3 BYTEs blank-padded file extension
Also alles klar. Wenn kein Kommandozeilenparameter übergeben wird, sind
die benutzten 11 Bytes mit Leerzeichen ($20) vorinitialisiert.
Damit hast du jetzt alle Infos, um das Ding in einer beliebigen Sprache
deiner Wahl nachzuprogrammieren.
vielen Dank an alle für die super Unterstützung.
Thomas