2009-07-30 10 views
10

के रूप में चलाने के बिना किसी प्रोग्राम को अपनी शुरुआत से कैसे ढूंढें, मैं एक ऐसा टूल लिख रहा हूं जो उपयोगकर्ता द्वारा निर्दिष्ट प्रोग्राम का पता लगाने के लिए डीटीआर के माध्यम से कॉल करता है।रूट को

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

अन्य समाधान मुझे पता है की कार्यक्रम अपने आप को शुरू करने के लिए, यह SIGSTOP भेजकर इसे रोक सकते हैं, dtrace -p करने के लिए अपने पीआईडी ​​पारित, तो यह SIGCONT भेजकर इसे जारी है। समस्या यह है कि या तो प्रोग्राम बिना किसी खोज के कुछ सेकंड तक चलता है जबकि डीटीआरएस प्रतीक जानकारी एकत्र करता है या, अगर मैं प्रक्रिया को जारी रखने से पहले कुछ सेकंड तक सोता हूं, तो डीटी्रेस शिकायत करता है कि objc<pid>:<class>:<method>:entry कोई जांच नहीं करता है।

क्या कोई तरीका है कि मैं उपयोगकर्ता के खाते के तहत प्रोग्राम को रूट के रूप में नहीं चला सकता, लेकिन अभी भी डीटीआरएस शुरुआत से इसका पता लगाने में सक्षम है?

उत्तर

2

एक लॉन्चर प्रोग्राम बनाएं जो किसी प्रकार के सिग्नल की प्रतीक्षा करेगा (जरूरी नहीं कि एक शाब्दिक सिग्नल, केवल एक संकेत है कि यह तैयार है), फिर अपना लक्ष्य निष्पादित करें। अब लॉन्चर प्रोग्राम dtrce -p, और एक बार dtrace ऊपर है, लॉन्चर जाने दो।

+1

यहां तक ​​कि बेहतर: इसे सभी में रोल करें। एक पाइप, कांटा बनाएं, बच्चे को पाइप पर प्रतीक्षा करें, dtrace -p CHILD_PID, पाइप को लिखें, बच्चा उठता है और निष्पादन करता है। – bstpierre

+0

वादा करता है। मुझे नहीं पता कि यह काम करेगा, हालांकि: मेरा टूल पायथन में लिखा गया है, और यह कोको कार्यक्रमों का पता लगाने के लिए डिज़ाइन किया गया है। मेरे उपकरण में किसी कोको के बिना, मुझे लगता है कि मुझे अभी भी त्रुटि मिलेगी कि objc प्रदाता कोई जांच नहीं करता है। लेकिन मैं कल कोशिश करूँगा। –

3

यदि दूसरा उत्तर आपके लिए काम नहीं करता है, तो क्या आप प्रोग्राम को जीडीबी में चला सकते हैं, मुख्य (या इससे पहले भी) में तोड़ सकते हैं, पिड प्राप्त कर सकते हैं, और स्क्रिप्ट शुरू कर सकते हैं? मैंने कोशिश की है कि अतीत में और यह काम करने लग रहा था।

5

sudo dtruss -f sudo -u <original username> <command> जैसे कुछ ने मेरे लिए काम किया है, लेकिन मुझे बाद में इसके बारे में बुरा लगा।

मैंने इसके बारे में एक रडार बग दायर किया और इसे # 5108629 के डुप्लिकेट के रूप में बंद कर दिया।

3

खैर, यह थोड़ा पुराना है, लेकिन क्यों :-) नहीं ..

मुझे नहीं लगता कि बस कमांड लाइन से यह करने के लिए एक रास्ता है, लेकिन सुझाव के रूप में, एक सरल लांचर आवेदन, जैसे कि निम्नलिखित, ऐसा करेंगे। मैन्युअल अटैचिंग को निश्चित रूप से कुछ कॉल के साथ libdtrace में बदल दिया जा सकता है।

int main(int argc, char *argv[]) { 
    pid_t pid = fork(); 
    if(pid == 0) { 
     setuid(123); 
     seteuid(123); 
     ptrace(PT_TRACE_ME, 0, NULL, 0); 
     execl("/bin/ls", "/bin/ls", NULL); 
    } else if(pid > 0) { 
     int status; 
     wait(&status); 

     printf("Process %d started. Attach now, and click enter.\n", pid); 
     getchar(); 

     ptrace(PT_CONTINUE, pid, (caddr_t) 1, 0); 
    } 

    return 0; 
} 
3

यह स्क्रिप्ट (इस Info.plist के CFBundleExecutable है किसी एप्लिकेशन के लिए) निष्पादन के नाम लेता है आप (आप तो लक्ष्य एप्लिकेशन बाद यह स्क्रिप्ट चल रहा है शुरू कर सकते हैं) एक पैरामीटर के रूप DTrace लिए निगरानी करना चाहते हैं :

string gTarget;  /* the name of the target executable */ 

dtrace:::BEGIN 
{ 
    gTarget = $$1; /* get the target execname from 1st DTrace parameter */ 

    /* 
    * Note: DTrace's execname is limited to 15 characters so if $$1 has more 
    * than 15 characters the simple string comparison "($$1 == execname)" 
    * will fail. We work around this by copying the parameter passed in $$1 
    * to gTarget and truncating that to 15 characters. 
    */ 

    gTarget[15] = 0;  /* truncate to 15 bytes */ 
    gTargetPID = -1;  /* invalidate target pid */ 
} 

/* 
* capture target launch (success) 
*/ 
proc:::exec-success 
/
    gTarget == execname 
/
{ 
    gTargetPID = pid; 
} 

/* 
* detect when our target exits 
*/ 
syscall::*exit:entry 
/
    pid == gTargetPID 
/
{ 
    gTargetPID = -1;  /* invalidate target pid */ 
} 

/* 
* capture open arguments 
*/ 
syscall::open*:entry 
/
    ((pid == gTargetPID) || progenyof(gTargetPID)) 
/
{ 
    self->arg0 = arg0; 
    self->arg1 = arg1; 
} 

/* 
* track opens 
*/ 
syscall::open*:return 
/
    ((pid == gTargetPID) || progenyof(gTargetPID)) 
/
{ 
    this->op_kind = ((self->arg1 & O_ACCMODE) == O_RDONLY) ? "READ" : "WRITE"; 
    this->path0 = self->arg0 ? copyinstr(self->arg0) : "<nil>"; 

    printf("open for %s: <%s> #%d", 
     this->op_kind, 
     this->path0, 
     arg0); 
} 
+0

यह बहुत अच्छा है, सिवाय इसके कि जब इस dtrace को करने से कोई भी पिड प्रदाता ट्रेस पॉइंट नहीं मिलता है। उदाहरण के लिए, मुझे एक त्रुटि मिलती है: "जांच विवरण पिड * :: confstr: वापसी किसी भी जांच से मेल नहीं खाती" – Droopycom

1

dtruss यह (https://stackoverflow.com/a/11706251/970301 पर @ kenorb के जवाब के बाद के चरण के लिए ऋण) प्रारंभ किए बिना, -n विकल्प जहां प्रक्रिया आप पता लगाने के लिए चाहते हैं उसका नाम निर्दिष्ट कर सकते हैं है। तो निम्नलिखित की तरह कुछ यह करना चाहिए:

sudo dtruss -n "$program" 
$program 
0

पर संबंधित question "? गैर-रूट विशेषाधिकार के साथ पता लगाया आदेश को चलाने के लिए dtrace मिल कैसे कर सकते हैं" my answer देखें [वैसा]।

अनिवार्य रूप से, आप एक (गैर-रूट) पृष्ठभूमि प्रक्रिया शुरू कर सकते हैं जो डीटीआरएस शुरू करने के लिए 1sec (दौड़ की स्थिति के लिए खेद है) की प्रतीक्षा करता है, और उस प्रक्रिया के पीआईडी ​​को स्नूप करता है।

sudo true && \ 
(sleep 1; cat /etc/hosts) &; \ 
sudo dtrace -n 'syscall:::entry /pid == $1/ {@[probefunc] = count();}' $! \ 
&& kill $! 

लिंक किए गए उत्तर में पूर्ण स्पष्टीकरण।

संबंधित मुद्दे