Ne bih pitao da nisam zaglavio malo, samo malo :) Zaglavio sam na necemu jako jako "jednostavnom".
Evo koda programcica iz tutoriala:
void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
int *ret;
ret = buffer1 + 12;
(*ret) += 8;
}
void main() {
int x;
x = 0;
function(1,2,3);
x = 1;
printf("%d\n",x);
}
i slika stacka bi izgledala ovako:
bottom of top of
memory memory
buffer2 buffer1 sfp ret a b c
<------ [ ][ ][ ][ ][ ][ ][ ]
top of bottom of
stack stack
Ok, koliko sam shvatio, buffer jedan zauzima 8 bajtova (4+1=5, po blokovima od 4 bajta to ide u 2 bloka, dakle 8 bajtova),
sfp (bp) zauzima 4 bajta. Dakle ukupno je to 12 bajtova i stoga stavimo ret=buffer1+12 da dobijemo EIP.
Problem sad nastaje u (*ret)+=8. Mozda moj kalkulator ne valja, ali ja ne vidim kako je on dobio 8 iz ovoga:
[aleph1]$ gdb example3
GDB is free software and you are welcome to distribute copies of it
under certain conditions; type "show copying" to see the conditions.
There is absolutely no warranty for GDB; type "show warranty" for details.
GDB 4.15 (i586-unknown-linux), Copyright 1995 Free Software Foundation, Inc...
(no debugging symbols found)...
(gdb) disassemble main
Dump of assembler code for function main:
0x8000490 <main>: pushl %ebp
0x8000491 <main+1>: movl %esp,%ebp
0x8000493 <main+3>: subl $0x4,%esp
0x8000496 <main+6>: movl $0x0,0xfffffffc(%ebp)
0x800049d <main+13>: pushl $0x3
0x800049f <main+15>: pushl $0x2
0x80004a1 <main+17>: pushl $0x1
0x80004a3 <main+19>: call 0x8000470 <function>
0x80004a8 <main+24>: addl $0xc,%esp
0x80004ab <main+27>: movl $0x1,0xfffffffc(%ebp)
0x80004b2 <main+34>: movl 0xfffffffc(%ebp),%eax
0x80004b5 <main+37>: pushl %eax
0x80004b6 <main+38>: pushl $0x80004f8
0x80004bb <main+43>: call 0x8000378 <printf>
0x80004c0 <main+48>: addl $0x8,%esp
0x80004c3 <main+51>: movl %ebp,%esp
0x80004c5 <main+53>: popl %ebp
0x80004c6 <main+54>: ret
0x80004c7 <main+55>: nop
------------------------------------------------------------------------------
We can see that when calling function() the RET will be 0x8004a8, and we
want to jump past the assignment at 0x80004ab. The next instruction we want
to execute is the at 0x8004b2. A little math tells us the distance is 8
bytes.
Evo kako to izgleda kod mene:
int main() {
function(1,2,3);
printf("a\n");
printf("b\n");
return 0;
}
i gdb exe daje:
Dump of assembler code for function main:
0x080483aa <main+0>: push %ebp
0x080483ab <main+1>: mov %esp,%ebp
0x080483ad <main+3>: sub $0x18,%esp
0x080483b0 <main+6>: and $0xfffffff0,%esp
0x080483b3 <main+9>: mov $0x0,%eax
0x080483b8 <main+14>: add $0xf,%eax
0x080483bb <main+17>: add $0xf,%eax
0x080483be <main+20>: shr $0x4,%eax
0x080483c1 <main+23>: shl $0x4,%eax
0x080483c4 <main+26>: sub %eax,%esp
0x080483c6 <main+28>: movl $0x3,0x8(%esp)
0x080483ce <main+36>: movl $0x2,0x4(%esp)
0x080483d6 <main+44>: movl $0x1,(%esp)
0x080483dd <main+51>: call 0x8048384 <function>
0x080483e2 <main+56>: movl $0x8048551,(%esp)
0x080483e9 <main+63>: call 0x80482b8 <printf@plt>
0x080483ee <main+68>: movl $0x8048554,(%esp)
0x080483f5 <main+75>: call 0x80482b8 <printf@plt>
0x080483fa <main+80>: mov $0x0,%eax
0x080483ff <main+85>: leave
0x08048400 <main+86>: ret
0x08048401 <main+87>: nop
Ako mi netko moze pojasnit ko debilu :) kako se racuna razmak? kalkulator daje 10, tutorial daje 8...a exe daje segmentation fault u svakom slucaju.
Aloha!