2010-11-12 20 views
10

पर विभाजन दोष मैं स्वयं संशोधित कोड के बारे में एक लेख मिला और कुछ उदाहरण करने की कोशिश की है, लेकिन मैं हमेशा विभाजन दोष मिलता है। जैसा कि मैं समझ सकता हूं, स्मृति अनुमतियों में उल्लंघन है। कोड सेगमेंट (आर) ईएडी/ई (एक्स) ecute है और इसलिए इस गलती के परिणाम लिखने का प्रयास है। क्या रनटाइम पर या पहले मेमोरी अनुमतियों को बदलकर प्रोग्राम का परीक्षण करने का कोई तरीका है? मैं लिनक्स का उपयोग कर रहा हूं और उदाहरण जीएएस असेंबली में लिखा गया है।स्व संशोधित कोड हमेशा लिनक्स

.extern memcpy 
.section .data 
string: 
     .asciz "whatever" 
string_end: 
.section .bss 
     .lcomm buf, string_end-string 
.section .text 
.globl main 
main: 
     call changer 
     mov $string, %edx 
label: 
     push string_end-string 
     push $buf 
     push $string 
     call memcpy 
changer: 
     mov $offset_to_write, %esi 
     mov $label, %edi 
     mov $0xb, %ecx 
loop1: 
     lodsb 
     stosb 
     loop loop1 
     ret 
offset_to_write: 
     push 0 
     call exit 
end: 

इसलिए यहाँ osgx ने सुझाव दिया संशोधन के बाद एक काम कर कोड (वास्तव में अगर आप & लिंक & रन यह दुर्घटनाओं को इकट्ठा लेकिन आप gdb यह करता है का उपयोग करके देखें, तो अपने कोड को संशोधित करता है!) है।

.extern memcpy 
.section .data 
string: 
     .asciz "Giorgos" 
string_end: 
.section .bss 
     .lcomm buf, string_end-string 
.section .text 
.globl main 
main: 
     lea (main), %esi    # get the start of memory region to 
             # change its permissions (smc-enabled) 
     andl $0xFFFFF000, %esi   # align to start of a pagesize 
     pushl $7      # permissions==r|w|x 
     pushl $4096     # page size 
     pushl %esi     # computed start address 
     call mprotect 

     call changer     # function that does smc 
     mov  $string, %edx 
label: 
     push string_end-string  # this code will be overridden 
     push $buf     # and never be executed! 
     push $string 
     call memcpy 
changer: 
     mov  $offset_to_write, %esi # simple copy bytes algorithm 
     mov  $label, %edi 
     mov  $0xb, %ecx 
loop1: 
     lodsb 
     stosb 
     loop loop1 
     ret 
offset_to_write:      # these instructions will be 
     push $0      # executed eventually 
     call exit 
end: 
+0

सुनिश्चित नहीं हैं कि यह कैसे लिनक्स पर किया जाता है, लेकिन आप या तो .text अनुभाग के लिए कस्टम झंडे का उपयोग करने के अपने लिंकर हिदायत सकता है, या तो उन्हें स्रोत में निर्दिष्ट करने के लिए सक्षम होने के लिए (.data के लिए डिफ़ॉल्ट आरडब्ल्यू, .text के लिए RX है) – ruslik

+0

@ruslik क्या मैं स्रोत से स्रोत (टेक्स्ट) सेगमेंट को आरडब्ल्यूएक्स का उपयोग करके निर्दिष्ट कर सकता हूं? –

उत्तर

14

आप क्रम में स्मृति पहुँच अनुमतियाँ बदलने के लिए करना चाहिए।

#include <sys/mman.h> 

void *addr = get_address_of_instruction_pointer(); 
int length = 4096; /* size of a page */ 

if (mprotect(addr, length, PROT_READ | PROT_WRITE | PROT_EXEC) == 0) { 
    /* current code page is now writable and code from it is allowed for execution */ 
} 
+0

क्या मैं इस समारोह का असेंबली से उपयोग कर सकता हूं? क्या इसका उपयोग करने के लिए मुझे किसी विशेष विशेषाधिकार की आवश्यकता है? –

+1

हां, आप कर सकते हैं। सी कोड को mprotect से संकलित करने का आसान तरीका है। फ़ाइल (-एस) और mprotect कॉल को अपने कोड पर कॉपी-पेस्ट करें। आपकी प्रक्रिया के स्वामित्व वाली स्मृति के लिए विशेष विशेषाधिकारों की आवश्यकता नहीं है, और कर्नेल – osgx

+0

पर कोई सुपर-सुरक्षा पैच नहीं होना चाहिए, एक अच्छा लेख है (केवल दोष - यह इंटेल सिंटैक्स का उपयोग कर रहा है) http: //asm.sourceforge। नेट/लेख/smc.html – osgx

5

आधुनिक सीपीयू में डीईपी नामक एक सुविधा होती है जो स्टैक पर कोड निष्पादित करने से रोकती है। पहले, यह संभव था; अब, यह नहीं है। बाइनरी को डिफ़ॉल्ट रूप से केवल पढ़ने योग्य मेमोरी में लोड किया जाता है।

इस तरह से, आप अपने बाइनरी के स्थान को निष्पादन योग्य के रूप में चिह्नित करने के लिए mprotect सिस्टम कॉल का उपयोग कर सकते हैं - आपके कोड के रूप में लंबे समय तक डीईपी-संरक्षित नहीं है। तो कोड और ढेर डालने की कोशिश न करें और फिर इसमें कूदें।

+1

'mprotect PROT_READ | PROT_WRITE | PROT_EXEC' को डीईपी अक्षम करना चाहिए। इसके अलावा, इसे केवल एमएस दुनिया – osgx

+0

में डीईपी कहा जाता है लेकिन मैं ढेर में हेरफेर करने की कोशिश नहीं करता, मैं कोड कोड में निर्देशों को बदलने/उत्पन्न करने का प्रयास करता हूं। –

+0

@osgx: _ "यह कहा जाता है डीईपी केवल एमएस दुनिया में" _ [कि बस सच नहीं है] (http://oleb.net/blog/2012/07/ios-hackers-handbook/); डीईपी एक आम शब्द है। –

1

तुम भी लिंकर करने के लिए स्विच -N पास करके पूरे कार्यक्रम के लिए लिखने-संरक्षण निष्क्रिय कर सकते हैं। यदि आप जीसीसी से लिंकर का आह्वान कर रहे हैं, तो Wl,-N पास करें। यदि आप सीधे ld का आह्वान करते हैं, तो -N पास करें।