Aku membenturkan kepalaku ke dinding dengan ini.
Dalam proyek saya, ketika saya mengalokasikan memori dengan mmap
pemetaan ( /proc/self/maps
) menunjukkan bahwa itu adalah wilayah yang dapat dibaca dan dieksekusi meskipun saya hanya meminta memori yang dapat dibaca.
Setelah melihat ke dalam strace (yang terlihat bagus) dan debugging lainnya, saya dapat mengidentifikasi satu-satunya hal yang tampaknya menghindari masalah aneh ini: menghapus file assembly dari proyek dan hanya menyisakan C. murni (apa ?!)
Jadi di sini adalah contoh aneh saya, saya mengerjakan Ubunbtu 19.04 dan gcc default.
Jika Anda mengkompilasi target yang dapat dieksekusi dengan file ASM (yang kosong) kemudian mmap
mengembalikan wilayah yang dapat dibaca dan dieksekusi, jika Anda membangun tanpa itu maka berperilaku dengan benar. Lihat output /proc/self/maps
yang telah saya sisipkan dalam contoh saya.
contoh.c
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
int main()
{
void* p;
p = mmap(NULL, 8192,PROT_READ,MAP_ANONYMOUS|MAP_PRIVATE,-1,0);
{
FILE *f;
char line[512], s_search[17];
snprintf(s_search,16,"%lx",(long)p);
f = fopen("/proc/self/maps","r");
while (fgets(line,512,f))
{
if (strstr(line,s_search)) fputs(line,stderr);
}
fclose(f);
}
return 0;
}
example.s : Apakah file kosong!
Keluaran
Dengan ASM termasuk versi
VirtualBox:~/mechanics/build$ gcc example.c example.s -o example && ./example
7f78d6e08000-7f78d6e0a000 r-xp 00000000 00:00 0
Tanpa ASM termasuk versi
VirtualBox:~/mechanics/build$ gcc example.c -o example && ./example
7f1569296000-7f1569298000 r--p 00000000 00:00 0
-Wa,--noexecstack
.Jawaban:
Linux memiliki domain eksekusi yang disebut
READ_IMPLIES_EXEC
, yang menyebabkan semua halaman yang dialokasikan denganPROT_READ
juga diberikanPROT_EXEC
. Program ini akan menunjukkan kepada Anda apakah itu diaktifkan untuk dirinya sendiri:Jika Anda mengompilasinya bersama dengan
.s
file kosong , Anda akan melihat bahwa itu diaktifkan, tetapi tanpa itu, ia akan dinonaktifkan. Nilai awal ini berasal dari meta-informasi ELF dalam biner Anda . Lakukanreadelf -Wl example
. Anda akan melihat baris ini ketika dikompilasi tanpa.s
file kosong :Tapi yang ini saat kamu mengompilasinya:
Catat,
RWE
bukan hanyaRW
. Alasan untuk ini adalah bahwa penghubung mengasumsikan bahwa file rakitan Anda memerlukan read-Implies-exec kecuali itu secara eksplisit mengatakan bahwa mereka tidak, dan jika ada bagian dari program Anda memerlukan read-Implies-exec, maka itu diaktifkan untuk seluruh program Anda . File rakitan yang dikompilasi oleh GCC mengatakan bahwa ia tidak memerlukan ini, dengan baris ini (Anda akan melihat ini jika Anda mengompilasinya-S
):Masukkan baris itu
example.s
, dan itu akan berfungsi untuk memberi tahu linker bahwa itu tidak membutuhkannya juga, dan program Anda kemudian akan berfungsi seperti yang diharapkan.sumber
.o
file! Tapi bagaimanapun, saya rasa ini adalah mekanisme yanggcc -zexecstack
digunakan, dan mengapa itu membuat tidak hanya stack tetapi semuanya dapat dieksekusi.-Wa,--noexecstack
. Saya pikir itu adalah ujung tajam yang sangat jahat. Kehilangan diam-diam dari nx-stack harus menjadi kerentanan keamanan. Orang-orang Binutil harus memperbaikinya..note.GNU-stack,"",@progbits
dijelaskan - saat ini buram, setara dengan "string karakter ajaib ini menyebabkan efek ini", tetapi string tersebut jelas terlihat seperti memiliki semacam semantik.Sebagai alternatif untuk memodifikasi file rakitan Anda dengan varian direktif bagian khusus GNU, Anda dapat menambahkan
-Wa,--noexecstack
ke baris perintah Anda untuk membuat file rakitan. Sebagai contoh, lihat bagaimana saya melakukannya di musl'sconfigure
:https://git.musl-libc.org/cgit/musl/commit/configure?id=adefe830dd376be386df5650a09c313c483adf1a
Saya percaya setidaknya beberapa versi dentang dengan integrated-assembler mungkin mengharuskannya untuk dilewatkan sebagai
--noexecstack
(tanpa-Wa
), jadi skrip configure Anda mungkin harus memeriksa keduanya dan melihat mana yang diterima.Anda juga dapat menggunakan
-Wl,-z,noexecstack
pada waktu tautan (dalamLDFLAGS
) untuk mendapatkan hasil yang sama. Kerugian dari ini adalah tidak membantu jika proyek Anda menghasilkan.a
file perpustakaan statis ( ) untuk digunakan oleh perangkat lunak lain, karena Anda kemudian tidak mengontrol opsi waktu tautan ketika digunakan oleh program lain.sumber