在命令行直接輸入 MySQL 密碼(如 mysql -u root -p'password')會導致密碼在進程列表(ps -ef)中明文可見,構成嚴重安全風險。本文介紹一種利用 C 語言覆寫 argv 參數內存,實現運行時隱藏命令行密碼的技術方案,原理同 MySQL 官方客戶端一致。
argv[1] 存儲在進程內存中memset() 將密碼字元逐個覆寫為 'x'(或任意字元)getc(stdin) 阻塞),此時 ps 顯示已被遮蔽#include
#include
#include
#include
int main(int argc, char *argv[]) {
int i = 0;
pid_t mypid = getpid();
// 參數檢查:至少需要程式名 + 1 個參數(密碼)
if (argc == 1) {
return 1; // 異常退出
}
printf("argc = %d and arguments are:\n", argc);
for (i = 0; i < argc; i++) {
printf("%d = %s\n", i, argv[i]);
}
printf("Replacing first argument with x's... Now open another terminal and run: ps p %d\n", (int)mypid);
fflush(stdout); // 清空緩衝區,確保輸出可見
// 核心邏輯:用 'x' 覆蓋 argv[1](密碼)的每個字元
memset(argv[1], 'x', strlen(argv[1]));
// 阻塞等待鍵盤輸入,保持進程存活以便觀察 ps 輸出
getc(stdin);
return 0;
}
# 切換至普通用戶(模擬非 root 環境)
su - dabu
cd ~
touch pwhide.c
# 將上述代碼寫入 pwhide.c
gcc -o hide pwhide.c
ls # 顯示 hide pwhide.c
./hide dabu.info
# 輸出:
# argc = 2 and arguments are:
# 0 = ./hide
# 1 = dabu.info
# Replacing first argument with x's... Now open another terminal and run: ps p 15585
此時程式阻塞於 getc(stdin),**不要關閉終端、不要按鍵**。
# 以 root 或其他用戶登入
ps p 15585 # 使用上一步顯示的 PID
# 輸出:
# PID TTY STAT TIME COMMAND
# 15585 pts/0 S+ 0:00 ./hide xxxxxxxxx # 9 個 'x' 對應 'dabu.info' 9 字元
MySQL 官方客戶端(mysql)採用相同機制:
memset() 覆寫對應 argv 區域ps aux | grep mysql 僅顯示 xxxxxxxx| 平台 | 方案 |
|---|---|
| Linux | 重寫 argv(本文方案) |
| FreeBSD / macOS | setproctitle() 系統調用 |
| Windows | SetConsoleTitle() / 進程參數區塊修改 |