[ MiTo @ 24.06.2006. 15:38 ] @
Pozdrav svima,

Ne bih pitao da nisam zaglavio malo, samo malo :) Zaglavio sam na necemu jako jako "jednostavnom".

Evo koda programcica iz tutoriala:
Code:

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:
Code:

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:
Citat:

[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:
Code:

int main() {

    function(1,2,3);
    printf("a\n");
    printf("b\n");
    return 0;
}



i gdb exe daje:

Citat:

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!
[ EArthquake @ 25.06.2006. 10:24 ] @
od tog teksta se mnogo stvari promenilo
gcc danas ubacuje neku vrstu paddinga izmedju baffera ako se ne varam
to si mogao da primetis i ako si probao da exploitas onaj najprostiji primer

main(int argc, char **argv)
{
char buff[5];
strcpy(buff,argv[1]);
}

primetices da moras da overflowas cak 28 bajtova da bi dosao do eip-a


resenje tvog problema je da racunas sve sam uz pomoc gdb-a , gledaj lepo disassembly koda i
videces, definitivno moze da se resi , samo su brojke drugacije , a mene ssad mrzi da gledam da bih ti rekao tacno :)

ae poz
Aca
[ MiTo @ 25.06.2006. 11:10 ] @
EArthquake hvala na odgovoru, smislit cu nesto siguran sam

...

Code:

void overflow(char *buf)
{
        char var[5];
        strcpy(var,buf);
}

int main(int argc,char **argv)
{
        overflow(argv[1]);
        return 0;
}


ok, kad idem sa strcpy prepisem i bp i ip:

Code:


$ ./vuln AAAAAAAAAAAAA  //--> AAAAA (5 za var) AAAA (za bp) AAAA (za ip)

rezultira sa

ebp            0x41414141       0x41414141
esi            0x0      0
edi            0xb7fbecc0       -1208226624
eip            0x41414141       0x41414141



Dakle prepise oba registra, ali svejedno iz toga ne mogu tocno zakljuciti kako pokazivacem dosetati do IP-a, bar nisam uspio.
Nesto mi je tu cudno

[Ovu poruku je menjao MiTo dana 25.06.2006. u 15:45 GMT+1]
[ EArthquake @ 26.06.2006. 11:39 ] @
ne razumem , sta ti sad nije jasno

EIP == extended instruction pointer , ili ti pokazivac na sledecu instrujkciju koja treba da se izvrsi
ako u EIPu imas 0x41414141 to znaci da se sledeca instrukcija koja treba da se izvrsi nalazi na adresi 0x41414141
sto je malo podalje od onoga gde bi trebalo da bude , odnosno na 0x41414141 se ne nalazi nista "pametno" sto bi program mogao da smatra instrukcijom i stoga dobijas segmentation fault

onda moras u EIP da smestis adresu gde se nalaze instrukcije koje zelis da se izvrse , tj adresu tvog shellcode-a



[ MiTo @ 26.06.2006. 12:05 ] @
Pa da, to mi je sve jasno, ali nije mi jasno zasto ne mogu doci pokazivacem na eip?
Strcpy upucuje na odredjenu udaljenost, ali pokazivacem ne mozes doci koristeci tu udaljenost, postoji negdje nekakav padding ili nesto vec.


ps


Code:

void function(int a, int b, int c) {
   char buffer1[5];
   int *ret;

    ret = buffer1 + 13;// string length +1 +ebp
    (*ret) = 0x41414141;
}


Code:

gdb exe
break main
run
stepi
...
...
info stack
x ret


Code:

 Saved registers:
  ebp at 0xbfa7e478, eip at 0xbfa7e47c
(gdb) x ret
0xbfa7e47c:     0x080483dd


Deduciram da kernel (nije grsec) ne da na ovaj nacin minjat IP, strcpy ga vjerojatno prevari jer pocne pisat par blokova dalje.

[Ovu poruku je menjao MiTo dana 27.06.2006. u 16:50 GMT+1]
[ Sarevok @ 21.08.2006. 21:06 ] @
Nisam citao sve sto je gore pisano, ali samo jedno quick pitanje: da li ti je stack executable?
[ EArthquake @ 23.08.2006. 12:38 ] @
ako mislis inace, na pojedinim distribucijama je po default ekzekutabilan , na nekima postoje zastite

a ako mislis u njegobvom slucaju , stvarno ne znam
kod mene na slackware-u nema non executable stacka po defaultu

[ EArthquake @ 04.09.2006. 18:43 ] @
izasao je tekst koji bi trebao da razjasni razlike koje su se javile u novijhim verzijama gcc-a vezane za smashing the stack

tekst mozete naci na http://www.milw0rm.com/papers/82

poz
Aca