ここで説明したように、Linux はプログラムの引数をプログラムのデータ空間に置き、この領域の先頭へのポインターを保持します。これは ps
で使用されるものです など、プログラムの引数を見つけて表示します。
データはプログラムの空間にあるため、データを操作できます。プログラム自体を変更せずにこれを行うには、シムに main()
をロードする必要があります プログラムの実際のメインの前に呼び出される関数。この shim は、実際の引数を新しいスペースにコピーしてから、元の引数を上書きして ps
null のみが表示されます。
次の C コードはこれを行います。
/* 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);
}
main()
に介入することはできません 、ただし、標準 C ライブラリ関数 __libc_start_main
に介入できます 、それは続けて main を呼び出します。このファイル shim_main.c
をコンパイルします 最初のコメントに記載されているように、示されているように実行します。 printf
を残しました 実際に呼び出されていることを確認します。たとえば、実行
LD_PRELOAD=/tmp/shim_main.so /bin/sleep 100
次に ps
を実行します 空白のコマンドと引数が表示されます。
コマンド引数が表示される可能性がある時間はまだわずかです。これを回避するには、たとえば、shim を変更してファイルからシークレットを読み取り、それをプログラムに渡される引数に追加することができます。
<オール>
問題のアプリケーションのコマンド ライン インターフェイスのドキュメントを参照してください。引数として直接ではなく、ファイルからシークレットを提供するオプションがあるかもしれません.
それが失敗した場合は、シークレットを提供する安全な方法がないという理由で、アプリケーションに対してバグ レポートを提出してください。
特定のニーズに合わせて、meuh の回答のソリューションをいつでも慎重に (!) 適応させることができます。 Stéphane のコメントとそのフォローアップに特に注意してください。
プログラムを機能させるために引数を渡す必要がある場合、 hidepid
を使用できない場合は、何をしてもうまくいきません。
これは bash スクリプトだとおっしゃいましたが、bash はコンパイル済み言語ではないため、ソース コードは既に入手できているはずです。
そうでない場合は、してもよい gdb
を使用してプロセスのコマンドラインを書き換えることができます または類似して argc
で遊んでいます /argv
すでに開始されていますが、
ソースコードを入手するか、ベンダーに相談してコードを変更することをお勧めします。 POSIX オペレーティング システムのコマンド ラインでシークレットを指定することは、安全な操作と互換性がありません。