स्रोत कोड के बिना प्रोग्राम के लिए तर्क छिपाएं


15

मुझे अपने द्वारा चलाए जा रहे कार्यक्रम के लिए कुछ संवेदनशील तर्क छिपाने की आवश्यकता है, लेकिन मेरे पास स्रोत कोड तक पहुंच नहीं है। मैं इसे एक साझा सर्वर पर भी चला रहा हूं, hidepidइसलिए मैं कुछ उपयोग नहीं कर सकता क्योंकि मेरे पास sudo विशेषाधिकार नहीं हैं।

यहाँ कुछ चीजें हैं जो मैंने कोशिश की हैं:

  • export SECRET=[my arguments], के बाद एक कॉल करने के लिए ./program $SECRET, लेकिन यह मदद करने के लिए प्रतीत नहीं होता है।

  • ./program `cat secret.txt`जहां secret.txtमेरे तर्क शामिल हैं, लेकिन सर्वशक्तिमान psमेरे रहस्यों को सूँघने में सक्षम है।

क्या मेरे तर्कों को छिपाने का कोई और तरीका है जिसमें व्यवस्थापक हस्तक्षेप शामिल नहीं है?


वह विशेष कार्यक्रम क्या है? यदि यह एक सामान्य आदेश है जिसे आपको बताने की आवश्यकता है (और कुछ अन्य दृष्टिकोण भी हो सकते हैं) जिसमें से एक है
बेसिल स्टायरनेविच

14
तो आप समझते हैं कि क्या चल रहा है, जिन चीजों की आपने कोशिश की है, उनके पास काम करने का कोई मौका नहीं है क्योंकि शेल पर्यावरण चर का विस्तार करने और कार्यक्रम को लागू करने से पहले कमांड प्रतिस्थापन करने के लिए जिम्मेदार है । ps"अपने रहस्यों को सूँघने" के लिए कुछ भी जादुई नहीं कर रहा है। वैसे भी, यथोचित-लिखित कार्यक्रमों के बजाय एक निर्दिष्ट फ़ाइल से एक रहस्य पढ़ने के लिए एक कमांड-लाइन विकल्प की पेशकश करनी चाहिए या इसे सीधे तर्क के रूप में लेने के बजाय स्टड से।
jamesdlin

मैं एक निजी कंपनी द्वारा लिखित मौसम अनुकार कार्यक्रम चला रहा हूं। वे अपने स्रोत कोड को साझा नहीं करते हैं, न ही उनके दस्तावेज़ किसी फ़ाइल से एक रहस्य साझा करने का कोई तरीका प्रदान करते हैं। यहां विकल्पों से बाहर हो सकते हैं
एमएस

जवाबों:


25

जैसा कि यहां बताया गया है , लिनक्स प्रोग्राम के डेटा स्पेस में प्रोग्राम की दलीलें रखता है, और इस क्षेत्र की शुरुआत के लिए एक पॉइंटर रखता है। psकार्यक्रम तर्क को खोजने और दिखाने के लिए इसका उपयोग किया जाता है ।

चूंकि डेटा प्रोग्राम के स्पेस में है, इसलिए वह इसमें हेरफेर कर सकता है। कार्यक्रम को बदले बिना ऐसा करने में एक main()फ़ंक्शन के साथ एक शिम लोड करना शामिल है जिसे कार्यक्रम के वास्तविक मुख्य से पहले बुलाया जाएगा। यह शिम असली तर्कों को एक नए स्थान पर कॉपी कर सकता है, फिर मूल तर्कों को अधिलेखित कर सकता है ताकि psबस nuls दिखाई देगा।

निम्नलिखित C कोड ऐसा करता है।

/* /unix//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(), लेकिन आप मानक सी लाइब्रेरी फ़ंक्शन पर हस्तक्षेप कर सकते हैं __libc_start_main, जो कि मुख्य कॉल पर जाता है। shim_main.cप्रारंभ में टिप्पणी के रूप में इस फ़ाइल को संकलित करें , और दिखाए अनुसार चलाएं। मैंने printfकोड में एक छोड़ दिया है ताकि आप जांच सकें कि यह वास्तव में कहा जा रहा है। उदाहरण के लिए, भागो

LD_PRELOAD=/tmp/shim_main.so /bin/sleep 100

फिर एक करें psऔर आप एक खाली कमांड देखेंगे और दिखाया जा रहा है।

अभी भी कुछ समय है जब कमांड आर्ग दिखाई दे सकता है। इससे बचने के लिए, आप उदाहरण के लिए, एक फ़ाइल से अपने रहस्य को पढ़ने के लिए शिम को बदल सकते हैं और इसे कार्यक्रम में पारित होने वाले आर्ग में जोड़ सकते हैं।


12
लेकिन अभी भी एक छोटी खिड़की /proc/pid/cmdlineहोगी जिसके दौरान रहस्य दिखाएगा (जैसा कि जब curlवह पासवर्ड को छिपाने की कोशिश करता है तो उसे कमांड लाइन पर दिया जाता है)। जब आप LD_PRELOAD का उपयोग कर रहे हैं, तो आप मुख्य लपेट सकते हैं ताकि गुप्त पर्यावरण से उस argv तक कॉपी हो जाए जो मुख्य प्राप्त करता है। जैसे कॉल करें LD_PRELOAD=x SECRET=y cmdजहां आप होने के main()साथ कॉल करते हैंargv[][argv[0], getenv("SECRET")]
स्टीफन चेज़ेलस

जैसा कि यह दृश्य है, आप किसी रहस्य को छिपाने के लिए पर्यावरण का उपयोग नहीं कर सकते /proc/pid/environ। यह आर्गन के समान ही ओवरराइट हो सकता है, लेकिन यह उसी विंडो को छोड़ देता है।
17

11
/proc/pid/cmdlineसार्वजनिक है, /proc/pid/environनहीं है। कुछ प्रणालियाँ थीं जहाँ ps(वहाँ एक निष्पादनीय निष्पादन योग्य) ने किसी भी प्रक्रिया के ज्ञानकोश को उजागर किया, लेकिन मुझे नहीं लगता कि आप किसी भी समय आएंगे। पर्यावरण को आमतौर पर पर्याप्त सुरक्षित माना जाता है । एक ही यूरोप के साथ प्रक्रियाओं से prying करने के लिए सुरक्षित नहीं है, लेकिन वे अक्सर वैसे ही यूरोप द्वारा प्रक्रियाओं की मेमोरी पढ़ सकते हैं, इसलिए इसके बारे में आप बहुत कुछ नहीं कर सकते हैं।
स्टीफन चेजलस

4
@ स्टीफनचेज़ेलस: यदि कोई रहस्यों को पारित करने के लिए पर्यावरण का उपयोग करता है, तो आदर्श रूप से आवरण mainकार्यक्रम की विधि को आगे बढ़ाने वाला आवरण भी बच्चे की प्रक्रियाओं के लिए आकस्मिक रिसाव से बचने के लिए पर्यावरण चर को हटा देता है। वैकल्पिक रूप से रैपर एक फाइल से सभी कमांड-लाइन तर्क पढ़ सकता है ।
डेविड फ़ॉर्स्टर

@DavidFoerster, अच्छी बात है। मैंने अपने उत्तर को अपडेट कर दिया है ताकि इसे ध्यान में रखा जा सके।
स्टीफन चेज़लस

16
  1. विचाराधीन एप्लिकेशन की कमांड लाइन इंटरफ़ेस का प्रलेखन पढ़ें। एक तर्क के बजाय सीधे फ़ाइल से रहस्य की आपूर्ति करने का एक विकल्प हो सकता है।

  2. यदि वह विफल रहता है, तो इस आधार पर एप्लिकेशन के खिलाफ बग रिपोर्ट दर्ज करें कि उसके लिए एक गुप्त आपूर्ति करने का कोई सुरक्षित तरीका नहीं है।

  3. आप हमेशा ध्यान से (!) अपनी विशिष्ट जरूरतों के लिए meuh के उत्तर में समाधान को अनुकूलित कर सकते हैं। स्टीफन की टिप्पणी और उसके अनुसरण पर विशेष ध्यान दें ।


12

यदि आपको इसे काम करने के लिए कार्यक्रम के लिए तर्कों को पारित करने की आवश्यकता है, तो आप भाग्य से बाहर होने जा रहे हैं, भले ही आप क्या करें यदि आप hidepidprocfs पर उपयोग नहीं कर सकते हैं ।

चूंकि आपने उल्लेख किया है कि यह एक बैश स्क्रिप्ट है, इसलिए आपको पहले से ही स्रोत कोड उपलब्ध होना चाहिए, क्योंकि बैश एक संकलित भाषा नहीं है।

उसमें असफल होने पर आप कर सकते हैं का उपयोग कर प्रक्रिया के cmdline पुनर्लेखन करने में सक्षम हो gdbया के साथ प्रयोग करना समान और argc/ argvएक बार यह पहले से ही शुरू कर दिया है, लेकिन:

  1. यह सुरक्षित नहीं है, क्योंकि आप अभी भी उन्हें बदलने से पहले शुरू में अपने कार्यक्रम के तर्कों को उजागर करते हैं
  2. यह बहुत आसान है, भले ही आप इसे काम करने के लिए प्राप्त कर सकें, मैं इस पर भरोसा करने की सिफारिश नहीं करूंगा

मैं वास्तव में सिर्फ सोर्स कोड प्राप्त करने की सलाह दूंगा, या कोड को संशोधित करने के लिए विक्रेता से बात करूंगा। POSIX ऑपरेटिंग सिस्टम में कमांड लाइन पर रहस्यों की आपूर्ति सुरक्षित संचालन के साथ असंगत है।


11

जब कोई प्रक्रिया एक कमांड ( execve()सिस्टम कॉल के माध्यम से ) निष्पादित करती है , तो इसकी मेमोरी मिटा दी जाती है। निष्पादन के दौरान कुछ जानकारी पारित करने के लिए, execve()सिस्टम कॉल उसके लिए दो तर्क लेता है: ए argv[]और envp[]सरणियाँ।

वे तार के दो सरणियाँ हैं:

  • argv[] तर्क होते हैं
  • envp[]पर्यावरण चर परिभाषाओं में शामिल है var=valueप्रारूप में तार (सम्मेलन द्वारा)।

जब तुम करोगे:

export SECRET=value; cmd "$SECRET"

(यहां पैरामीटर विस्तार के आसपास लापता उद्धरण जोड़े गए)।

आप को क्रियान्वित कर रहे हैं cmdगुप्त के साथ ( value) में दोनों पारित कर दिया argv[]और envp[]argv[]होगा ["cmd", "value"]और envp[]कुछ ऐसा होगा [..., "PATH=/bin:...", "HOME=...", ..., "SECRET=value", "TERM=xterm", ...]। जैसा कि उस पर्यावरण चर से रहस्य के मूल्य को प्राप्त करने के लिए cmdकोई भी getenv("SECRET")या समकक्ष नहीं कर रहा है SECRET, इसे पर्यावरण में डालना उपयोगी नहीं है।

argv[]जनता का ज्ञान है। यह आउटपुट में दिखाता है psenvp[]आजकल नहीं है। लिनक्स पर, यह दिखाता है /proc/pid/environ। यह ps ewwwBSDs (और psलिनक्स पर procps- एनजी के साथ ) के आउटपुट में दिखाता है , लेकिन केवल एक ही प्रभावी यूआईडी (और सेतु / सेटगाइड निष्पादन योग्य के लिए अधिक प्रतिबंधों के साथ) चलने वाली प्रक्रियाओं के लिए। यह कुछ ऑडिट लॉग में दिखा सकता है, लेकिन उन ऑडिट लॉग को केवल प्रशासकों द्वारा ही एक्सेस किया जाना चाहिए।

संक्षेप में, एक निष्पादन योग्य को पारित किए जाने वाले ई-मेल का मतलब निजी या कम से कम निजी के रूप में एक प्रक्रिया की आंतरिक मेमोरी के रूप में होता है (जो कुछ परिस्थितियों में सही विशेषाधिकार के साथ एक अन्य प्रक्रिया भी उदाहरण के लिए डीबगर के साथ उपयोग कर सकती है और कर सकती है भी डिस्क के लिए फेंक दिया)।

चूंकि argv[]सार्वजनिक ज्ञान है, एक कमांड जो डेटा की अपेक्षा करता है कि इसकी कमांड लाइन पर गुप्त होने का मतलब है डिजाइन द्वारा टूट गया है।

आमतौर पर, ऐसे कमांड जिन्हें गुप्त रखने की आवश्यकता होती है, आपको ऐसा करने के लिए एक अन्य इंटरफ़ेस प्रदान करता है, जैसे पर्यावरण चर के माध्यम से। उदाहरण के लिए:

IPMI_PASSWORD=secret ipmitool -I lan -U admin...

या स्टडिन की तरह एक समर्पित फ़ाइल डिस्क्रिप्टर के माध्यम से:

echo secret | openssl rsa -passin stdin ...

(बनाया echoजा रहा है, यह के उत्पादन में नहीं दिखा ps)

या एक फ़ाइल, जैसे .netrcके लिए ftpऔर कुछ अन्य आदेशों या

mysql --defaults-extra-file=/some/file/with/password ....

कुछ एप्लिकेशन जैसे curl(और यह @meuh द्वारा यहां भी लिया गया दृष्टिकोण है ) पासवर्ड को छिपाने के लिए उन्हें argv[]prying आँखों से प्राप्त करने की कोशिश करते हैं (कुछ सिस्टम स्मृति के उस हिस्से को अधिलेखित करके जहां argv[]तार संग्रहीत किए गए थे)। लेकिन यह वास्तव में मदद नहीं कर रहा है और सुरक्षा का झूठा वादा करता है। यह execve()ओवरराइटिंग के बीच एक खिड़की छोड़ देता है जहां psअभी भी रहस्य दिखाई देगा।

उदाहरण के लिए, यदि एक हमलावर जानता है कि आप एक स्क्रिप्ट कर रहे हैं curl -u user:somesecret https://...(उदाहरण के लिए एक क्रॉन जॉब में), तो उसे बस इतना करना होगा कि कैश से बेदखल कर दिया जाए (कई) पुस्तकालयों का curlउपयोग करता है (उदाहरण के लिए sh -c 'a=a;while :; do a=$a$a;done') के रूप में अपने स्टार्टअप को धीमा करने के लिए, और यहां तक ​​कि बहुत ही अक्षम until grep 'curl.*[-]u' /proc/*/cmdline; do :; doneकरने के लिए मेरे परीक्षणों में उस पासवर्ड को पकड़ने के लिए पर्याप्त है।

यदि तर्क ही एकमात्र तरीका है, तो आप गुप्त को आदेशों को पारित कर सकते हैं, फिर भी कुछ चीजें हो सकती हैं जिन्हें आप आज़मा सकते हैं।

कुछ प्रणालियों पर, लिनक्स के पुराने संस्करणों सहित, केवल पहले कुछ बाइट्स (लिनक्स 4.1 पर 4096 और उससे पहले) के तार को argv[]बुझाया जा सकता है।

वहाँ, आप कर सकते हैं:

(exec -a "$(printf %-4096s cmd)" cmd "$secret")

और यह रहस्य छिपा होगा क्योंकि यह पहले 4096 बाइट्स है। अब जिन लोगों ने उस पद्धति का उपयोग किया है, उन्हें अब लिनक्स पर पछतावा करना चाहिए क्योंकि 4.2 के बाद अब args की सूची को काट नहीं सकता है /proc/pid/cmdline। यह भी ध्यान दें कि ऐसा नहीं है क्योंकि psकमांड लाइन के बहुत से बाइट्स से अधिक नहीं दिखाई देंगे (जैसे FreeBSD पर जहां यह 2048 तक सीमित लगता है) जो कि psअधिक प्राप्त करने के लिए एक ही एपीआई का उपयोग नहीं कर सकता है । हालांकि यह दृष्टिकोण उन प्रणालियों पर मान्य psहै, जहां एक नियमित उपयोगकर्ता के लिए एकमात्र तरीका है उस जानकारी को पुनः प्राप्त करना (जैसे कि जब एपीआई विशेषाधिकार प्राप्त होता है और psइसका उपयोग करने के लिए सेटगिड या सेतु होता है), लेकिन अभी भी संभावित रूप से भविष्य के सबूत नहीं हैं।

एक और दृष्टिकोण के लिए होगा नहीं में गुप्त पारित argv[]लेकिन प्रोग्राम (का उपयोग करते हुए इंजेक्षन कोड gdbया एक $LD_PRELOADहैक) से पहले अपने main()शुरू कर दिया जाता है कि आवेषण में गुप्त argv[]से प्राप्त execve()

साथ LD_PRELOAD, के लिए गैर setuid / setgid एक जीएनयू सिस्टम पर गतिशील रूप से जुड़ा हुआ निष्पादनयोग्य:

/* 
 * replace ***** with secret read from fd 9
 * gcc -Wall -fpic -shared -o inject_secret.so inject_secret.c -ldl 
 * LD_PRELOAD=/.../inject_secret.so cmd -p '*****' 9<<< secret
 */
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>

#define PLACEHOLDER "*****"
static char secret[1024];

int __libc_start_main(int (*main) (int, char**, char**),
                      int argc,
                      char **argv,
                      void (*init) (void),
                      void (*fini)(void),
                      void (*rtld_fini)(void),
                      void (*stack_end)){
    static int (*real_libc_start_main)() = NULL;
    int n;

    if (!real_libc_start_main) {
        real_libc_start_main = dlsym(RTLD_NEXT, "__libc_start_main");
        if (!real_libc_start_main) abort();
    }

    n = read(9, secret, sizeof(secret));
    if (n > 0) {
      int i;

      if (secret[n - 1] == '\n') secret[--n] = '\0'; 
      for (i = 1; i < argc; i++)
        if (strcmp(argv[i], PLACEHOLDER) == 0)
          argv[i] = secret;
    }

    return real_libc_start_main(main, argc, argv, init, fini,
                                rtld_fini, stack_end);
}

फिर:

$ gcc -Wall -fpic -shared -o inject_secret.so inject_secret.c -ldl
$ LD_PRELOAD=$PWD/inject_secret.so  ps '*****' 9<<< "-opid,args"
  PID COMMAND
 7659 /bin/zsh
 8828 ps *****

किसी भी बिंदु psपर ps -opid,argsवहाँ नहीं दिखाया गया है ( -opid,argsइस उदाहरण में रहस्य होने के नाते)। ध्यान दें कि हम पॉइंटर्स के argv[]सरणी के तत्वों को प्रतिस्थापित कर रहे हैं , न कि उन पॉइंटर्स द्वारा बताए गए स्ट्रिंग्स को ओवरराइड करने के कारण जो हमारे संशोधनों के आउटपुट में नहीं दिखते हैं ।ps

साथ gdb, अभी भी गैर-setuid / setgid गतिशील रूप से जुड़े हुए निष्पादनयोग्य और जीएनयू सिस्टम पर:

tmp=$(mktemp) && cat << EOF > "$tmp" &&
break __libc_start_main
commands 1
set argv[1]="-opid,args"
continue
end
run
EOF

gdb -n --batch-silent --return-child-result -x "$tmp" --args ps '*****'
rm -f -- "$tmp"

फिर भी gdb, एक गैर-जीएनयू विशिष्ट दृष्टिकोण जो निष्पादन योग्य गतिशील रूप से जुड़े होने या डिबग प्रतीकों पर भरोसा नहीं करता है और कम से कम लिनक्स पर निष्पादन योग्य किसी भी ईएलएफ के लिए काम करना चाहिए:

#! /bin/sh -
# gdb+sh polyglot script to replace "*****" arguments with the content
# of the SECRET environment variable *after* execve and before calling
# the executable's main() function.
#
# Usage: SECRET=somesecret cmd --password '*****'

if ':' - ':'
then
  # running in sh
  # retrieve the start address for the executable
  start=$(
    LC_ALL=C objdump -f -- "$(command -v -- "${1?}")" |
    sed -n 's/^start address //p'
  )
  [ -n "$start" ] || exit
  # re-exec ourself with gdb.
  exec gdb -n --batch-silent --return-child-result -iex "set \$start = $start" -x "$0" --args "$@"
  exit 1
fi
end
# running in gdb
break *$start
commands 1
  # The stack on startup contains:
  # argc argv[0]... argv[argc-1] 0 envp[0] envp[1]... 0 argv[] and envp[] strings
  set $argc = *((int*)$sp)
  set $argv = &((char**)$sp)[1]
  set $envp = &($argv[$argc+1])
  set $i = 0
  while $envp[$i]
    # look for an envp[] string starting with "SECRET=". We can't use strcmp()
    # here as there's no guarantee that the debugged executable has such
    # a function
    set $e = $envp[$i]
    if $e[0] == 'S' && \
       $e[1] == 'E' && \
       $e[2] == 'C' && \
       $e[3] == 'R' && \
       $e[4] == 'E' && \
       $e[5] == 'T' && \
       $e[6] == '='
      set $secret = &($e[7])
      # replace SECRET=xxx<NUL> with SECRE=<NUL>
      set $e[5] = '='
      set $e[6] = '\0'
      # not calling loop_break as that causes a SEGV with my version of gdb
    end
    set $i = $i + 1
  end
  if $secret
    # now looking for argv[] strings being "*****" and replace them with
    # the secret identified earlier
    set $i = 0
    while $i < $argc
      set $a = $argv[$i]
      if $a[0] == '*' && \
       $a[1] == '*' && \
       $a[2] == '*' && \
       $a[3] == '*' && \
       $a[4] == '*' && \
       $a[5] == '\0'
        set $argv[$i] = $secret
      end
      set $i = $i + 1
    end
  end
  # using "continue" as "detach" causes a SEGV with my version of gdb.
  continue
end
run

सांख्यिकीय रूप से जुड़े निष्पादन योग्य के साथ परीक्षण:

$ SECRET=/proc/self/cmdline ./replace_secret busybox cat '*****' | tr '\0' '\n'
/bin/busybox
cat
*****

जब निष्पादन योग्य स्थिर हो सकता है, तो हमारे पास गुप्त स्टोर करने के लिए मेमोरी आवंटित करने का एक विश्वसनीय तरीका नहीं है, इसलिए हमें कहीं और से रहस्य प्राप्त करना होगा जो पहले से ही प्रक्रिया मेमोरी में है। यही कारण है कि यहाँ environ स्पष्ट विकल्प है। यदि प्रक्रिया किसी कारण से अपने वातावरण को डंप करने या अविशिष्ट अनुप्रयोगों को निष्पादित करने का निर्णय लेती है, तो हम इसे लीक करने से बचने के SECRETलिए (इसे बदलकर SECRE=) प्रक्रिया में छिपाते हैं ।

यही कारण है कि यह भी सोलारिस 11 (बशर्ते gdb पर काम करता है और GNU binutils स्थापित कर रहे हैं (आप नाम बदलना पड़ सकता है objdumpकरने के लिए gobjdump)।

FreeBSD पर (कम से कम x86_64, मुझे यकीन नहीं है कि उन पहले 24 बाइट्स (जो 16 हो जाते हैं जब gdb (8.0.1) इंटरेक्टिव होता है, यह सुझाव देना कि स्टैक पर) वहाँ gdb में बग हो सकता है), argcऔर argvपरिभाषाओं को बदलें साथ में:

set $argc = *((int*)($sp + 24))
set $argv = &((char**)$sp)[4]

(आपको gdbपैकेज / पोर्ट को संस्करण के रूप में स्थापित करने की आवश्यकता हो सकती है जो अन्यथा सिस्टम के साथ आता है प्राचीन है)।


पुनः (यहां पैरामीटर विस्तार के आसपास गुम उद्धरण जोड़े गए): उद्धरणों का उपयोग न करने में क्या गलत है? क्या वास्तव में अंतर है?
युकशिमा हक्साय

@yukashimahuksay, उदाहरण के लिए bash / POSIX गोले और वहाँ से जुड़े प्रश्नों में एक चर को भूलने के लिए सुरक्षा निहितार्थ देखें ।
स्टीफन चेज़लस

3

आप क्या कर सकते हैं

 export SECRET=somesecretstuff

फिर, यह मानते हुए कि आप अपने ./programC में लिख रहे हैं (या कोई और करता है, और आपके लिए इसे बदल सकता है या सुधार सकता है), उस प्रोग्राम में getenv (3) का उपयोग करें , शायद

char* secret= getenv("SECRET");

और export आप के बाद बस ./programएक ही खोल में चलाते हैं । या पर्यावरण चर नाम इसे पारित किया जा सकता है ( ./program --secret-var=SECRETआदि चलकर ...)

psअपने रहस्य के बारे में नहीं बताएगा, लेकिन खरीद (5) अभी भी बहुत सारी जानकारी दे सकती है (कम से कम उसी उपयोगकर्ता की अन्य प्रक्रियाओं के लिए)।

कार्यक्रम के तर्कों को पारित करने के बेहतर तरीके को डिजाइन करने में सहायता के लिए इसे भी देखें ।

ग्लोबिंग और शेल की भूमिका के बारे में बेहतर स्पष्टीकरण के लिए इस उत्तर को देखें ।

शायद आपके programपास कुछ अन्य तरीके हैं डेटा प्राप्त करने के लिए (या अंतर-प्रक्रिया संचार का अधिक बुद्धिमानी से उपयोग करें) सादे कार्यक्रम के तर्क से (यह निश्चित रूप से चाहिए, अगर यह संवेदनशील जानकारी को संसाधित करने का इरादा है)। इसका प्रलेखन पढ़ें। या शायद आप उस प्रोग्राम का दुरुपयोग कर रहे हैं (जिसका उद्देश्य गुप्त डेटा को संसाधित करना नहीं है)।

गुप्त डेटा छिपाना वास्तव में मुश्किल है। यह कार्यक्रम तर्क के माध्यम से पारित करने के लिए पर्याप्त नहीं है।


5
यह सवाल से बहुत स्पष्ट है कि वह करता भी नहीं स्रोत कोड के लिए ./programहै, तो क्या यह उत्तर की पहली छमाही प्रासंगिक होने के लिए प्रतीत नहीं होता।
पाइप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.