Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > General Coding
You last visited: Today at 13:41

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



Assembler Code analysieren

Discussion on Assembler Code analysieren within the General Coding forum part of the Coders Den category.

Reply
 
Old   #1
 
Belur's Avatar
 
elite*gold: 0
Join Date: Jul 2009
Posts: 3,441
Received Thanks: 1,473
Assembler Code analysieren

Hey, ich habe bei einer Aufgabe Schwierigkeiten zu verstehen, was folgender Assembler-Code macht.
Das zugehörige Programm akzeptiert als Übergabeparameter eine Seriennummer und prüft ob diese gültig oder ungültig ist. Nun geht es darum den Algorithmus rauszufinden bzw. das Schema nach welchem die Nummern akzeptiert werden.

Dazu folgender disassemblierter Code:
Code:
Dump of assembler code for function check_key:
   0x00000000004005bd <+0>:	push   %rbp
   0x00000000004005be <+1>:	mov    %rsp,%rbp
   0x00000000004005c1 <+4>:	sub    $0x20,%rsp
   0x00000000004005c5 <+8>:	mov    %rdi,-0x18(%rbp)
   0x00000000004005c9 <+12>:	mov    -0x18(%rbp),%rax
   0x00000000004005cd <+16>:	mov    %rax,%rdi
   0x00000000004005d0 <+19>:	mov    $0x0,%eax
   0x00000000004005d5 <+24>:	callq  0x4004c0 <atoi@plt>
   0x00000000004005da <+29>:	mov    %eax,-0x4(%rbp)
   0x00000000004005dd <+32>:	cmpl   $0x0,-0x4(%rbp)
   0x00000000004005e1 <+36>:	jne    0x4005ea <check_key+45>
   0x00000000004005e3 <+38>:	mov    $0xffffffff,%eax
   0x00000000004005e8 <+43>:	jmp    0x40062e <check_key+113>
   0x00000000004005ea <+45>:	mov    -0x4(%rbp),%edx
   0x00000000004005ed <+48>:	mov    %edx,%eax
   0x00000000004005ef <+50>:	shl    $0x2,%eax
   0x00000000004005f2 <+53>:	add    %edx,%eax
   0x00000000004005f4 <+55>:	add    %eax,%eax
   0x00000000004005f6 <+57>:	add    %edx,%eax
   0x00000000004005f8 <+59>:	mov    %eax,-0x4(%rbp)
   0x00000000004005fb <+62>:	mov    -0x4(%rbp),%eax
   0x00000000004005fe <+65>:	mov    %eax,%edx
   0x0000000000400600 <+67>:	shr    $0x1f,%edx
   0x0000000000400603 <+70>:	add    %edx,%eax
   0x0000000000400605 <+72>:	sar    %eax
   0x0000000000400607 <+74>:	mov    %eax,-0x4(%rbp)
   0x000000000040060a <+77>:	sarl   $0x3,-0x4(%rbp)
   0x000000000040060e <+81>:	addl   $0xf7f9,-0x4(%rbp)
   0x0000000000400615 <+88>:	subl   $0x13c,-0x4(%rbp)
   0x000000000040061c <+95>:	cmpl   $0x17,-0x4(%rbp)
   0x0000000000400620 <+99>:	jne    0x400629 <check_key+108>
   0x0000000000400622 <+101>:	mov    $0x0,%eax
   0x0000000000400627 <+106>:	jmp    0x40062e <check_key+113>
   0x0000000000400629 <+108>:	mov    $0x1,%eax
   0x000000000040062e <+113>:	leaveq 
   0x000000000040062f <+114>:	retq   
End of assembler dump.
#Edit: Hier das gleiche nochmal in Intel-Syntax:
Ich muss dazu sagen, dass ich mich vorher nie wirklich mit Assembler beschäftigt habe.
Deswegen ein paar Fragen:

Code:
mov    %rdi,-0x18(%rbp)
Hier verschiebe ich also den Inhalt aus %rdi an die Stelle -0x18(%rbp) (also 24Bytes vor dem Register rbp.
Falls das nun ein 4Byte int ist. Steht der dann in positiver oder negativer Richtung praktisch? Also von: -0x18(%rbp) bis -0x14(%rbp) oder von -0x18(%rbp) bis -0x1C(%rbp).

Danach wird vermutlich mein char*-Übergabeparameter mit atoi in ein int umgewandelt. Woher weiß ich da in welches Register bzw an. welche Stelle der Wert geschrieben wird?

Ich würde jetzt mal raten, dass der int-Wert nach -0x4(%rbp) geschrieben wurde.
Und danach wird geprüft ob der Wert 0 ist?
Code:
cmpl   $0x0,-0x4(%rbp)
Falls ja, dann wird der maximale int-Wert in das %eax Register geschrieben und die Methode verlassen?



Mir gehts prinzipiell erstmal darum den Code bis zum ersten "cmpl" zu verstehen. Habe da so etwas meine Schwierigkeiten. Evtl. kennt auch einer gute Literatur wo man sich einlesen kann.
Der Assembler Code ist für eine x86 Maschine (64Bit).

Hoffe mich kann da jemand etwas aufklären.

Grüße
Belur is offline  
Old 10/11/2015, 17:13   #2
 
Shadow992's Avatar
 
elite*gold: 77
Join Date: May 2008
Posts: 5,430
Received Thanks: 5,878
Quote:
Originally Posted by Belur View Post
Hey, ich habe bei einer Aufgabe Schwierigkeiten zu verstehen, was folgender Assembler-Code macht.
Das zugehörige Programm akzeptiert als Übergabeparameter eine Seriennummer und prüft ob diese gültig oder ungültig ist. Nun geht es darum den Algorithmus rauszufinden bzw. das Schema nach welchem die Nummern akzeptiert werden.

Dazu folgender disassemblierter Code:
Code:
Dump of assembler code for function check_key:
   0x00000000004005bd <+0>:	push   %rbp
   0x00000000004005be <+1>:	mov    %rsp,%rbp
   0x00000000004005c1 <+4>:	sub    $0x20,%rsp
   0x00000000004005c5 <+8>:	mov    %rdi,-0x18(%rbp)
   0x00000000004005c9 <+12>:	mov    -0x18(%rbp),%rax
   0x00000000004005cd <+16>:	mov    %rax,%rdi
   0x00000000004005d0 <+19>:	mov    $0x0,%eax
   0x00000000004005d5 <+24>:	callq  0x4004c0 <atoi@plt>
   0x00000000004005da <+29>:	mov    %eax,-0x4(%rbp)
   0x00000000004005dd <+32>:	cmpl   $0x0,-0x4(%rbp)
   0x00000000004005e1 <+36>:	jne    0x4005ea <check_key+45>
   0x00000000004005e3 <+38>:	mov    $0xffffffff,%eax
   0x00000000004005e8 <+43>:	jmp    0x40062e <check_key+113>
   0x00000000004005ea <+45>:	mov    -0x4(%rbp),%edx
   0x00000000004005ed <+48>:	mov    %edx,%eax
   0x00000000004005ef <+50>:	shl    $0x2,%eax
   0x00000000004005f2 <+53>:	add    %edx,%eax
   0x00000000004005f4 <+55>:	add    %eax,%eax
   0x00000000004005f6 <+57>:	add    %edx,%eax
   0x00000000004005f8 <+59>:	mov    %eax,-0x4(%rbp)
   0x00000000004005fb <+62>:	mov    -0x4(%rbp),%eax
   0x00000000004005fe <+65>:	mov    %eax,%edx
   0x0000000000400600 <+67>:	shr    $0x1f,%edx
   0x0000000000400603 <+70>:	add    %edx,%eax
   0x0000000000400605 <+72>:	sar    %eax
   0x0000000000400607 <+74>:	mov    %eax,-0x4(%rbp)
   0x000000000040060a <+77>:	sarl   $0x3,-0x4(%rbp)
   0x000000000040060e <+81>:	addl   $0xf7f9,-0x4(%rbp)
   0x0000000000400615 <+88>:	subl   $0x13c,-0x4(%rbp)
   0x000000000040061c <+95>:	cmpl   $0x17,-0x4(%rbp)
   0x0000000000400620 <+99>:	jne    0x400629 <check_key+108>
   0x0000000000400622 <+101>:	mov    $0x0,%eax
   0x0000000000400627 <+106>:	jmp    0x40062e <check_key+113>
   0x0000000000400629 <+108>:	mov    $0x1,%eax
   0x000000000040062e <+113>:	leaveq 
   0x000000000040062f <+114>:	retq   
End of assembler dump.
Ich muss dazu sagen, dass ich mich vorher nie wirklich mit Assembler beschäftigt habe.
Deswegen ein paar Fragen:

Code:
mov    %rdi,-0x18(%rbp)
Hier verschiebe ich also den Inhalt aus %rdi an die Stelle -0x18(%rbp) (also 24Bytes vor dem Register rbp.
Falls das nun ein 4Byte int ist. Steht der dann in positiver oder negativer Richtung praktisch? Also von: -0x18(%rbp) bis -0x14(%rbp) oder von -0x18(%rbp) bis -0x1C(%rbp).

Danach wird vermutlich mein char*-Übergabeparameter mit atoi in ein int umgewandelt. Woher weiß ich da in welches Register bzw an. welche Stelle der Wert geschrieben wird?

Ich würde jetzt mal raten, dass der int-Wert nach -0x4(%rbp) geschrieben wurde.
Und danach wird geprüft ob der Wert 0 ist?
Code:
cmpl   $0x0,-0x4(%rbp)
Falls ja, dann wird der maximale int-Wert in das %eax Register geschrieben und die Methode verlassen?



Mir gehts prinzipiell erstmal darum den Code bis zum ersten "cmpl" zu verstehen. Habe da so etwas meine Schwierigkeiten. Evtl. kennt auch einer gute Literatur wo man sich einlesen kann.
Der Assembler Code ist für eine x86 Maschine (64Bit).

Hoffe mich kann da jemand etwas aufklären.

Grüße
Ich bin einmal ganz ehrlich:
Da ich die AT&T-Syntax wirklich verabscheue, habe ich mir den Code nur ganz grob angeschaut, aber was ich soweit sagen kann:

1. Bei x86-64 gibt es nur 2 verschiedene Arten eine Funktion zu callen einmal die "Microsoft"-Variante und die "System V AMD64"-Variante.
Ich vermute dein Code lief/läuft auf einem Linux-System, weil unter Windows meistens die Intel-Syntax benutzt wird.
Daher werden all Funktionen wie folgt gecalled:
Quote:
The calling convention of the System V AMD64 ABI is followed on Solaris, Linux, FreeBSD, Mac OS X, and other UNIX-like or POSIX-compliant operating systems. The first six integer or pointer arguments are passed in registers RDI, RSI, RDX, RCX, R8, and R9, while XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6 and XMM7 are used for floating point arguments. For system calls, R10 is used instead of RCX.

Quelle: https://en.wikipedia.org/wiki/X86_calling_conventions
Das heißt wenn ich die Syntax richtig lese, müsste in "rdi" der Pointer zu deinem String stehen.

2.
Das Ergebnis, also der Return-Wert, sollte ,wie immer und wie auch bei vielen 32Bit-Calls (korrigiert mich wenn ich falsch liege), in "eax" bzw. "rax" liegen.

3.
Ein "mov %rdi,-0x18(%rbp)" fängt an der Stelle "rbp-0x18" an zu schreiben und schreibt dann an die Stelle "rbp-0x17" das nächste Byte ...
In Intel-Syntax ist das etwas "intuitiver" dargestellt wie ich finde:
"mov [rbp-0x18], rdi" (man beachte die vertauschte Reihenfolge der Intel-Syntax).

4.
Eigentlich alle Register mit einem "r" vorne und der Zeichenlänge von 3 sind 8Byte = 64Bit groß. Register mit einem "e" an erster Stelle + Zeichenlänge 3 normalerweise 4Byte und Register mit Zeichenlänge 2, 2Byte.
Ich bin mir gerade unsicher, ob das wirklich immer in allen Fällen zutrifft, aber zumindest in 99% der Fälle passt das.
Shadow992 is offline  
Thanks
1 User
Old 10/11/2015, 17:47   #3
 
Belur's Avatar
 
elite*gold: 0
Join Date: Jul 2009
Posts: 3,441
Received Thanks: 1,473
Besten Dank.

Ich füge mal den Code in Intel-Syntax hinzu. Vermutlich ist das für die meisten besser lesbar. Defaultmäßig war im gdb AT&T eingestellt.
Belur is offline  
Old 10/11/2015, 18:08   #4


 
Jeoni's Avatar
 
elite*gold: 966
Join Date: Apr 2010
Posts: 1,105
Received Thanks: 681
Da jetzt auch die Intel-Syntax verfügbar und mir langweilig war, habe ich mir mal die Mühe gemacht das nach C zu übersetzen. Raus kam folgendes:
Code:
int CheckKey(
	const char* arg0 // @ rbp - 0x18
	)
{
	int var0 = atoi(arg0); // @ rbp - 4
	if (var0 == 0)
	{ // @ +38
		return -1;
	}
	var0 = (((var0 << 2) + var0) * 2) + var0; // @ +45 to +62
	var0 = (var0 + (var0 >> 31)) >> 1; // @ +62 to +77
	var0 >>= 3; // @ +77
	var0 += 0xf7f9; // @ +81
	var0 -= 0x13c; // @ +88
	return (var0 == 0x17) ? 0 : 1;
}
Hab an ein paar Stellen rangeschrieben von wo es kommt, aber auch dort, wo nichts steht, sollte sich dann recht leicht wiederfinden lassen. So groß ist die Funktion ja nicht
Wenn etwas unklar ist, frag einfach. Ich weiß nicht, wie detailliert erklärt du es brauchst
Ein paar Grundlagen hat Shadow ja schon erläutert.
Mit freundlichen Grüßen
Jeoni
Jeoni is offline  
Thanks
2 Users
Old 10/11/2015, 18:17   #5
 
Belur's Avatar
 
elite*gold: 0
Join Date: Jul 2009
Posts: 3,441
Received Thanks: 1,473
Vielen Dank, das werde ich mir sofort nochmal detailliert anschauen.

Nur mal aus Interesse: Haste das so "frei Hand" reverse-engineered oder mit Hilfe irgendeines Tools? IDA Pro oder Hopper oder wie sie alle heißen.

Respekt auf jeden Fall, da wär so schnell nicht hingekommen
Belur is offline  
Old 10/11/2015, 18:27   #6


 
Jeoni's Avatar
 
elite*gold: 966
Join Date: Apr 2010
Posts: 1,105
Received Thanks: 681
Das war frei Hand. Bzw. mit Visual Studio als Editor, aber da hätte es auch jeder Andere getan. IDA nutze ich sehr gerne bei größeren Projekten. Da ist es denn auch eine Hilfe, wenn man die Funktionen / Variablen (lokal wie global) frei benennen kann und das dann im gesamten restlichen Code automatisch übernommen wird. Hier waren es ja nur 2 lokale Variablen (von denen nicht eine nötig gewesen wäre), die kann ich mir noch so merken.
Wäre hier jetzt komplizierter gewesen die Funktion in IDA reinzubekommen als das tatsächliche Analysieren

Mit freundlichen Grüßen
Jeoni
Jeoni is offline  
Thanks
1 User
Old 10/11/2015, 19:07   #7
 
Belur's Avatar
 
elite*gold: 0
Join Date: Jul 2009
Posts: 3,441
Received Thanks: 1,473
Ich komme einfach mal mit dem zweiten Teil

Zu der check_key Funktion gibt es natürlich noch die main:
Code:
Dump of assembler code for function main:
   0x0000000000400630 <+0>:	push   rbp
   0x0000000000400631 <+1>:	mov    rbp,rsp
   0x0000000000400634 <+4>:	sub    rsp,0x20
   0x0000000000400638 <+8>:	mov    DWORD PTR [rbp-0x14],edi
   0x000000000040063b <+11>:	mov    QWORD PTR [rbp-0x20],rsi
   0x000000000040063f <+15>:	cmp    DWORD PTR [rbp-0x14],0x2
   0x0000000000400643 <+19>:	je     0x400665 <main+53>
   0x0000000000400645 <+21>:	mov    rax,QWORD PTR [rbp-0x20]
   0x0000000000400649 <+25>:	mov    rax,QWORD PTR [rax]
   0x000000000040064c <+28>:	mov    rsi,rax
   0x000000000040064f <+31>:	mov    edi,0x400734
   0x0000000000400654 <+36>:	mov    eax,0x0
   0x0000000000400659 <+41>:	call   0x400490 <printf@plt>
   0x000000000040065e <+46>:	mov    eax,0x1
   0x0000000000400663 <+51>:	jmp    0x4006a1 <main+113>
   0x0000000000400665 <+53>:	mov    rax,QWORD PTR [rbp-0x20]
   0x0000000000400669 <+57>:	add    rax,0x8
   0x000000000040066d <+61>:	mov    rax,QWORD PTR [rax]
   0x0000000000400670 <+64>:	mov    rdi,rax
   0x0000000000400673 <+67>:	call   0x4005bd <check_key>
   0x0000000000400678 <+72>:	mov    DWORD PTR [rbp-0x4],eax
   0x000000000040067b <+75>:	cmp    DWORD PTR [rbp-0x4],0x0
   0x000000000040067f <+79>:	jne    0x400692 <main+98>
   0x0000000000400681 <+81>:	mov    edi,0x400745
   0x0000000000400686 <+86>:	call   0x400480 <puts@plt>
   0x000000000040068b <+91>:	mov    eax,0x0
   0x0000000000400690 <+96>:	jmp    0x4006a1 <main+113>
   0x0000000000400692 <+98>:	mov    edi,0x40075b
   0x0000000000400697 <+103>:	call   0x400480 <puts@plt>
   0x000000000040069c <+108>:	mov    eax,0x1
   0x00000000004006a1 <+113>:	leave  
   0x00000000004006a2 <+114>:	ret    
End of assembler dump.
Es fällt mir allgemein sehr schwer, zu verstehen was da gemacht wird:
zB:
Code:
mov    rax,QWORD PTR [rbp-0x20]
add    rax,0x8
mov    rax,QWORD PTR [rax]
Also eine Variable wird in ein Register geladen? Danach wird die Variable um 8 inkrementiert. Und was ist der 3. Schritt? Wird die inkrementierte Variable wieder in "rax" gemovt? Sollte sie da nicht schon drinstehen? Oder passiert da evtl. doch was ganz anderes.
Bevor der Key geprüft wird der Schlüssel + 8 gerechnet?

Eine andere Sache wäre: Beim ersten cmp wird [rbp-0x14] mit 2 verglichen. Ich kann mir jetzt nur vorstellen dass damit die Länge des args-Arrays gemeint ist. Weil wenn die nicht passt wird auch eine Fehlermeldung ausgegeben. Vor dem print passieren aber dann noch etliche andere Sachen.


Gibt es irgendein gutes Buch a la "Assembler from scratch" oder eine gute Seite wo man Schritt für Schritt die Befehle nachvollziehen kann?
Belur is offline  
Old 10/11/2015, 20:03   #8

 
elite*gold: 150
Join Date: Apr 2007
Posts: 2,394
Received Thanks: 6,644
Bei schritt 3 ist RAX eine Addresse, der Wert der an der Addresse steht wird in RAX gepackt.
wurstbrot123 is offline  
Thanks
1 User
Old 10/11/2015, 20:14   #9


 
Jeoni's Avatar
 
elite*gold: 966
Join Date: Apr 2010
Posts: 1,105
Received Thanks: 681
Code:
mov    rax, QWORD PTR [rax]
Dies dereferenziert rax und lädt das Ergebnis wieder nach rax. Man könnte es sich in C folgendermaßen vorstellen:
Code:
rax = *rax;
(Register sind natürlich untypisiert)

Das erste cmp vergleicht die lokale Variable an rbp-0x14 mit 2. Die lokale Variable wird zwei Zeilen darüber mit RDI, welches dort das erste Argument von main enthält, gefüllt. Du gehst also recht in der Annahme, dass es sich dort um argc handelt.

Das Argument für die check_key funktioniert kommt letztlich ja aus der lokalen Variable an rbp-0x20. Oben in main sieht man wie diese Variable mit RSI, laut der Aufrufkonvention also dem zweiten Argument von main (argv) gefüllt wird.
Wenn man sich nun ansieht, was damit gemacht wird, um zum argument für die check_key Funktion zu gelangen kommt man für den Aufruf erstmal auf sowas:
Code:
check_key(*(argv + 8))
(mal unter der Annahme, dass es keine Typen gäbe und Pointerarithmetik uns hier nicht aufhält)
argv ist allgemein bekannt als Array aus Pointern auf (konstante) Zeichenketten (const char*[]). 8 ist, da es x64 ist, genau einmal die Pointergröße. Was hier also passiert ist, dass auf den Eintrag von argv an Index 1 zugegriffen wird.
Code:
check_key(argv[1])
Damit macht der vorherige Check von argc natürlich auch Sinn.

Kann leider keine Empfehlungen für Bücher oder Tutorials machen, ich habe mir das eigentlich alles selbst beigebracht (und ein paar Mal bei Bekannten nachgefragt). Wenn ich eine Instruktion nicht kannte, habe ich sie bei Google gesucht. Als Referenz nutze ich häufig , aber gab auch schon Instruktionen, die dort nicht erläutert wurden. Nebenbei muss man dann natürlich sich auch Wissen zu den Registern und Aufrufkonventionen aneignen. Ist dann auch recht lehrreich, wenn man sich den asm Code ansieht, den der Compiler aus eigenem Source Code ausspuckt. Dann fallen einen noch eher die Zusammenhänge auf, was beim Rückübersetzen von asm dann natürlich auch nützlich ist.

Mit freundlichen Grüßen
Jeoni
Jeoni is offline  
Thanks
1 User
Old 10/11/2015, 20:39   #10
 
Belur's Avatar
 
elite*gold: 0
Join Date: Jul 2009
Posts: 3,441
Received Thanks: 1,473
Danke, die Seite speicher ich mir auch mal ab

Werde vor allem die Berechnungen in der check_key Methode morgen nochmal Schritt für Schritt durchgehen. Irgendein System muss da ja hintersteken, sodass man das vereinfachen kann.

Rein theoretisch müsste ich ja so alle gültigen Schlüssel ausgeben lassen können:
Code:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
	int var0;
	int i;
	for (i = 0; i <= 9223372036854775807; i++) {
		var0=i;
		var0 = (((var0 << 2) + var0) * 2) + var0; // @ +45 to +62
		var0 = (var0 + (var0 >> 31)) >> 1; // @ +62 to +77
		var0 >>= 3; // @ +77
		var0 += 0xf7f9; // @ +81
		var0 -= 0x13c; // @ +88
		if (var0 == 0x17){
			printf("%d", i);
		}
	}

}
Und er findet tatsächlich passende Schlüssel.
Respekt ich war echt skeptsich ob das mit den ganzen Klammern und Shifts passt O.o
Belur is offline  
Old 10/11/2015, 20:52   #11


 
Jeoni's Avatar
 
elite*gold: 966
Join Date: Apr 2010
Posts: 1,105
Received Thanks: 681
Jetzt wo ich mir die neue Aufgabenstellung ansehe, fällt mir ein Fehler in meinem rückübersetztem Code auf. Korrigiert sollte es so lauten:
Code:
int CheckKey(
	const char* arg0 // @ rbp - 0x18
	)
{
	int var0 = atoi(arg0); // @ rbp - 4
	if (var0 == 0)
	{ // @ +38
		return -1;
	}
	var0 = (((var0 << 2) + var0) * 2) + var0; // @ +45 to +62
	var0 = (var0 + (var0 >> 31)) / 2; // @ +62 to +77
	var0 /= 8; // @ +77
	var0 += 0xf7f9; // @ +81
	var0 -= 0x13c; // @ +88
	return (var0 == 0x17) ? 0 : 1;
}
Falls es dich interessiert: Ich hatte "sar" für einen einfachen Shift gehalten, der es aber nicht ist. Andernfalls wäre 0x17 wohl nicht erreichbar, wenn ich mich jetzt auf die schnelle nicht vertan habe.
Mit freundlichen Grüßen
Jeoni
Jeoni is offline  
Thanks
1 User
Old 10/11/2015, 20:58   #12
 
Belur's Avatar
 
elite*gold: 0
Join Date: Jul 2009
Posts: 3,441
Received Thanks: 1,473
Also deine erste Version scheint richtig zu sein.

Wenn ich alle ints durchgehe und jedes Mal die Berechnung ausführe bekomme ich gültige Schlüssel.
zB:
390359730
780811302
780811303

Bei deiner zweiten Lösung kommen keine gültigen Schlüssel raus. Von daher war die erste Berechnung wohl doch richtig.
Belur is offline  
Old 10/11/2015, 21:05   #13


 
Jeoni's Avatar
 
elite*gold: 966
Join Date: Apr 2010
Posts: 1,105
Received Thanks: 681
Nein, die Lösung des "korrigierten" Codes liegt lediglich im negativem Bereich, wie ich gerade durch Rückentwickeln festgestellt habe. Mit einer Eingabe von -91843 ist das Endergebnis nach den paar Operationen ebenso 23 (0x17). Ich bin mir recht sicher (aber das will nichts heißen), dass meine korrigierte Fassung die korrektere ist, da die benutzte sar-Instruktion eben kein normaler Shift ist, sondern sich wie ein n-faches vorzeichenbehaftetes Teilen durch 2 verhält, was meine erste Version außer Acht lässt. Dies wäre korrekt, wenn statt "sar" die "shr" Instruktion benutzt werden würde.
Referenz: .
Obige Zahl ist meines Wissens nach auch die einzige Lösung, so dass sich die check_key Methode auf ein simples
Code:
atoi(argv[1]) == -91843)
reduzieren ließe.
Mit freundlichen Grüßen
Jeoni
Jeoni is offline  
Thanks
1 User
Old 10/11/2015, 21:30   #14
 
Belur's Avatar
 
elite*gold: 0
Join Date: Jul 2009
Posts: 3,441
Received Thanks: 1,473
Interessant, du hast da mehr Ahnung als ich, deswegen vertraue ich dir mal.

Da deine erste Lösung aber nur passende Schlüssel generiert, muss es auch irgendwie passen. Eine Aufgabe ist auch einen Keygenerator zu schreiben, der nur passende Schlüssel generiert. Das spricht ja auch dafür, dass es mehr als einen passenden Schlüssel gibt.

Falls du dich selbst überzeugen möchtest, hab ich das Programm einfach mal angehängt.
-91843 ist allerdings auch eine korrekte Eingabe für das Programm. Ich kanns mir nicht wirklich erklären, aber deine "nicht-ganz-korrekte" Version produziert ausschließlich korrekte Schlüssel.
Attached Files
File Type: zip schluessel.zip (2.6 KB, 0 views)
Belur is offline  
Thanks
1 User
Old 10/11/2015, 21:39   #15


 
Jeoni's Avatar
 
elite*gold: 966
Join Date: Apr 2010
Posts: 1,105
Received Thanks: 681
Ah, jetzt hab ich's. Bei positiver Eingabe ist ja egal, ob shr ("richtiger" Shift) oder sar (n-faches vorzeichenbehaftetes Dividieren durch 2). Das heißt, dass die zweite, korrigierte Version den positiven Lösungsraum der ersten Version, von der du ja schon Schlüssel gefunden hast, inkludiert, sich der negative Lösungsraum jedoch unterscheidet.
Die zweite Version ist in der Tat korrekter, aber meine Annahme, dass es nur eine einzige Lösung gäbe, war falsch, was wohl darauf zurückzuführen ist, dass ich die Divisionen nicht mehr als Shifts gesehen habe, was sie ja immernoch sind.
Vielleicht gehst du auch nochmal den negativen Zahlenraum durch, vielleicht befindet sich dort ja auch noch eine Lösung, wobei ich das irgendwie nicht glaube.
Mit freundlichen Grüßen
Jeoni
Jeoni is offline  
Thanks
1 User
Reply


Similar Threads Similar Threads
Assembler Code *YaY*
10/24/2013 - General Coding - 17 Replies
Hallo, ich habe seit Neustem im Studium (Wirtschaftsinformatik) den Kurs Informatik I. Im Zuge der ersten Übungen sollen wir, bevor es mit Java los/weiter geht mit Assembler Code bzw. auch in Maschinensprache programmieren. Eine unserer ersten Aufgaben lautet, die Formel x = (x-5) * (x+3) in Assembler Code zu übersetzen. Dafür haben wir eine kleine Tabelle mit Befehlen in der Assembler Sprache bekommen: Define x y27 Load x18 Store x03 Add c07 AddMem x05 Mult c09 MultMem x Die...
Assembler code
12/05/2011 - Off Topic - 2 Replies
Hello im studing some basic with assembler and I have got a task to make a code(on assembler) which would make my initials. I still dont know the right task,just that i have to make assembler to show me my initials(like a picture, teacher said somethign about pixels).So I decided to ask you guys for some help, maybe someone already did a similar task. I wish to see how that code looks, doenst matter what initials used. (would be nice M and P, this are my ones :D )
Suche Assembler tutorials für Bot Programmierung (packete analysieren)
08/09/2009 - General Coding - 16 Replies
Hey Leute Möchte Bots mittels c++ schreiben und brauche noch ein paar Assembler tutorials. Hoffe ihr könnt mir da helfen MFG LEri^^



All times are GMT +1. The time now is 13:42.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.