确实,这应该在应用程序本身中解决。而且此类应用程序应该是开源的,因此应该选择在应用程序本身中解决问题。发生这种错误的与安全相关的应用程序也可能会犯其他错误,因此我不信任它。
简单插入器
但是您要求的是另一种方式,所以这是一种:
#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
确实如此)或从中读取密码x11-ssh-askpass
。