GNU/Linux >> Linux の 問題 >  >> Linux

ソースコードなしでプログラムする引数を隠す

ここで説明したように、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 オペレーティング システムのコマンド ラインでシークレットを指定することは、安全な操作と互換性がありません。


    Linux
    1. トップ5のソースコードリポジトリ

    2. ソースコードを使用してLinuxにphpMyAdminをインストールする方法

    3. Sudo特権なしでプログラムをローカルにインストールする方法は?

    1. ソースコードからnanoエディターをインストールする方法

    2. VSCodium –トラッカーのないオープンソースのVisual Studio Code

    3. コマンドライン引数を解析する C argc および argv の例

    1. Linux CFS スケジューラ コードはどこにありますか?

    2. ソースコマンドによって呼び出されたスクリプトに引数を渡す方法は?

    3. パフォーマンス コール グラフのソース行番号は?