Assembler in C als string
-
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.
-
Mir ist nochetwas äußerst merkwürdiges aufgefallen: Der Speicherzugriffsfehler passiert garnicht in Z(), sondern ich kann das programm noch alles mögliche machen lassen, und erst ganz am Schluss beim Beenden kommt der Fehler (nach return glaub ich, da bin ich mir aber nicht sicher)
Ich find das ziemlichNachtrag:
DDD (gdb) sagt mir folgendes:Program received signal SIGSEGV, Segmentation Fault.
0x40041e70 in _dl_pagesize () from /lib/libc.so.6das ist zwei steps nach der }-Klammer-Zu von main
Nachtrag 2:
hab übrigens jetzt keinen char C[]=... string mehr, sondern mit malloc angelegt und dann mit C[x]=0xSoUndSo alles reingeschrieben,dann ausgeführt und dann ordentlich free... aber es passiert auch in der alten version genauso[ Dieser Beitrag wurde am 16.11.2002 um 21:50 Uhr von Chickenman editiert. ]
-
Der Code scheint mir verdammt konfus, z.B.:
mov %eax, 0 sub %esp, %eax ;oder sub %esp, 8 sub %esp, 8 ;also ich kann 8 und 8 zusammenzählen, und gcc?
Optimiert soetwas echt???
so, hab mal nachgeguckt, 0xC3 ist wirklich ret, aber da der compiler ein call %eax macht, liegt nahe, dass dies ein far call ist (schau mal nach, dass müsste dann ein FF D0 (musste das jez doch glatt ma durch nasm jagen :)).
Daher solltest du es mal mit nem far ret (0xCB) versuchen. Das würde auch das Problem erklären. Das ist das bekannte Prob, dass das OS meckert wenn der Stack nacher anders ist als vorher.
Und das wirkt sich natürlich dann erst nach dem beenden deines progs aus.mfg
-bg-
-
Nee, das isses auch nicht, obwohl es so schön logisch klingt
Da wird das prog dann gar nicht erst beendet.. da geht er gleich in der funktion flöten
-
Original erstellt von -bg-:
so, hab mal nachgeguckt, 0xC3 ist wirklich ret, aber da der compiler ein call %eax macht, liegt nahe, dass dies ein far call ist (schau mal nach, dass müsste dann ein FF D0 (musste das jez doch glatt ma durch nasm jagen :)).Warum soll call %eax ein far-call sein? Ist doch kein Fremdes segment drin verwickelt, FF D0 ist auch n u ein near call, einen Far-call hast du erst, wenn ein anderes Segment involviert ist. So stüruzt das Programm natürlich beim far ret ab weil es ein illegales segment versucht zu erreichen
-
Original erstellt von Chickenman:
**```
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"
};Disassembliert:
push ebp
mov esp, ebp
sub esp, 16
mov edx, 0x0000000d
mov ecx, 0x08049415
mov ebx, 0x00000001
mov eax, 0x00000004
int 0x80
retWolltest du nicht vielelihct den Stack wieder herrichten per
mov esp, ebp
?[ Dieser Beitrag wurde am 17.11.2002 um 14:57 Uhr von TriPhoenix editiert. ]
-
@Tri: und das jetzt noch mal für noch nicht ganz so gut asm könner?
Versteh nicht ganz was du mir damit sagen willst
-
Du musst den Stack am Ende der Funktion wieder so machen, wie er vorher war. Du lässt ihn aber einfach so wie er ist, und das geht garantiert schief.
-
Um CD9000s post mal zu verdeutlichen:
Stack bevor die FUnktion aufgerufen wird:
...
------------------
Rücksprungaddresse am Ende von main
------------------
alter EBP vor main
------------------
Variable Z
------------------Stack nachdem die Funktion aufgerufen wurde (in der Funktion):
...
------------------
Rücksprungaddresse am Ende von main
------------------
alter EBP vor main
------------------
Variable Z
------------------
Rücksprungaddresse von der asm-Funktion
------------------
alter EBP vor der asm-Funktion
------------------Da beginnen die Probleme, der return springt dann nicht zurück an main, sondenr dahin, wo halt EBP drauf gezeigt hat und das geht shconmal schief.
Korrekt wäre mov esp, EBP, damit der Stakc wieder in dem Zustand VOR dewm Aufruf der asm-Funktion ist