2012-12-14 15 views
8

मैं अपने खुद के कार्यान्वयन के साथ एक मानक प्रणाली कॉल (जैसे SYS_mkdir) की जगह की जरूरत है।सिस्टम कॉल लिनक्स कर्नेल मॉड्यूल में अवरोधन (कर्नेल 3.5)

जैसा कि मैंने कुछ स्रोतों में पढ़ते हैं, this question Stackoverflow पर सहित, sys_call_table कर्नेल संस्करण 2.6 के बाद से प्रतीक निर्यात नहीं कर रहा है।

मैं निम्नलिखित कोड की कोशिश की:

#include <linux/module.h> 
    #include <linux/kernel.h> 
    #include <linux/unistd.h> 
    #include <asm/syscall.h> 

    int (*orig_mkdir)(const char *path); 

    .... 

    int init_module(void) 
    { 
      orig_mkdir=sys_call_table[__NR_mkdir]; 
      sys_call_table[__NR_mkdir]=own_mkdir; 
      printk("sys_mkdir replaced\n"); 
      return(0); 
    } 

    .... 

दुर्भाग्य से मैं संकलक त्रुटि प्राप्त:

error: assignment of read-only location ‘sys_call_table[83]’ 

मैं कैसे सिस्टम कॉल जगह ले सकता है?

संपादित करें: क्या कर्नेल पैचिंग के बिना कोई समाधान है?

+0

को 'चार *' प्रकार कलाकारों के साथ की कोशिश तो –

+2

आवंटित किया जा सकता है [इस] (http://www.linuxforums.org/forum/kernel/133982-cannot-modify-sys_call_table.html) और [ यह] (http://stackoverflow.com/questions/2103315/linux- कर्नेल- सिस्टम-call-hooking-example) आपके लिए उपयोगी है –

+0

कोई सार्वभौमिक समाधान w/o पैचिंग नहीं है। –

उत्तर

0

सबसे पहले, आप sys_call_table का स्थान निर्धारित करने की जरूरत है। here देखें।

सिर्फ स्थित प्रणाली तालिका में लिखने से पहले, आप अपनी स्मृति पृष्ठों लिखने योग्य बनाने के लिए किया है। उस चेक के लिए here और यदि यह काम नहीं करता है, तो this आज़माएं।

6

हाँ वहाँ पैच/कर्नेल के पुनर्निर्माण के बिना एक समाधान है। Kprobes आधारभूत संरचना (या सिस्टमटैप) का प्रयोग करें।

यह आपको गिरी के किसी भी समय (रों) में "जांच" (कार्यों) कर देता है, एक कर्नेल मॉड्यूल का उपयोग कर सकेंगे।

sys_call_table को संशोधित करके समान सामान करना अब रोक दिया गया है (यह केवल पढ़ने योग्य है) & को गंदा हैक माना जाता है! Kprobes/Jprobes/आदि ऐसा करने के लिए एक "साफ" तरीका है .. इसके अलावा, कर्नेल स्रोत पेड़ में प्रदत्त प्रलेखन और samples उत्कृष्ट है (कर्नेल src tree- Documentation/kprobes.txt के अंतर्गत देखें)।

+1

kprobes/systemtap आपको * सिस्टम कॉल हैंडलर * को प्रतिस्थापित नहीं करने देगा, लेकिन इसे पूरक/इसे पूर्ववत कर सकता है। – fche

+0

अरे, kprobes पैचिंग का उपयोग करता है :) –

+0

@fche: हाँ, मैं सहमत हूं। मुद्दा यह था कि प्रभाव समान है .. @ IlyaMatveychikov: AFAIK, नहीं, kprobes एक कर्नेल सुविधा है; आपको किसी भी पैच को लागू करने की आवश्यकता नहीं है। इसके अलावा, अधिकांश distros kprobes सक्षम है .. – kaiwan

7

यह मेरे लिए काम करता है।

Linux Kernel: System call hooking example और https://bbs.archlinux.org/viewtopic.php?id=139406

asmlinkage long (*ref_sys_open)(const char __user *filename, int flags, umode_t mode); 
asmlinkage long new_sys_open(const char __user *filename, int flags, umode_t mode) 
{ 
    return ref_sys_open(filename, flags, mode); 
} 

static unsigned long **aquire_sys_call_table(void) 
{ 
    unsigned long int offset = PAGE_OFFSET; 
    unsigned long **sct; 

    while (offset < ULLONG_MAX) { 
    sct = (unsigned long **)offset; 

    if (sct[__NR_close] == (unsigned long *) sys_close) 
     return sct; 

    offset += sizeof(void *); 
    } 
    print("Getting syscall table failed. :("); 
    return NULL; 
} 


// Crazy copypasted asm stuff. Could use linux function as well... 
// but this works and will work in the future they say. 
static void disable_page_protection(void) 
{ 
    unsigned long value; 
    asm volatile("mov %%cr0, %0" : "=r" (value)); 

    if(!(value & 0x00010000)) 
    return; 

    asm volatile("mov %0, %%cr0" : : "r" (value & ~0x00010000)); 
} 

static void enable_page_protection(void) 
{ 
    unsigned long value; 
    asm volatile("mov %%cr0, %0" : "=r" (value)); 

    if((value & 0x00010000)) 
    return; 

    asm volatile("mov %0, %%cr0" : : "r" (value | 0x00010000)); 
} 


static int __init rootkit_start(void) 
{ 

    //Hide me 

    print("loaded"); 

    if(!(sys_call_table = aquire_sys_call_table())) 
    return -1; 

    disable_page_protection(); 
    { 
    ref_sys_open = (void *)sys_call_table[__NR_open]; 
    sys_call_table[__NR_open] = (unsigned long *)new_sys_open; 
    } 
    enable_page_protection(); 
    return 0; 
} 

static void __exit rootkit_end(void) 
{ 
    print("exiting"); 

    if(!sys_call_table) { 
    return; 
    } 

    disable_page_protection(); 
    { 
    sys_call_table[__NR_open] = (unsigned long *)ref_sys_open; 
    } 
    enable_page_protection(); 
} 
0

उपयोग LSM infrustructure देखें। LSM पर

देखो path_mkdir या जानकारी के लिए inode_mkdir हुक। एक प्रश्न जिसे हल करने की आवश्यकता है, वह है कि सिस्टम अपने स्वयं के एलएसएम मॉड्यूल को कैसे पंजीकृत करें, जबकि सिस्टम इसे स्पष्ट रूप से अनुमति नहीं देता है। तथ्य यह है कि sys_call_table केवल पढ़ने के लिए की वजह से

How can I implement my own hook function with LSM?

0

समस्या के कारण होता है: विवरण के लिए यहां उत्तर देखें। Sys_call_table में हेरफेर करने से पहले, त्रुटि से बचने के लिए, आपको इसे लिखने योग्य भी बनाना होगा। कर्नेल इसे प्राप्त करने के लिए एक समारोह प्रदान करता है। और वह कार्य set_mem_rw() के रूप में दिया गया है।

बस sys_call_table

set_mem_rw((long unsigned int)sys_call_table,1); 

जोड़ तोड़ कर्नेल मॉड्यूल के निकास समारोह में पहले नीचे दिए गए कोड स्निपेट जोड़ने के लिए, मत भूलना कृपया वापस sys_call_table वापस लौटने को पढ़ने के लिए only.It नीचे के रूप में प्राप्त किया जा सकता ।

set_mem_ro((long unsigned int)sys_call_table,1);  
संबंधित मुद्दे