Assembler in C als string
-
Also, ich hab da mal ne Frage. (logisch)
Ich hab in asm unter linux (nasm) ein Helloworld geschrieben, kompiliert und den Hex-Code in einen String. Die Adresse auf den Hello-String hab ich angepasst und dann lass ich den string(mit assembler-hex-zeug) als mit hilfe von funktionspointer wie ne funktion gestartet. geht auch so weit, gibt das Hello world! aus und macht nen speicherzugriffsfehler (ganz am schluss). Ich find nur nich wo der Fehler is, kenn mich mit asm auch noch net soo aus. Ich stell einfach mal den Source rein, in der Hoffnung das mir jemand helfen kann... *hoff hoff hoff*#include <stdio.h> #include <stdlib.h> char Hello[]={'H','e','l','l','o',' ','W','o','r','l','d','\n','\0'}; char Hello2[]={'H','e','l','l','o',' ','w','o','r','l','d','!','\n','\0'}; char C[]={ "\xBA\x0D\x00\x00\x00" /* BA: edx - mov edx str-länge*/ "\xB9\xA5\x95\x04\x08" /* B9: ecx - mov ecx addresse d string */ "\xBB\x01\x00\x00\x00" /* BB: ebx - mov ebx 1 - stdout*/ "\xB8\x04\x00\x00\x00" /* B8: eax - mov eax 4 - sys_write*/ "\xCD\x80" /* int 80 - kernelaufruf (linux)*/ }; int main(int argc, char *argv[]) { printf("%x\n",&Hello2); printf("%s",Hello); void (*Z)()=(void*)C; Z(); return 0; }
[ Dieser Beitrag wurde am 09.11.2002 um 02:10 Uhr von Chickenman editiert. ]
-
das liegt daran, dass du den Code wie eine Funktion behandelst, dieser aber keine Funktion ist, der Aufruf von ret am Ende fehlt und so versucht die CPU Code auszuführen, der hinter dem String im Speicher liegt und das gibt den Seg Fault
schau dir mal den Text http://www.nondot.org/sabre/os/files/Booting/CompilingBinaryFilesUsingACompiler.pdf an, der hilft dir vielleicht dabei eine Funktion zu schreiben, die du ausführen kannst.
BTW.
wenn du die Adresse eines Pointers ausgeben willst, solltest du %p und nicht %x nutzen
-
Ich hab mir das jetzt angeschaut und bei dem ganzen noch ein leave und ein ret angehängt, (C9 und C3), aber es geht irgendwie immer noch nicht
-
Das leave darfst du nur anhängen wenn du auch ein enter davor gepackt hast!!
probiers mal nur mit ret(C3)!dann sollte es klappenenter und leave sind für hochsprachen gedacht und müssen paarweise benutzt werden ansonsten bringst du den stack durcheinander es sei denn du weist ganz exakt was du tust.
-
ok, hab jetzt nur ret drin, und immer noch das gleiche...
So siehts jetzt aus:"\xBA\x0D\x00\x00\x00" /* BA: edx - mov edx str-länge*/ "\xB9\x15\x94\x04\x08" /* B9: ecx - mov ecx addresse d string */ "\xBB\x01\x00\x00\x00" /* BB: ebx - mov ebx 1 - stdout*/ "\xB8\x04\x00\x00\x00" /* B8: eax - mov eax 4 - sys_write*/ "\xCD\x80" /* int 80 - kernelaufruf (linux)*/ "\xC3"
-
Sicher, dass das ganze als NEAR call aufgerufen wird?
Probiers doch mal mit retf (CB).
-
nee, auch nicht.. das programm ansich ist immer noch das gleiche wie am Anfang, nur das im string hat sich geändert
-
Soviel ich weiss, muss man Assembler-Subroutinen importieren.
Meiner Meinung nach, schreibt der C Compiler noch irgendwelche Markierungen in den Code, so dass da keine funktionierende Assembler subroutine steht, sondern nur die Zeichen. Wenn da überhaupt einer wäre ist nicht garantiert dass er auch funktioniert. Hast du ihn denn schon getestet? Ausserdem muss der Code an einer geraden Speicherstelle beginnen. Oder muss es sogar eine doubleword Grenze sein?
-
Code darf auf Intel beginnen wo er will. Das Problem wird sien, dass die Sieten in dem der "Code" steht, nicht ausführbar sind, d.h. es ist nicht erlaubt von den Seiten im Speicher Code auszuführen. Das müsste man mit nem Syscall ändern, aber ich kann dir leider net sagen wie unter Linux
-
Aber wieso funktioniert der Code dann bis zum Ende und gibt dann erst nen Fehler
-
bei mir geht der Code gar nicht (also vorher wird Hello, World! ausgegeben, durch das printf).
@Tri
warum gehen dann bufferoverflow exploits?[ Dieser Beitrag wurde am 10.11.2002 um 18:01 Uhr von kingruedi editiert. ]
-
Original erstellt von kingruedi:
**bei mir geht der Code gar nicht (also vorher wird Hello, World! ausgegeben, durch das printf).
**Was hast du für Compiler/System?
Es sollte erst die Adresse kommen (von dem String mit asm-code)
dann sollte
Hello World und
Hello world! kommen...Hello world! wird von dem asm-code ausgegeben..
Bevor das ganze läuft musst du einmal compilieren, dann die Adresse ankucken und in den Code eintragen, wo
/* B9: ecx - mov ecx addresse d string */
steht..
dh wenn als adresse 0x8049415 da steht musst du in zweierschritten rückwärts in den Code eintragen, also als erstes 15 dann 94 dann 04 als letztes 08"\xB9\x15\x94\x04\x08" /* B9: ecx - mov ecx addresse d string */ hier-> | | | |
und dann nochmal compilieren
[ Dieser Beitrag wurde am 10.11.2002 um 18:21 Uhr von Chickenman editiert. ]
[ Dieser Beitrag wurde am 10.11.2002 um 18:23 Uhr von Chickenman editiert. ]
-
gcc 3.0.4
Debian GNU/Linux Kernel 2.4.18
-
Original erstellt von kingruedi:
**gcc 3.0.4Debian GNU/Linux Kernel 2.4.18**
Hmm.. dass müsste dann eigentlich gehen.. das mit der Adresse hast du gemacht, oder? Ich könnt mich ja mal per ssh bei dir einloggen und probieren, kanns aber verstehen wen du das nicht willst
-
sonst lass den gcc das nur in asm übersetzen und poste mal den Code, das wird dann zwar in AT&T Syntax sein, aber dass ist halb so wild.
mfg
-bg-
-
Original erstellt von -bg-:
**sonst lass den gcc das nur in asm übersetzen und poste mal den Code, das wird dann zwar in AT&T Syntax sein, aber dass ist halb so wild.
**Dann aber bitte per
gcc -masm=intel -S bla.cweil das produziert schönen intel-syntax-code (ab gcc 3)
-
Original erstellt von TriPhoenix:
**Dann aber bitte per
gcc -masm=intel -S bla.cweil das produziert schönen intel-syntax-code (ab gcc 3) :D**
hab ich gemach. In dem file bla.c steht:
#include <stdio.h> #include <stdlib.h> char Hello[]={'H','e','l','l','o',' ','W','o','r','l','d','\n','\0'}; char Hello2[]={'H','e','l','l','o',' ','w','o','r','l','d','!','\n','\0'}; char C[]={ "\x55" "\x89\xE5" "\x83\xEC\x10" "\xBA\x0D\x00\x00\x00" /* BA: edx - mov edx str-länge*/ "\xB9\x15\x94\x04\x08" /* B9: ecx - mov ecx addresse d string */ "\xBB\x01\x00\x00\x00" /* BB: ebx - mov ebx 1 - stdout*/ "\xB8\x04\x00\x00\x00" /* B8: eax - mov eax 4 - sys_write*/ "\xCD\x80" /* int 80 - kernelaufruf (linux)*/ "\xC3" }; void hello() { printf("%s",Hello); } int main(int argc, char *argv[]) { printf("%p\n",&Hello2); hello(); void (*Z)()=(void*)C; Z(); return 0; }
und in der entstandenen bla.s steht:
.file "main.c" .intel_syntax .globl Hello .data .type Hello,@object .size Hello,13 Hello: .byte 72 .byte 101 .byte 108 .byte 108 .byte 111 .byte 32 .byte 87 .byte 111 .byte 114 .byte 108 .byte 100 .byte 10 .byte 0 .globl Hello2 .type Hello2,@object .size Hello2,14 Hello2: .byte 72 .byte 101 .byte 108 .byte 108 .byte 111 .byte 32 .byte 119 .byte 111 .byte 114 .byte 108 .byte 100 .byte 33 .byte 10 .byte 0 .globl C .type C,@object .size C,30 C: .string "U\211\345\203\354\020\272\r" .string "" .string "" .string "\271\025\224\004\b\273\001" .string "" .string "" .string "\270\004" .string "" .string "" .string "\315\200\303" .section .rodata .LC0: .string "%s" .text .align 2 .globl hello .type hello,@function hello: push %ebp mov %ebp, %esp sub %esp, 8 sub %esp, 8 push OFFSET FLAT:Hello push OFFSET FLAT:.LC0 call printf add %esp, 16 leave ret .Lfe1: .size hello,.Lfe1-hello .section .rodata .LC1: .string "%p\n" .text .align 2 .globl main .type main,@function main: push %ebp mov %ebp, %esp sub %esp, 8 and %esp, -16 mov %eax, 0 sub %esp, %eax sub %esp, 8 push OFFSET FLAT:Hello2 push OFFSET FLAT:.LC1 call printf add %esp, 16 call hello mov DWORD PTR [%ebp-4], OFFSET FLAT:C mov %eax, DWORD PTR [%ebp-4] call %eax mov %eax, 0 leave ret .Lfe2: .size main,.Lfe2-main .ident "GCC: (GNU) 3.2"
Ich vermute dass dann die adresse, wo der string steht nicht mehr stimmt, aber das macht ja nix. hab mir das da oben aber noch nich so genau angeschaut, werd wahrscheinlich nicht allzu viel blicken
-
kleine Zwischenfrage während ihr überlegt
Was genau hat der da aus dem String C gemacht? ich kann da irgendwie gar nix mehr rauslesen (ich mein die Stelle da)
C: .string "U\211\345\203\354\020\272\r" .string "" .string "" .string "\271\025\224\004\b\273\001" .string "" .string "" .string "\270\004" .string "" .string "" .string "\315\200\303" .section .rodata
-
Vielleicht muss man wie bei manchen Viren di Adressen alle relativ berechnen?
call relativ
relativ:
;jetzt addi vom stack holen und alles andere relativ dazu angeben.
-
ähh, ja.. kann mir jemand nen link sagen, wo das mit dem relativ erklärt ist (oder mir gleich erklären)? Bin (noch) nicht so gut in Assembler.
-
Na, ich denke mal der call wird schon stimmen...
Ansonsten kann ich auch net mehr dazu sagen, da mir ebenfalls schleierhaft ist, was der Compiler aus dem String gemacht hat.