Seperti yang dijelaskan di sini, Linux meletakkan argumen program di ruang data program, dan menyimpan pointer ke awal area ini. Inilah yang digunakan oleh ps
dan seterusnya untuk menemukan dan menampilkan argumen program.
Karena data berada di ruang program, ia dapat memanipulasinya. Melakukan hal ini tanpa mengubah program itu sendiri berarti memuat shim dengan main()
fungsi yang akan dipanggil sebelum main sebenarnya dari program. Shim ini dapat menyalin argumen sebenarnya ke ruang baru, lalu menimpa argumen asli sehingga ps
hanya akan melihat nol.
Kode C berikut melakukan ini.
/* https://unix.stackexchange.com/a/403918/119298
* capture calls to a routine and replace with your code
* gcc -Wall -O2 -fpic -shared -ldl -o shim_main.so shim_main.c
* LD_PRELOAD=/.../shim_main.so theprogram theargs...
*/
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <dlfcn.h>
typedef int (*pfi)(int, char **, char **);
static pfi real_main;
/* copy argv to new location */
char **copyargs(int argc, char** argv){
char **newargv = malloc((argc+1)*sizeof(*argv));
char *from,*to;
int i,len;
for(i = 0; i<argc; i++){
from = argv[i];
len = strlen(from)+1;
to = malloc(len);
memcpy(to,from,len);
memset(from,'\0',len); /* zap old argv space */
newargv[i] = to;
argv[i] = 0;
}
newargv[argc] = 0;
return newargv;
}
static int mymain(int argc, char** argv, char** env) {
fprintf(stderr, "main argc %d\n", argc);
return real_main(argc, copyargs(argc,argv), env);
}
int __libc_start_main(pfi main, int argc,
char **ubp_av, void (*init) (void),
void (*fini)(void),
void (*rtld_fini)(void), void (*stack_end)){
static int (*real___libc_start_main)() = NULL;
if (!real___libc_start_main) {
char *error;
real___libc_start_main = dlsym(RTLD_NEXT, "__libc_start_main");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(1);
}
}
real_main = main;
return real___libc_start_main(mymain, argc, ubp_av, init, fini,
rtld_fini, stack_end);
}
Tidak mungkin mengintervensi main()
, tetapi Anda dapat mengintervensi fungsi pustaka C standar __libc_start_main
, yang kemudian memanggil main. Kompilasi file ini shim_main.c
seperti yang tercantum dalam komentar di awal, dan jalankan seperti yang ditunjukkan. Saya telah meninggalkan printf
dalam kode sehingga Anda memeriksa apakah itu benar-benar dipanggil. Misalnya, jalankan
LD_PRELOAD=/tmp/shim_main.so /bin/sleep 100
lalu lakukan ps
dan Anda akan melihat perintah kosong dan argumen ditampilkan.
Masih ada sedikit waktu agar perintah args dapat terlihat. Untuk menghindarinya, Anda dapat, misalnya, mengubah shim untuk membaca rahasia Anda dari file dan menambahkannya ke argumen yang diteruskan ke program.
-
Baca dokumentasi antarmuka baris perintah dari aplikasi yang dimaksud. Mungkin ada opsi untuk memberikan rahasia dari file alih-alih sebagai argumen secara langsung.
-
Jika gagal, laporkan laporan bug terhadap aplikasi dengan alasan tidak ada cara yang aman untuk memberikan rahasianya.
-
Anda selalu dapat dengan hati-hati(!) Menyesuaikan solusi dalam jawaban meuh dengan kebutuhan spesifik Anda. Berikan perhatian khusus pada komentar Stephane dan tindak lanjutnya.
Jika Anda perlu meneruskan argumen ke program untuk membuatnya berfungsi, Anda akan kurang beruntung apa pun yang Anda lakukan jika Anda tidak dapat menggunakan hidepid
pada procfs.
Karena Anda menyebutkan ini adalah skrip bash, Anda seharusnya sudah memiliki kode sumbernya, karena bash bukan bahasa yang dikompilasi.
Jika gagal, Anda dapat dapat menulis ulang cmdline proses menggunakan gdb
atau serupa dan bermain-main dengan argc
/argv
setelah itu sudah dimulai, tetapi:
- Ini tidak aman, karena Anda masih mengekspos argumen program Anda terlebih dahulu sebelum mengubahnya
- Ini cukup meretas, bahkan jika Anda bisa membuatnya berfungsi, saya tidak akan merekomendasikan untuk mengandalkannya
Saya benar-benar hanya merekomendasikan mendapatkan kode sumber, atau berbicara dengan vendor untuk memodifikasi kode. Memberikan rahasia pada baris perintah di sistem operasi POSIX tidak kompatibel dengan operasi aman.