実際、これはアプリケーション自体で修正する必要があります。そして、そのようなアプリケーションはオープンソースである必要があります。そのため、アプリ自体の問題を修正することはオプションです。この種の間違いを犯すセキュリティ関連のアプリケーションは、他の間違いも犯すかもしれないので、私はそれを信用しません。
シンプルなインターポーザー
しかし、あなたは別の方法を求めていたので、ここに一つあります:
#define _GNU_SOURCE
#include <dlfcn.h>
int __libc_start_main(
int (*main) (int, char * *, char * *),
int argc, char * * ubp_av,
void (*init) (void),
void (*fini) (void),
void (*rtld_fini) (void),
void (* stack_end)
)
{
int (*next)(
int (*main) (int, char * *, char * *),
int argc, char * * ubp_av,
void (*init) (void),
void (*fini) (void),
void (*rtld_fini) (void),
void (* stack_end)
) = dlsym(RTLD_NEXT, "__libc_start_main");
ubp_av[argc - 1] = "secret password";
return next(main, argc, ubp_av, init, fini, rtld_fini, stack_end);
}
これをコンパイルします
gcc -O2 -fPIC -shared -o injectpassword.so injectpassword.c -ldl
次に、プロセスを実行します
LD_PRELOAD=$PWD/injectpassword.so darkcoind masternode start fakepasshrase
インターポーザーライブラリはmain
、アプリケーションの関数が実行される前にこのコードを実行します。mainの呼び出しで、最後のコマンドライン引数を実際のパスワードに置き換えます。/proc/*/cmdline
ただし、印刷されたコマンドライン(したがって、などのツールで表示されるps
)には、まだ偽の引数が含まれています。明らかに、ソースコードとそれからコンパイルするライブラリを自分だけが読めるようにしなければならないので、chmod 0700
ディレクトリで操作するのが最適です。また、パスワードはコマンド呼び出しの一部ではないため、bash履歴も安全です。
より高度なインターポーザー
より複雑な操作を行う場合は__libc_start_main
、ランタイムライブラリが適切に初期化される前に実行されることに注意してください。したがって、絶対に不可欠でない限り、関数呼び出しを避けることをお勧めします。あなたの心のコンテンツに関数を呼び出すことができるようにしたい場合main
は、すべての初期化が完了した後、それが呼び出される直前に必ず呼び出してください。次の例では、コマンドライン引数として渡されたパスワードを非表示にする方法を指摘してくれたGrubermenschに感謝する必要がありましgetpass
た。
#define _GNU_SOURCE
#include <dlfcn.h>
#include <unistd.h>
static int (*real_main) (int, char * *, char * *);
static int my_main(int argc, char * * argv, char * * env) {
char *pass = getpass(argv[argc - 1]);
if (pass == NULL) return 1;
argv[argc - 1] = pass;
return real_main(argc, argv, env);
}
int __libc_start_main(
int (*main) (int, char * *, char * *),
int argc, char * * ubp_av,
void (*init) (void),
void (*fini) (void),
void (*rtld_fini) (void),
void (* stack_end)
)
{
int (*next)(
int (*main) (int, char * *, char * *),
int argc, char * * ubp_av,
void (*init) (void),
void (*fini) (void),
void (*rtld_fini) (void),
void (* stack_end)
) = dlsym(RTLD_NEXT, "__libc_start_main");
real_main = main;
return next(my_main, argc, ubp_av, init, fini, rtld_fini, stack_end);
}
これによりパスワードの入力が求められるため、インターポーザライブラリを秘密にする必要がなくなりました。プレースホルダー引数はパスワードプロンプトとして再利用されるため、次のように呼び出します
LD_PRELOAD=$PWD/injectpassword.so darkcoind masternode start "Password: "
別の方法としては、ファイル記述子(例:gpg --passphrase-fd
doなど)、またはからパスワードを読み取ることができますx11-ssh-askpass
。